OmniAICreator/Qiita-1.07M huggingface dataset:
VSCodeのDevcontainerでpython環境構築

VSCodeのDevcontainerアップデートで記載方法が変わっていたので備忘録として、簡単な環境構築をまとめてみました。

# 環境
・Visual Studio Code
・Docker Desktop

VSCodeの拡張機能として以下をインストール
・Dev Containers

# サンプル構成

```
sample/
  ┣ .devcontainer
  ┃   ┗ devcontainer.json
  ┃
  ┗ sample.py
```

```:devcontainer.json
{
    // 接続するコンテナの名前
    "name": "Python 3.11 Dev",

    // 利用するコンテナイメージ
    "image": "python:3.11-slim",

    // コンテナ起動時のホストとの疎通ポート
    "forwardPorts": [
        5000
    ],

    // コンテナビルド時に実行したいコマンド
    "postCreateCommand": "apt-get update && pip3 install requests",

    // 利用したいVSCodeの拡張機能
    "customizations": {
        "vscode": {
            "extensions": [
                "ms-python.python",
                "ms-python.vscode-pylance"
            ]
        }
    }
}
```

```:sample.py
def main():
    print('Hello, World!')

if __name__ == '__main__':
    main()
```

# コンテナ起動
VSCodeのコマンドパレットにて以下コマンドを実行
`Rebuild and Reopen in Container`

ビルド前は開いているフォルダが表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2515654/d41bba78-26fe-7387-af07-aca4168c49a1.png)

ビルド後は接続しているコンテナが表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2515654/158e6da9-8af8-e442-b054-662c2bd892f1.png)

# 動作検証
sample.pyを実行するとコンテナ環境内でPythonコードが実行される
```
root@931306:/workspaces/sample# /usr/local/bin/python /workspaces/sample/sample.py
Hello, World!
root@931306:/workspaces/sample# 
```


# 公式ドキュメント
https://code.visualstudio.com/docs/devcontainers/containers

https://containers.dev/implementors/json_reference/

PythonのDevcontainerテンプレート

https://github.com/devcontainers/templates/tree/main/src/python

# 参考

https://zenn.dev/harurow/articles/c903de5f479a57

https://lethediana.sakura.ne.jp/tech/archives/steps-ja/1511/

https://qiita.com/yoshii0110/items/c480e98cfe981e36dd56

https://qiita.com/Yuki_Oshima/items/d3b52c553387685460b0

https://qiita.com/quotto/items/a672e8b3b45865832577

https://blog.kinto-technologies.com/posts/2022-12-10-VSCodeDevContainer/

https://zenn.dev/hkdord/articles/remote-containers

https://zenn.dev/chizu_puzzle/articles/19e43872705b24

https://blog.hiros-dot.net/?p=10059
【積読】RESTアーキテクチャスタイル後編


:::note
RESTは複数のアーキテクチャスタイルを組み合わせて構築した複合アーキテクチャスタイル。
本記事ではRESTを構成するアーキテクチャスタイルについて記述しています。
:::

---

## 統一インターフェース
統一インターフェースとは、URIで指し示したリソースに対する操作を、統一した限定的なインターフェースで行うアーキテクチャスタイルのこと。

例えば、HTTP1.1ではGETやPOSTなど8個のメソッドだけが定義されており、通常これ以上はメソッドは増えない。メソッドが8個に限定されていて拡張できないのは、一般的なプログラミング言語の感覚から考えると厳しい制約にも感じる。

#### 利点
* インターフェースの柔軟性に制限を加えることで全体のアーキテクチャがシンプルに
* クライアントとサーバの実装の独立性が向上する

現在のWebが多様なクライアントやサーバの実装で構成されているのは、統一インターフェースが一役買っている。統一インターフェースはRESTを最も特徴付けるアーキテクチャスタイル。

## 階層化システム
統一インターフェースの利点の一つに、システム全体が階層化しやすいことが挙げられる。例えばWebサービスでは、サーバとクライアントの間にロードバランサを設置して負荷分散をしたり、プロキシを設置してアクセスを制限したりします。クライアントからするとサーバもプロキシも同じインターフェースで接続できるので、接続先からプロキシに変わったことを意識する必要がない。

これは、サーバやプロキシなどの各コンポーネント間のインターフェースをHTTPで統一しているから実現ができる。

このようにシステムをいくつかの階層に分離するアーキテクチャスタイルのことを階層化システムと呼ぶ。

## コードオンデマンド
コードオンデマンドは、プログラムコードをサーバからダウンロードし、クライアント側でそれを実行するアーキテクチャスタイル。

#### 利点
* クライアントを後から拡張できること

クライアントプログラムにあらかじめ用意した機能ではなく、新しい機能を追加していける。JavaScriptなどをふんだんに使った派手なWebサービスはコードオンデマンドの恩恵を受けている。

#### 欠点
* ネットワーク通信におけるプロトコルの可視性が低下すること

HTTPというアプリケーションプロトコルに従って通信している間は、通信の意味やアクセスするリソースが明白。一方、コードオンデマンドでプログラムをダウンロードし、クライアント側で実行してしまうと、アプリケーションプロトコルの可視性が低下する。



---

参考文献

技術評論者「Webを支える技術」

https://gihyo.jp/book/2010/978-4-7741-4204-3
libwacom で XPPen のペンタブレットを動かす - Ubuntu 22.04 LTS 版

# 概要

Ubuntu 22.04 LTS ではデフォルトの libwacom のバージョンが上がったため、ペンタブドライバ設定の追加が簡単になりました。
また、Wacom以外のペンタブにも積極的に対応するようになったようです。

そこで私が持っているペンタブ「 XPPen Deco mini7 」を使えるようにしてみます。
XPPen では公式でLinux用ドライバを配布していますが、細かい設定変更をしなければこちらでも問題ないです。


# 検証環境

* OS: Ubuntu 22.04 LTS AMD64
* 使用ペンタブ: XPPen Deco mini7

# 設定手順

## 必要なファイルをダウンロードする。

下記のページから「xp-pen-deco-mini7.tablet」をダウンロードします。

https://github.com/linuxwacom/libwacom/tree/master/data

また、その中にある「layouts」フォルダから「xp-pen-deco-mw.svg」もダウンロードします。

## フォルダの作成

ファイルを配置するフォルダを作成します。
```
$ sudo mkdir /etc/libwacom/
$ sudo mkdir /etc/libwacom/layouts/
```

## ファイルの配置

ダウンロードした設定ファイルを配置します。
```
$ sudo cp xp-pen-deco-mini7.tablet /etc/libwacom/
$ sudo cp xp-pen-deco-mw.svg /etc/libwacom/layouts/
```

## 設定の読み込み

最後に libwacom のデータベースをアップデートすれば認識するようになります。

```
$ sudo libwacom-update-db /etc/libwacom
```

これで Ubuntu の設定画面で設定を行えるようになります。
ただペンの設定は、ペンタブ本体をUSB接続後に、一度ペンを本体に触れさせないと出てこないようです。


# その他

もう一つ「 XPPen Deco M (有線接続モデル) 」も持っているのですが、おそらく「xp-pen-deco-mw.tablet」の設定そのままか、少しの変更だけで動くはずです。
後日検証予定。

また24.04LTSぐらいまでには、これらの設定ファイルの入った新しい libwacom がインストールされるようになるはずなので、この作業は不要になると思います。

# 参考URL

https://github.com/linuxwacom/libwacom
NiceGUIでChatGPTのStreamを表示する

## 環境
- python = 3.10
- nicegui = 1.3.13
- openai = 0.28.0

## 実装
![2023-09-23-nicegui.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50391/7208992e-deac-fefe-d139-9f19acd98e50.gif)

NiceGUIで、上記の図のようにChatGPTの出力結果をStreamで表示するには、次のようにします。

```python
from nicegui import ui
import openai

input_text = ui.input(label="入力")
result = ui.label()

async def generate(e):
    input_text = e.sender.value
    completion = await openai.ChatCompletion.acreate(
        model="gpt-3.5-turbo",
        messages=[{"role": "user", "content": input_text}],
        max_tokens=100,
        stream=True,
    )
    async for chunk in completion:
        next = chunk['choices'][0]['delta'].get('content', '')
        result.text += next

input_text.on("keydown.enter", generate)


ui.run()
```

NiceGUIは、非同期でイベントハンドラーを定義しないと表示の更新がブロックされてしまいます。`ChatCompletion`で、`create()`ではなく`acreate()`を使い、`stream=True`とすることで非同期ジェネレータで返却されるため、これを扱うことでストリームを表示できます。

## 参考
- [Implementing Token\-by\-Token \(Streaming\) Effect in NiceGUI\. · Issue \#1128 · zauberzeug/nicegui](https://github.com/zauberzeug/nicegui/issues/1128)
- [ChatGPTを非同期でPythonから利用する方法 \- Make組ブログ](https://blog.hirokiky.org/entry/2023/03/14/163203)
- [StreamlitでChatGPTのStreamを表示する \- Qiita](https://qiita.com/suzuki_sh/items/64d84c417cba43cd6351)-
[PADフロー] PADフロー整形

Power Automate Desktopの、フローを整形するフローです。
クリップボード上で処理します。
`# [ControlRepository][PowerAutomateDesktop]` 以降のJSON部分を処理します。

整形内容

- 改行
- セレクタの要素名の、シングルクォーテーション部分を削除
- スクリーンショット削除(`ScreenShot`/`ScreenshotPath`を`null`にする)

```PADフロー整形.robin
Clipboard.GetText Text=> ClipboardText
Text.ParseText.RegexParseForFirstOccurrence Text: ClipboardText TextToFind: $'''(?m)^(?=\\{\\s+\"ControlRepositorySymbols\": \\[)''' StartingPosition: 0 IgnoreCase: False OccurrencePosition=> Position
IF Position = (-1) THEN
    EXIT Code: 0
END
Text.GetSubtext.GetSubtextFromStartTo Text: ClipboardText NumberOfChars: Position Subtext=> Robin
Text.GetSubtext.GetSubtextFrom Text: ClipboardText CharacterPosition: Position Subtext=> Json
Text.Replace Text: Json TextToFind: $'''(?<=\\\\r\\\\n)''' IsRegEx: True IgnoreCase: False ReplaceWith: $'''\\n      ''' ActivateEscapeSequences: True Result=> Json
Text.Replace Text: Json TextToFind: $'''(?m)(?<=^ {21,}\\\\\"Name\\\\\": \\\\\"[^\'\\n]+) \'.+\'(?=\\\\\")''' IsRegEx: True IgnoreCase: False ReplaceWith: $'''%''%''' ActivateEscapeSequences: False Result=> Json
Text.Replace Text: Json TextToFind: $'''(?m)(?<=^\\s+\\\\\"ScreenShot\\\\\": )\\\\\"[^\"]+\\\\\"''' IsRegEx: True IgnoreCase: False ReplaceWith: $'''null''' ActivateEscapeSequences: False Result=> Json
Text.Replace Text: Json TextToFind: $'''(?m)(?<=^\\s+\\\\\"ScreenshotPath\\\\\": )\\\\\"[^\"]+\\\\\"''' IsRegEx: True IgnoreCase: False ReplaceWith: $'''null''' ActivateEscapeSequences: False Result=> Json
Clipboard.SetText Text: $'''%Robin%%Json%'''
```

使っている正規表現をメモしておきます。
リファレンスは[正規表現言語 - クイック リファレンス - .NET | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/standard/base-types/regular-expression-language-quick-reference)。
確認は[regex101](https://regex101.com/)の.NET(C#) FLAVOR が便利です。

```txt:改行
(?<=\\r\\n)
```

```txt:シングルクォーテーション部分
(?m)(?<=^ {21,}\\"Name\\": \\"[^'\n]+) '.+'(?=\\")
```

```txt:ScreenShot
(?m)(?<=^\s+\\"ScreenShot\\": )\\"[^"]+\\"
```

```txt:ScreenshotPath
(?m)(?<=^\s+\\"ScreenshotPath\\": )\\"[^"]+\\"
```
未経験エンジニアが転職活動で聞かれた質問

今回は、僕が未経験エンジニアとして転職活動中に聞かれた質問をまとめてみました！

※自社開発系の会社がメインではあったので、主に自社開発系の企業で問われる質問の内容となっています。受託・SESとは少し異なりますのでご了承ください。


# 質問されたこと

## キャリアの側面

- なぜ、転職しようと思いましたか？
- なぜ、エンジニアになろうと思いましたか？
- 前職では、どんな仕事をしてましたか？
- 前職を辞めた理由はなんですか？
- 現職の仕事について教えてください。
- 現職で工夫していたことはなんですか？
- エンジニアを目指すきっかけはなんですか？

## 技術の側面

- どんな言語を学んでいましたか？
- チーム開発の経験はありますか？
- GitHubを使用したことはありますか？
- 学習するにあたり、どんな点を工夫していましたか？
- プログラミングをしていて、辛かったことはありますか？
    - それをどのように乗り越えましたか？
- どんなポートフォリオを作成していましたか？

## 性格の側面

- 強みと弱みを教えてください。
- 周りの人間からはどんな人と言われることが多いですか？
- 業務の中で、辛いことがあった時、どうしますか？

---

こんな感じで、質問をされていたと思います！

で、ここからが重要なんですが、面接ではフェーズ毎に見られているポイントが異なります。全てに当てはまるわけではありませんが、概ねこんな感じかと思いますので、参考にしてみてください🙋‍♀️

# フェーズ毎の違い

## 一次面接（技術や職種の理解について）

基本的に、一次面接では技術や応募してきた職種（業界）についての質問が多く、自社開発系の企業では特に「**ユーザー視点を持っているか**」を重視してる企業が多いです。

以下は一次面接で、見られている点についてです↓↓↓

- ユーザー視点を持っているのかが問われている
- 〇〇というポジションに、今までの経験をどのようにいかすことができるのかを知りたい
    - これは職種に対する理解があるかをみている

## 二次面接

技術に関する事項はクリアしたと見なされて、次に見られるのが人柄です！

これは、ただ性格を知りたいとかではなく、**自社とのマッチ度**を見られています。

以下は二次面接で、見られている点についてです↓↓↓

- 人柄
- カルチャーに沿っているかどうかを判断されている

## 最終面接

ここまで来れば、「安心！」ではありません。ここでは、今までの言動の辻褄が合っているか、一緒に働くイメージが持てるかなど見られています。（あれ、二次面接とほぼ一緒…?）つまり、ここに関しては、**企業による**というのが回答になります。（大体、CEOが出てくると思うので、その人によるところが大きい）

- 今までの面接から、話してる内容の辻褄が合っているか
- 人柄が会社とマッチするのか

---

ざっくりではありますが、僕の経験が少しでも多くの人の役に立てばいいなと思うので、ぜひ参考にしてみてください🙇‍♂️

また、よければ、Xもやっているのでフォローお願いします！！！

https://twitter.com/KazukiITWeb1
GUIツールから仮想環境とGitHubを連携しようとしたら苦戦した話

## 環境

- Windows11
- wsl(Ubuntu)
- Git 2.25.1
- Soucetree
- Gitドドド初心者

## 発生したこと

Soucetree経由でGitHubからUbuntu内```sunaba01```ディレクトリにリポジトリをクローンしようとしたら以下のエラーが発生

```
'git status' がコード 128 で終了しました: fatal: detected dubious ownership in repository at '//wsl.localhost/Ubuntu-20.04/home/***/sunaba01'
To add an exception for this directory, call:

	git config --global --add safe.directory '%(prefix)///wsl.localhost/Ubuntu-20.04/home/***/sunaba01'
 (\\wsl.localhost\Ubuntu-20.04\home\***\sunaba01)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579944/bd41f103-4b71-ef83-562b-1b3d18039de5.png)


## 原因

```git 2.35.2```から導入された```safe.directory```の影響らしい

## 解決方法

筆者の例であるが、以下のコマンドを試したら解決~~した~~しなかった（"再発"にて記載）

```
git config --global --add safe.directory "'%(prefix)///wsl.localhost/Ubuntu-20.04/home/*'"
```

個別ディレクトリを毎回設定するのが面倒だったので、homeディレクトリ以下は全部許可する設定でsafe.directoryに登録

この際、パス指定を```'%(prefix)///wsl.localhost/Ubuntu-20.04/home/*'```とシングルクオーテーションだけにしてしまうとうまくいかなかった

## 確認

safe.directoryを設定後、ちゃんと設定できているか確認する

```
$ git config --global -l

color.diff=auto
color.status=auto
color.branch=auto
safe.directory=%(prefix)///wsl.localhost/Ubuntu-20.04/home/*
safe.directory='%(prefix)///wsl.localhost/Ubuntu-20.04/home/*'
```

```safe.directory='%(prefix)///wsl.localhost/Ubuntu-20.04/home/*'```があればOK

## 所管

Gitを触るのが初心者だったため、バージョン依存ではなく仮想環境依存のエラーだと思い原因特定までに苦戦した。
エラーメッセージを検索したらあっさり出てきたので、後学のために本記事を残す。


 - [Ubuntu(WSL)の git をアップデートする](https://oji-cloud.net/2023/07/01/post-7591/)
 - [Getting code 128: fatal: detected dubious ownership in repository](https://community.atlassian.com/t5/Bitbucket-questions/Getting-code-128-fatal-detected-dubious-ownership-in-repository/qaq-p/2373506)

## 再発

解消したと思ったらエラー再発。
原因が「仮想環境側のGit」ではなく「仮想環境にアクセスしようとする、Windows側のGit」だったので、Windows側のGitのsafe.directoryを設定。
今回は自分しか使用しないので全ファイル許可の設定で記述する。
（Windows側のCUIはPowerShellを使用）

```
git config --global -e
```
config内
```
[safe]
        directory = *
```

※仮想環境側の```safe.directory```は削除して問題なかった

これでWindows側に入れたGit GUI経由でGitHub管理に成功。
Twitterで悲鳴を上げていたら助けてくれたFF内有識者に感謝。
ciscoのルーターでDHCPサーバーの設定がうまくいかないとき

# したいこと
cisco 891FJをDHCPサーバーとして使いたい．

# 起きたこと
設定したはずなのにIPが配られなかった．

設定は以下のサイトなどを参考に

https://www.infraexpert.com/study/dhcpz1.html

```
ip dhcp pool wireless
 network 192.168.2.128 255.255.255.240
 default-router 192.168.2.1
 dns-server 192.168.2.1 192.168.1.1 8.8.8.8
```
このようにしていた．

が，スマホやノートPCを接続してもIPが配られない...

# 解決方法

192.168.2.128以降の一部のアドレスのみをDHCP配布したかったので `network` のマスクを `255.255.255.240` としていたが，これが間違いだった．
`network` の部分のマスクはサブネットマスクとしてクライアントに配られる情報だったらしく，
/24のネットワークであれば `255.255.255.0` とするべきだった．

配布するアドレスの制限は `(config)# ip dhcp excluded-address` で行う．
なので，

```
(config)# ip dhcp excluded-address 192.168.2.0 192.168.2.128
```

とすると129番以降がDHCPで配布されるようになる．
MacにおけるSSH Keyの作成の仕方

1. まずホームディレクトリに行き、.sshが存在するかを確認します。

```
cd;
ls .ssh;
```

1. sshがなければフォルダを作成します

```
mkdir .ssh;
cd .ssh;
```

1. SSHキーを作成します。

tオプションでrsaを指定します。

```
ssh-keygen -t rsa
```

これで作成は完了です。


1. git hubにSSHの公開鍵を登録する場合

https://github.com/settings/keys
に下記コマンドで確認した内容を貼り付けます

```
cat ~/.ssh/id_rsa.pub;
```
ネットワークセキュリティ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/3bf4fc21-8d89-228f-1b13-4586f5d96922.png)
１：SSH（Secure SHell）
　主に遠隔ログインを行う時に利用するソフトウェアです。このソフトウェアが利用するプロトコルの名称もSSHです。SSHでは、ハイブリッド暗号方式を用いた暗号通信を行って、サーバと通信します。サーバにログインする際のパスワードや、さーべへの送信したコマンド、サーバからコマンド実行結果などが暗号化されてやりとりされますので、安全に遠隔ログインできます。また、ログインするさいの利用者認証として、パスワードによる認証の他に、公開鍵を利用した認証が可能なことも特徴です。
　代表的な利用場面として、インターネット経由でクラウドサービス上のサーバを保守管理する場合が挙げられます。

２：送信ドメイン認証
　送信ドメイン認証とは、送信限メールアドレスのドメインと、そのメールを配送しているメールサーバとの関係が正しいかを検証する方法です。迷惑メールの多くが、送信元メールアドレスのドメインとは無関係のメールサーバから送られてくることに着目した、迷惑メール対策です。送信ドメイン認証の方法には、SPFとDKIMがあります。

「送信ドメイン」
①SPF：送信元メールアドレスのドメインと、その目０流を配送しているメールサーバとの関係が正しいかをIPアドレスを用いて検証する。正規のメールサーバのIPアドレスは、DNSサーバに、SPF情報（SPFレコード）として登録しておく。

②DKIM：送信元メールアドレスのドメインと、そのメールを配送しているメールサーバとの関係が正しいのかをディジタル署名によって検証する。ディジタル署名の検証に使う公開鍵は、DNSサーバに、DKIM情報（DKIMレコード）として登録しておく。
Google Apps Script で ES Modules を使う方法

# これは何？

ES Module で作成されているライブラリを利用するときに困ったのでメモ。
読み込みたいモジュールが `DOMContentLoaded` 後に使用したいものだったので、 `Promise` で合成している。ただ `<script type="module">` を使えば十分だったかもしれない。

# 作成が必要なファイル一覧

| ファイル名 | 説明 |
|--|--|
| `main.gs` |  |
| `index.html` |  |
| `libLoader.js.html` | ES Module コードを動的に読み込むためのコード |
| `index.js.html` | EM Module を利用したいコード |
| `Lib_js.html` | 読み込みたい MS Module コード |


# Codes

```js:main.gs
'use strict';

function doGet() {
  return HtmlService
    .createTemplateFromFile('index')
    .evaluate();
}

/**
 * 
 * @param {string} filename
 * @returns {string} Html code
 */
function include(filename) {
  return HtmlService.createHtmlOutputFromFile(filename).getContent();
}

/**
 * 
 * @returns {string} javascript code
 */
function api_loadLibJs() {
  return HtmlService
    .createTemplateFromFile('Lib_js')
    .getRawContent();
}
```

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <?!= include('libLoader.js'); ?>
    <?!= include('index.js'); ?>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
```

```html:libLoader.js.html
<script>
const LibLoader = (() => {
  const DOMContentLoaded = new Promise((resolve, reject) => {
    const boot = () => {
      document.removeEventListener('DOMContentLoaded', boot);
      resolve();
    }
    document.addEventListener('DOMContentLoaded', boot);
  });
  const LibLoaded = new Promise((resolve, reject) => {
    google.script.run
      .withSuccessHandler(code => {
        const url = URL.createObjectURL(new Blob([code], {'type': 'text/javascript'}));
        import(url)
          .then(resolve)
          .catch(reject);
      })
      .withFailureHandler(reject)
      .api_loadLibJs();
  });
  return Promise.resolve()
    .then(() => DOMContentLoaded)
    .then(() => LibLoaded);
})();
</script>
```

```html:index.js.html
<script type="module">;(()=>{
'use strict';

LibLoader
  .then((module) => {
    module.hello(document.getElementById('app'));
  })
  .catch(console.error);
})();</script>
```

```js:Lib_js.html
//<script>
export const hello = (elm) => {
  elm.textContent = 'Hello, world!';
};
//</script>
```

# 参考

 * [Google Apps Script の Web アプリで CORS 制約を回避して Web Woker や ES Modules を使う](https://zenn.dev/37cohina/articles/710771a99b61e1)
 * [Promise の直列結合](https://qiita.com/norami_dream/items/0edfca15c15199921a73#%E7%9B%B4%E5%88%97%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)
【Xcode Cloud】Run Build Tool Plug-insを追加すると失敗する

# はじめに
Xcodeにプラグインを追加したらXcode Cloudが失敗するようになったので解決方法を記録しておきます。

# やりかた
① 「ci_scripts」というフォルダを作成します
![スクリーンショット 2023-09-23 19.29.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/8eb31105-1945-14a0-0375-064cc26c935d.png)

② 「ci_post_clone.sh」というスクリプトを作成します
![スクリーンショット 2023-09-25 14.41.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/662a3b98-ccfd-a11c-5f81-1274ec54aa73.png)

③ 「ci_post_clone.sh」を以下のように編集します
```ci_post_clone.sh
#!/bin/zsh

defaults write com.apple.dt.Xcode IDESkipPackagePluginFingerprintValidatation -bool YES
```

④ 実行可能ファイルに変更します
```:ターミナル
chmod +x ci_scripts/ci_post_clone.sh
```

# おわり
知らないと詰むやつですね

Xcode15からターゲットを選択するのがなくなり、勝手にLink binary With Librariesに追加されるようになったので変なのが追加されていないかも確認する必要がありそうです

# 公式ドキュメント
https://developer.apple.com/documentation/xcode/writing-custom-build-scripts

# 参考
https://zenn.dev/kyome/articles/56974297795cb5

https://forums.swift.org/t/telling-xcode-14-beta-4-to-trust-build-tool-plugins-programatically/59305/5

https://forums.swift.org/t/is-there-a-way-to-programmatically-allow-trust-the-compiler-plugin-to-run-from-the-command-line/65690

https://twitter.com/giginet/status/1575457371723567107
Proxmox上のWindows VMでNested VirtualizationしたWSL2とかがコケる件とその対策

# はじめに
環境は次の通りです。
ホスト:Proxmox VE 8.0.4
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/523aeb99-cd2c-6a65-7964-a91f5f0d64a7.png)
VM:Windows11 Enterprise Evaluation
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/34216717-3b69-3bbb-fea3-2cd65747ed6f.png)

まず最初にホスト側でNested Virtualizationが有効になっているか確認してください。
```
cat /sys/module/kvm_intel/parameters/nested   
```
Yが見えれば有効、Nが見えれば無効です。

Nの場合は次のコマンドを実行してください。
Intelの場合
```
echo "options kvm-intel nested=Y" > /etc/modprobe.d/kvm-intel.conf
reboot
```
AMDの場合
```
echo "options kvm-amd nested=1" > /etc/modprobe.d/kvm-amd.conf
reboot
```
再起動後に
```
cat /sys/module/kvm_intel/parameters/nested   
```
を実行してYが見えればOKです。
これでもNが見える場合はそもそもネスト仮想化に対応していない可能性があります。
マザーボードの設定を見直したりしてください。
# 第1段 ブートループ
Proxmox側ですでにNested Virtualizationが有効になっており、対象のVMのCPUはHostになっている状態でした。
Windowsの機能より
- Windows ハイパーバイザー プラットフォーム
- Linux用Windows サブシステム

を有効化して再起動した所、起動時に`SYSTEM THREAD EXCEPTION NOT HANDLED`と表示された後、修復ブートループへ…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/3d27b175-2093-9e60-cfe2-ac4d310da53d.png)
[Proxmox公式フォーラムにてそれっぽい解決策が書かれていた](https://forum.proxmox.com/threads/windows-10-vm-stuck-in-automatic-repair-boot-loop.108783/page-2#:~:text=Code%3A-,echo%20%22options%20kvm%20ignore_msrs%3D1%20report_ignored_msrs%3D0%22%20%3E%20/etc/modprobe.d/kvm.conf%0Aupdate%2Dinitramfs%20%2Dk%20all%20%2Du%0Areboot,-here%20it%20works)ので試した所…
(Proxmoxホストのシェルで実行してください。update-initramfsは2~3分かかるかもしれません。)
```
echo "options kvm ignore_msrs=1 report_ignored_msrs=0" > /etc/modprobe.d/kvm.conf
update-initramfs -k all -u
reboot
```

普通に立ち上がるようになり、ひとまずCPUをHostにした場合の無限ブートループは回避できました。
ついでにVM側のタスクマネージャーで`仮想マシン:はい`となっていた箇所も`仮想化:はい`となっていました。

# 第2段 Error: 0x80370109
既にUbuntuがアプリケーションに存在していたので起動を試みた所、下記の表示になりました。
```
Installing, this may take a few minutes...
WslRegisterDistribution failed with error: 0x80370109
Error: 0x80370109 ???????????????????

Press any key to continue...
```

これに関しては一旦Ubuntuをアンインストールし、管理者権限で起動したPowerShellから
```
wsl --install Ubuntu
```
を実行すると普通に通りました。
WSLで起動しているWEBアプリを同一ネットワーク内の別端末で表示する方法

## はじめに|

WEBアプリの開発中、WSL2で「npm run dev」や「yarn start」などでローカルにアプリを起動すると思います。

その際にスマホのブラウザで確認したくなったことありませんか？
chromeの開発者ツールのスマホエミュレータではなく、実機でです。

そんな時の備忘録です。

## 動作環境
- 開発環境
    - Windows10（※会社貸与ではない）
- ターミナル
    - Ubuntu 22.04.2 LTS (WSL2)
- スマホ
    - iPhone12（※これももちろん自前の端末）
- スマホのブラウザ
    - Safari

大前提として、PCとスマホが同一ネットワークに接続してある必要があります。

### PCのローカルIPアドレスの確認
画面右下のネットワークアイコンをクリック
→ 接続中のネットワークの「プロパティ」をクリック
→ 画面下部にあるプロパティ内の「IPv4 アドレス」「IPv4 DNSサーバー」を確認

### スマホのローカルIPアドレスの確認
設定アプリを起動
→ 「Wi-Fi」押下
→ 接続中のネットワークを押下
→ 画面下部のIPV4内の「ルーター」を確認

PCの方で確認した、「IPv4 DNSサーバー」と
スマホで確認した「ルーター」が一致していればOKです。

## 設定
まずは、今回確認したいアプリのIPアドレスとポート番号を確認。
アプリ起動時に出てくると思います。適宜読み替えてください。（ここだけ雑ですみません）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779836/2dde67b4-111f-1c79-f593-f3f710ff4ee5.png)
今回は
IPアドレス「172.24.201.10」
ポート「5174」
ですね。

PowerShellを管理者権限で立ちあげます。
```terminal
2> netsh.exe interface portproxy add v4tov4 listenaddress=192.168.11.27 listenport=5174 connectaddress=172.24.201.10 connectport=5174
```
を実行して、ポートフォワーディングを設定します。
192.168.11.27　は先ほどPCでIPアドレスを確認した時に確認した「IPv4 アドレス」を入力してください。

最後に、ファイアウォールの設定を変更します。
同一ネットワーク内でもブロックされます。

PC左下の検索窓にファイアと入力したら候補出ると思うので立ち上げてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779836/7a891999-3d53-9fdd-e804-d695b6070b04.png)

立ち上げ後、左側にある「詳細設定」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779836/23bd6736-7ada-a538-6c01-2ec0effd4f36.png)

左側、「受信の規則」を右クリック、「新しい規則」をクリック。

「ポート」を選択し、「次へ」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779836/112a4fc8-cd2d-8eb3-ebff-db5e6fb1a8ca.png)

「TCP」を選択し、先ほど確認したポート番号を「特定のローカルポート」に入力し「次へ」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779836/4023fd7a-a1b6-b689-1783-5144304008c0.png)

「接続を許可する」を選択し「次へ」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779836/2f16af09-1323-2089-cfc0-a7fbe69b7839.png)


「プライベート」を選択し「次へ」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779836/48fb08e8-a356-90e3-46c3-c7f26873fdc7.png)

画像のようにそれぞれ「名前」と「説明」を入力してください。そして「完了」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779836/091f9d3d-d5f4-bea3-2d8e-468ee39ee987.png)

## 確認
ここまで設定が完了したらスマホ側のブラウザで、PCのIPアドレスとポート番号を指定し
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779836/7b448c71-71bd-4f4b-5a77-386463bb6127.png)

アクセスします。
すると、よく見る画面をスマホから確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779836/20890cc4-9f6c-6ca3-065c-0a97f2e67ec7.png)

以上です。
動作確認終わったら、ファイアウォールの設定で先ほど、追加したものを右クリックし、「規則の無効化」をクリックして停止しておいてください。

PowerShellで以下を実行し、ポートフォワーディングの停止もお忘れなく。
```terminal
> netsh.exe interface portproxy delete v4tov4 listenport=5174 listenaddress=192.168.11.27
```
JWTについて理解する

# 目次
1. 背景
2. JWTとは
3. エンコードの中でもBase64URLエンコードを使う理由

## 1. 背景
業務でJWTについて扱っている為です。

## 2. JWTとは
- JSON Web Tokenの略
- JSONデータを[URLセーフ](https://qiita.com/yamatai12/items/1d2a43a291c1799210bd)にする方法を規定したもの
- JSONデータをコンパクトにする方法を規定したもの

RFCではJWTの仕様として次のように定義されています。
- URLセーフにする方法
JSONデータをBASE64URLエンコードする
- コンパクトにする方法
よく使われるデータ項目の名称を省略形にすることでJSONのキー名を短くする

JWTの仕様として省略名が予約されています
省略名|項目名|説明
| :----------| :----------| :----------|
iss|issuer|JWTの発行者
sub|subject|ユーザの識別子などJWTの主体
aud|audience|JWTの受信者
exp|expiration time|JWTの有効期限
nbf|Not Before|JWTの有効開始日時
iat|Issued At|JWTの発行日時
jti|JWT ID|JWTの一意な識別子

### クレーム(Claim)
JSONのデータ項目といっていたJSONのキーと値のペアはJWTでは「クレーム(Claim)」と言います。
```json
{
  "iss": "io.exact.sample.jwt",
  "sub": "saumple",
  "exp": 1670085336 
}
```
- 上の例ですと、"exp": 1670085336 はクレーム、expはクレーム名、1670085336はクレーム値と言います。
- 先ほど挙げたissやsubなどJWTで予約されているクレーム名は「登録クレーム名(Registered Claim Names)」と呼ばれます。しかし、この登録クレーム名の使用は任意です。
- 任意のクレームをJWTに含めることも可能です。

# 3.Base64URLエンコードを使う理由
### Base64
- 64個のテキスト文字からなるBase64セットのテキスト文字を使用してバイナリデータを表現し、誤って解釈することはないです。
- 非常に一般的なエンコーディングフォーマットであり、ほとんどのプログラミング言語で簡単に使用できます。

### Base64url
URLセーフなので、トークンをURLで送信することができます。

# 参考
- [基本から理解するJWTとJWT認証の仕組み](https://developer.mamezou-tech.com/blogs/2022/12/08/jwt-auth/#jwt%E3%81%A8%E3%81%AF)
- [Why do you use base64 URL encoding with JSON web tokens?](https://stackoverflow.com/questions/56711129/why-do-you-use-base64-url-encoding-with-json-web-tokens)
- [Why Base64 is used in JWTs?](https://stackoverflow.com/questions/58341833/why-base64-is-used-in-jwts)

# 参考になる記事を書いて下さった皆様に感謝致します!
【Rails】診断機能をラジオボタンを使って実装！

---
 ##  【Rails】診断機能をラジオボタンを使って実装！


今回はRuby on Railsで診断機能を実装します！
その時にチェックボックスではなくてラジオボタンを使って実装してみようと思います！
目次は以下の通りです！

### 1. コントローラー設計
### 1. データベース周り
### 1. Viewページ周り
### 1. ルート周り

## 1. コントローラー設計

```ruby:travels_controller.rb
class TravelsController < ApplicationController
  def index
  end

  def new
    @travel = Travel.new
  end

  def show
    @travel = Travel.find_by(id: params[:id])
  end

  def create
    @travel = Travel.new(travel_params)
    if @travel.save
        flash[:notice] = "診断が完了しました"
        redirect_to travel_path(@travel.id)
    else
        redirect_to :action => "new"
    end
  end

private
  def travel_params
      params.require(:travel).permit(:id, :question1, :question2, question: [])
  end
end

```



##  2.データベース周り

```ruby:ターミナル/コマンドプロンプト
$ rails g model Travel question1:string question2:string
```

```ruby:ターミナル/コマンドプロンプト
$ rails db:migrate
```

##  3.Viewページ周り

```ruby:travels/new.html.erb
<%= form_for(@travel, class: 'form-horizontal', role: 'form') do |f| %>
            <div class="container-sindan">
                <div class="row">
                    <div class="col-12">
                        <p>Question1. どちらかと言うと…</p>
                    </div>
                    <div class="col-6">
                        <p><%= f.radio_button :question1, "1" %>景色を選ぶ</p>
                    </div>
                    <div class="col-6">
                        <p><%= f.radio_button :question1, "2" %>食べ物を選ぶ</p>
                    </div>
                    <div class="col-12">
                        <p>Question2. 何人ぐらいで旅行行きたい？</p>
                    </div>
                    <div class="col-6">
                        <p><%= f.radio_button :question2, "1" %>1人</p>
                    </div>
                    <div class="col-6">
                        <p><%= f.radio_button :question2, "2" %>2~3人</p>
                    </div>
                </div>
           </div>
```

ラジオボタンを使う場合、一つのカラム(question)だけの場合、そのカラム内で一つしか選択することができないので、今回は質問ごとでカラムを変えて実装してます！


``` ruby:travels/show.html.erb
       <h5>診断結果</h5>
        <p>あなたにおすすめの旅行先は…</p>
        <div class="tweet-container">
                <% if @travel.question1 == "1" && @travel.question2 == "1"  %>
                    <h6>タイ</h6>
                <% elsif @travel.question1 == "1" && @travel.question2 == "2"  %>        
                    <h6>アメリカ</h6>
                 <% elsif @travel.question1 == "2" && @travel.question2 == "1"  %>       
                    <h6>インド</h6>
                 <% elsif @travel.question1 == "2" && @travel.question2 == "2"  %>       
                    <h6>ブラジル</h6>
                <% end %>
        </div>
```
if文を使って比較する時に、""で数字を囲うことに注意してください！今回は、DBでstring型で保存しているので比較させるときは文字列として比較させる必要があります！

##  4.ルート周り
```ruby:routes.rb
resources :travels
```
以上です！
【Node.js Axios】streamのレスポンスを扱うときの注意点

# はじめに

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191958/a528368a-e663-7313-b879-9469049def60.png)


図のように
１．APIサーバー①でAxiosを利用してAPIサーバー②からExcelファイルを取得
２，APIサーバー①で取得したExcelファイルをサーバー上に保存
する処理を実装したときに、**取得したExcelファイルを保存できずに結構ハマった**ので、備忘録として残しておきます。
（＊正しくはエクセルファイルとして保存できるが、ファイルが壊れていて開くことができない）

# TL;DR

- Axiosでストリームのレスポンスを受け取る際には、Axiosのoptionsで`responseType: stream`と指定すること
    - 指定しないと、レスポンスはJSON（デフォルト値）として扱われてしまう

# コード（抜粋）

- APIサーバー②のExcelファイルをストリームで返すAPI

```javascript
app.get(`/api/excel_files`, (req, res) => {
  try {
      const filePath = 'sample.xlsx';
      const fileStream = fs.createReadStream(filePath);
      const statusCode = 200
      res.status(statusCode);
      res.setHeader('Content-Type', 'application/octet-stream');
      fileStream.pipe(res);
  } catch (error) {
    console.log(error);
    return res.status(500).send('internal server error');
  }
})
```

- APIサーバー①からAPIサーバー②のAPIを呼び、取得したExcelファイルを保存するコード

```javascript

  const options = {
    responseType: 'stream', // !!ポイント!!
  }
  axios.get(url, options)
    .then(response => {
      const fileName = `test.xlsx`
      response.data.pipe(fs.createWriteStream(fileName));
    })
```

`options`に `responseType: 'stream'`を指定しないと`response.data.pipe()`の処理で

```
response.data.pipe is not a function
```
と怒られます。
（→`response.data`がstreamとして扱われないため、`.pipe`で処理できない）

responseTypeについては、[Axiosの公式のリクエスト設定](https://axios-http.com/ja/docs/req_config)に以下のように記載されています。

```
  // `responseType` には、以下のようなサーバーがオプションで応答するデータのタイプを指定します。
  // 'arraybuffer'、'document'、'json'、'text'、'stream'
  //   browser のみ: 'blob'
  responseType: 'json', // デフォルト
```

# 参考リンク

- [リクエスト設定 | Axios Docs](https://axios-http.com/ja/docs/req_config)

# つぶやき

Axiosにこんなオプションがあるのを知らなかった。
ライブラリのオプションにはどんなものがあるかは使うときに確認するようにしておいたほうがよいという教訓を得た。（知らないよりは知っておいたほうがよい）
GitHub からリポジトリを複製する

# はじめに
チームで管理しているドキュメントの更新、合同誌の執筆などの時に役立つ Git のクローン（複製）方法を記録していきます。
今回の環境は以下の通りです。
- OS：Windows
- エディター：Visual studio Code

# 事前準備
## Visual Studio Code のインストール
今回は、エディターとして Visual Studio Code を使用します。
インストールがまだな方はインストールをお願いします。

## Git のインストール
Git をインストールしましょう。
インストールしていないと、 Visual Studio Code 側でやることやれよって言われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/f964adfa-fd53-87bf-7cfb-80db935ec8e5.png)

## ローカルリポジトリの作成
自分のパソコンに Git に格納されたファイルやソースコードなどを複製する為の場所を用意します。
やり方が分からない方は、こちらの記事を参考にしてください。

https://qiita.com/YurimyMiyu/items/cc4dc31116fcd5f7b7d6

## リポジトリの URL 準備
予め会社やコミュニティからURLを共有されているという前提で書いています。
ご承知おきください。

# リポジトリへの招待を承諾する
1. リポジトリのURLへアクセスします。
2. Accept invitation をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/dcdf81c0-61be-d0c5-051a-fe82a569da39.png)
3. リポジトリに入れることを確認します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/8b9773cc-23ed-9b0c-2b86-b656c43ca4a8.png)



# GitHub からリポジトリを複製する

1. Visual Studio Code を起動します

2. ソース管理 をクリックします

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/a01578c4-0ebd-c45a-e614-25a1874c9804.png)

3. リポジトリの複製 をクリックします

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/a1dbbf82-f83d-a4b8-39aa-7f9268252c51.png)

4. 画面上部の GitHub からの複製 をクリックします

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/c7bb2038-c5c7-e648-0d8d-70c226f05f8d.png)

5. リポジトリを選択します

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/59448bfa-0b4a-dede-7269-491a00f8781f.png)

6. ローカルリポジトリ を選択し、リポジトリの宛先として選択 をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/0ef59061-5869-413d-abf4-e9cff577af70.png)

6. Sign in with your Browser をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/6f4d0388-48e5-e1d9-8dc0-bd6a4151a4a5.png)

7. ブラウザーが立ち上がって、Authorize Git Credential Manager という画面が出ます。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/44d91349-13dd-c9f6-fe07-60fcfdbe42cd.png)

8. Authorize git-ecosystem をクリックします。

9. 開く をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/6bbae125-8001-1a99-1bbc-61f8cab34eb2.png)

10. Visual Studio Code のエクスプローラーに Gitにあるファイルが出てきたら、完了です。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/e3d1c2a1-3bcd-f550-1231-7084df991fa1.png)

    ローカルリポジトリにもGit のリポジトリ名のフォルダーが出来ています。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/338bc00d-00fb-56b2-d029-f0e1c77f079c.png)

    中身を開くとこんな感じ
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/c39d1a31-5d6d-1017-a676-3d4b08215a31.png)

これで終わりです。
あとはガシガシ仕事するのみ！！
ItemsRepeater+ScrollViewerの子アイテムにコードからスクロールさせる方法

## ３行で説明

* ItemsRepaater.GetOrCreateElement() で得たUIElementに対して
* UIElement.StartBringIntoView()を呼び出すことでスクロールできる
* ItemsRepaater が入れ子の場合も、目的の UIElement に対して  StartBringIntoView() を実行すればOK

## 補足

* UWP（WinUI2）で試しました。WinUI3では未検証です。
[Swift] PRをマージした時にSwiftFormatを実行するGithub Actionsを作成する

PRがmainにマージされた時にSwiftFormatを実行したら思ったより便利だったので、備忘録として残しておきます。

# 実装
SwiftFormatを実行するためにMintを使用しています。

```yml
name: Format

on:
  push:
    branches:
      - main

jobs:
  format:
    name: SwiftFormat
    runs-on: macos-13
    env:
      MINT_PATH: mint/lib
      MINT_LINK_PATH: mint/bin
    steps:
      - uses: actions/checkout@v4
      
      - name: Select Xcode 15.0
        run: sudo xcode-select -s /Applications/Xcode_15.0.app
        
      - name: Install mint
        run: brew install mint
        
      - name: Cache Mint packages
        uses: actions/cache@v2
        with:
          path: mint
          key: ${{ runner.os }}-mint-${{ hashFiles('**/Mintfile') }}
          restore-keys: |
            ${{ runner.os }}-mint-
            
      - name: Format
        run: mint run swiftformat .
        
      - uses: stefanzweifel/git-auto-commit-action@v4
        with:
          commit_message: Run swift-format
          branch: 'main'
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

Mintのキャッシュの部分はこちらの記事を参考にさせていただきました🙇

https://qiita.com/uhooi/items/29664ecf0254eb637951

MintでPackageをビルドするときのXcodeのバージョンを指定します
```yml
      - name: Select Xcode 15.0
        run: sudo xcode-select -s /Applications/Xcode_15.0.app
```

そしてHomebrewでMintをインストールします
```yml
      - name: Install mint
        run: brew install mint
```

ここでMintでビルド済みのパッケージをキャッシュします。キャッシュをしないとワークフローを実行するごとにSwiftFormatが再ビルドされてしまい、ワークフローの実行に3分ほどかかってしまいます(キャッシュをしたら20~40秒ほど).
```yml
      - name: Cache Mint packages
        uses: actions/cache@v2
        with:
          path: mint
          key: ${{ runner.os }}-mint-${{ hashFiles('**/Mintfile') }}
          restore-keys: |
            ${{ runner.os }}-mint-
```
そして最後にswiftformatを実行し、差分が出た場合はmainブランチにpushします。
```yml
     - uses: stefanzweifel/git-auto-commit-action@v4
        with:
          commit_message: Run swift-format
          branch: 'main'
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
以上です！

PRをmainにマージする or mainにpushすることで、このようにSwiftFormatでコード整形をして、コミットをしてくれます。便利ですね。
![スクリーンショット 2023-09-23 19.28.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627061/d5b7fefc-39e0-77b5-258a-c17742f60632.png)
LINEでトークしながら、あれ何だった？を解決してみた。

![season_character3_autumn_momiji_ichou.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3536147/11e329d8-72b9-2ef2-f7e4-a5fc2f4fe2a6.png)



みなさん、こんにちは！
旅行とおうちでまったりすることが大好きな社会人3年目のキイロです！

最近も京都へ旅行してきたばかりのキイロですが、旅行といえばおいしい食べ物！
どうせ旅行に行くなら写真映えするものや美味しいものを食べたいですよね！

友達とどこのお店に行こうかたくさん相談しているうちに、キイロはある悩みを持ってしまいました。

**「友達とトークしたまま、検索機能が使えたらいいのに。」**


そうなんです。
LINEで友達とトークしているのに、お店の検索は検索機能アプリを使わなければならないのです。

これをどうにか1つにできないものか。
キイロはこの機能を作成してみることにしました。






**最終到達点はこんな感じです。**
![スクリーンショット 2023-09-23 140553.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3536147/50842943-0872-121e-2925-bae044c44a0f.png)
ここまで完成できるまでの道のりをお伝えします。







# 1.LINEBotのオウム返し
![スクリーンショット 2023-09-23 140829.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3536147/21d10df8-c359-07ac-7f3a-dde73b656dd9.png)

**まずはLINEBotのオウム返し機能を作成します。**

LINEdeveloperで取得した、チャネルアクセストークンを貼り付けし
Webhookを設定します。

# 2.オウム返し（モジュールの設定）
![スクリーンショット 2023-09-23 140729.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3536147/ea22670d-8cc6-0cca-795e-655caac14099.png)
**つぎに、オウム返しができるようにReply TokenとTextを設定します。**

これでオウム返しの完成です。

# 3.OpenAI(ChatGPT)と連結させる

最終到達点にいよいよ行ってしまいましょう。
今まではオウム返し（入力した言葉をそのまま返す）でしたが、
**今度はOpenAIからのメッセージを作成します。**


![スクリーンショット 2023-09-23 141213.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3536147/1d232f4e-31d2-bf67-198f-ad44a51947fd.png)

![スクリーンショット 2023-09-23 141359.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3536147/b14b1453-2e76-34b5-3fa3-efe6c2b9f5d3.png)





これでOpenAI(ChatGPT)と会話が成立します。



<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">投稿！ <a href="https://t.co/WRo9jeVXC1">pic.twitter.com/WRo9jeVXC1</a></p>&mdash; あかり (@akashiro_as) <a href="https://twitter.com/akashiro_as/status/1705518609727168978?ref_src=twsrc%5Etfw">September 23, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>







**こんな感じでLINEのトーク画面で検索機能を使用することが可能となります!!**



# 最後に
検索機能としては使用できていても、もっと深堀することができ、
より良いものが今後作れそうな気がしました。
今度作成してみたいものは、今の機能にレシピやモノづくりの工程が記載されていると
もっと使用したくなる機能が増えると思うので、応用できるようにしていきます！！！




**キイロがんばります！**
SQL学習アウトプットメモ①

# はじめに
IPAのデータベーススペシャリストの試験が近いので勉強した内容をアウトプットしていく:thinking:

# 用語
縦の列を
`属性、フィールド、カラム(columns)`
横の行を
`タプル、ロー(row)`
表のことを
`テーブル(table)`
と呼ぶ

和両立とは表の結合の際に選択項目をそろえる必要があることである
`和集合(UNION)`
`差集合(EXCEPT)`
`共通集合(INTERSECT)`

ただし`直積(CROSS JOIN)`は和両立ではない


# 射影
- COALESCE
A表にnameがなかった場合は'unknown'と表示する
```sql
SELECT COALESCE(name,'unknown') FROM A
```
COALESCEを使わずこれでも結果は同じ
```sql
SELECT CASE WHEN name IS NULL THEN 'unknown'
ELSE name END FROM A
```


- DISTINCT
A表のnameの重複を排除する
```sql
SELECT DISTINCT(name) FROM A
```
- CASE WHEN
A表からもしpriceが300以下なら割引価格それ以外なら通常価格と表示
```sql
SELECT
CASE WHEN price <= 300 THEN '割引対象'
ELSE 通常価格
END FROM A
```

# 内部結合
- 直積
- すべての組み合わせ
A表のタプルが500行、B表のタプルが500行あったとき
500*500=250000行となる

```sql
SELECT * FROM A,B
```



# 副問い合わせ
EXISTS(実行されるかされないか)

まずかっこの部分を評価する
Bが存在(EXISTS)したらAをすべて表示する

```sql
SELECT * FROM A
WHERE EXISTS (
SELECT * FROM B
)
```

Bが存在しなかったらAをすべて表示する

```sql
SELECT * FROM A
WHERE NOT EXISTS (
SELECT * FROM B
)
```

# 相関副問い合わせ
内側にその側のテーブルを記載することで1行ずつ評価していく
B表にあるnameがA表にもあったらA表からnameを一行表示
B表にあるnameがA表にもあったらA表からnameを一行表示と一行ずつ実行する

```sql
SELECT name FROM A
WHERE EXISTS (
SELECT * FROM B.name = A.name
)
```

```sql
SELECT name FROM A
WHERE IN (
SELECT * FROM B.name = A.name
)
```
ABC254 解説

**注意:この記事は未完成です。**

# ABC254 E - Small d and k

## [問題](https://atcoder.jp/contests/abc254/tasks/abc254_e)について

グラフとクエリが与えられます。
各クエリ　　頂点$x$からの距離が$k$以下の頂点の番号の総和を求める　　に答えてください。

### 特殊な制約

- 各頂点の次数は3以下
- クエリの$k$は3以下

## 解説

よくよく考えるとクエリで使う頂点は最大でも$3^3=27$頂点である。これは全部調べればいい！
BFSをするとして、各クエリで頂点$x$からの距離を全頂点について管理するとメモリが足りない。

さあどうする…

連想配列を使えば必要な頂点だけ距離を求められる！

## コード

``` py
from collections import defaultdict, deque
n, m = map(int, input().split())
g = [[] for _ in range(n)]
for _ in range(m):
  a, b = map(int, input().split())
  a -= 1
  b -= 1
  g[a].append(b)
  g[b].append(a)
for _ in range(int(input())):
  x, k = map(int, input().split())
  x -= 1
  di = defaultdict(lambda: -1)
  di[x] = 0
  q = deque([x])
  while q:
    p = q.popleft()
    for i in g[p]:
      if di[i] == -1:
        if di[p] < k:
          di[i] = di[p] + 1
          q.append(i)
  s = 0
  for i in list(di.items()):
    if i[1] != -1:
      s += i[0] + 1
  print(s)
```
リレーショナルデータベースとNoSQLは何が違う？

# 結論
||リレーショナル型DB|キーバリューストア型|ドキュメント指向型|グラフデータ型|時系列型|台帳型|
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|種類|RDB|NoSQL|NoSQL|NoSQL|NoSQL|NoSQL|
|略称|RDB|KVS|DOD|GraphDB| TSDB|ledgerDB|
|一言で|データの一貫性を重視|単純で処理速度が高速|拡張性が高い|データ間を関連付ける|時系列処理|改ざん耐性|

# データベースとは？

# リレーショナル型
一般的にデータベースといえばこれを指すと考えている。
表同士の関連を定義することで複雑な関係性を持つことが可能なデータベース。
ACID特性を持っており、障害発生時の対応が容易であることやダーティリードに強いことなどが利点。
<details><summary>ACID特性</summary><div>
## ACID特性
Atomicity: 入力されたデータに基づく処理が(すべて実行される/すべて実行されない)のいずれかになる。原子性
Consistency: 処理結果は「8桁である」, 「小数点以下を含まない」などデータベースに設定した条件を満たす。一貫性
Isolation: 処理中は外部からアクセスされない。独立性。
Durability: 処理が完了後にシステム障害が発生しても処理内容が失われない。永続性。
</div></details>

リレーショナルデータベースでは一般的にロー型DBが用いられる。
特定の列(Column)に対する一斉処理や検索などを高速に行う場合はカラム型DBを用いることがある。

# キーバリューストア型
データに対応する一意のキーを一対一で保存するデータベース
JSON形式に近い


# ドキュメント指向型
実際にデータを入れてから設計を決めることが可能なデータベース
JSONやXMLなど記述形式のデータを登録できる

# グラフデータ型
データの構造がネットワークのようになっているデータベース
SNSや乗換案内などユーザーや駅同士に関連があるデータを高速に検索したい場合などに使われる

# 時系列型
時刻と値がセットになったデータベース
時系列データに特化した圧縮アルゴリズムを用いることで検索の高速化が可能

# 台帳型
台帳機能に特化したデータベース。
データの変更を管理し、変更・削除できないよう制御する。
データが意図しない内容に変更されていないか、チェックする。

# 参考
https://sonnaka.com/210201-2/
【個人開発】情報漏洩を防止するChatGPTのCLIツールをプロトタイプした話

ChatGPTはプログラミングを含んだ様々な質問に答えてくれる便利なツールです。

一方で、特別な設定をしなければ、ChatGPTに送信した内容は学習データとして利用されるため、情報漏洩のリスクを孕んだツールでもあります。

例えば、社外秘をChatGPTに入力してしまい、その内容をChatGPTに学習されてしまうと、他の人がChatGPTを利用した際に社外秘が生成されてしまうといったことが起こり得ます。

そのため、業務でChatGPTを使う時は「入力内容が社外秘であるか？」といったことを気にする必要があり、結構イライラします。

今回はこの「ChatGPTを介した情報漏洩リスク」を自動で防ぐツールとして[「privacy gpt cli」](https://github.com/YukihiroArakawa/privacy-gpt-cli)を作成しました。

![Screen Shot 2023-09-23 at 18.23.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482077/15a3b2b1-e430-a351-e2a1-c3a675426e5a.png)

## 仕組み

以下の通り仕組みはかなりシンプルであり、標準入力を受け取った段階でブラックリストに含まれる社外秘を含んでいるかチェックして、社外秘を含んでいた場合はOpen AIのAPIに送信しないというものです。

1. ターミナルから標準入力を受け取る
1. 入力チェック
    1. ブラックリストに存在するワードが標準入力に含まれていた場合、Open AIのAPIに送信せずにブラックリストに含まれたワードが入力された旨をユーザに返す
    1. ブラックリストに存在するワードが含まれていない場合、Open AIのAPIにユーザの入力を送信する
1. 1に戻る

## 使い方

使い方はシンプルで、ツールを起動後は質問文を入力してEnterを押し、最後にgoという送信キーワードを入力してEnterを押すだけです。

そうするとOpen AI APIへ質問が送信され、レスポンスが表示されます。

![Screen Shot 2023-09-23 at 18.22.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482077/28a4789a-cf76-12c7-7d85-f9ec581ba4ff.png)


またブラックリストとして登録した「xxx corp」というワードを入力してみると、送信前にリジェクトされていることがわかります

![Screen Shot 2023-09-23 at 18.23.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482077/15a3b2b1-e430-a351-e2a1-c3a675426e5a.png)

## 展望

また今回のバージョンはあくまでプロトタイプ的な簡単なものなので、今後は以下の改善を加えて使いやすくしていきたいと思います。

- 事前設定するプロンプトをカスタマイズできるようにする
- gptのモデルを環境変数で指定できるようにする(現在はgpt3-turbo)
- レスポンスを非同期で受け取れるようにして、1文字ずつレスポンスを表示できるようにする
- 会話を保存できるようにする

以上

## 参考

- privacy-gpt-cli, https://github.com/YukihiroArakawa/privacy-gpt-cli
- open ai, api reference, https://platform.openai.com/docs/api-reference/introduction
- open-ai-java, https://github.com/TheoKanning/openai-java
- ****OpenAIとJavaでAIアシスタントを実装する,**** https://qiita.com/blue_islands/items/2522ba0bc1c2db450342
- ****JavaだってGPT-3.5を使ってChatGPTクローンが作れる,**** https://qiita.com/fsdg-yook/items/7b8e804e5e4bb31d5f5c
enum

# 初学者の備忘録
初学者の備忘録です。今回はenum編

## enumとは
enum とは、数値に意味を持たせることができるものです。数値に意味を持たせることのメリットは以下の通りです。

【メリット】
・決められた数値以外の登録が出来ないようにすることで安全性が高まる
・専用テーブルを作成しなくてもいい
・データベースに格納する時に、数値型の方がデータサイズが小さくなる

例えば支払い方法などにユーザー側がどの支払い方法を選択するか手入力するのではなく、enumを使用して選択式にしてあげることでクレジットカード、着払い、入金などの間違いが減るなどといったことです。

## 導入
【１】　Gem
enumは`enum_help`というGemなのでGemfileにenum_helpを記述します。最後の行で構いません。
```ruby:Gemfile
　　 :
  :
  gem "enum_help"
```

【２】　インストール
記述後、enum_help をインストールするために `bundle install` を行いましょう。
```ruby:Gemfile
　　 $ bundle install
```

導入は以上です。次は実装です。


## 実装
【１】　定義
enumを使用するModelに定義づけして、数値と文字列の紐付けをします。
今回は支払い方法でenumを使用した場合を例として進めていきます。
```ruby:app/model/必要ファイル
　　 enum payment_method: { credit_card: 0, transfer: 1,cash on delivery: 2 }
```
このように定義することで０の場合はクレジットカード、１の場合は銀行振込、２の場合は代引きという意味になります。
ただこのままだと日本語に対応していないので次は日本語対応の処理をしていきます。

【２】　日本語
日本語に対応させるために、config/application.rb に以下を追記します。
```diff_ruby:config/application.rb
　　 :
　　　　:

module NaganoCake
  class Application < Rails::Application  
  :
  :
  
  +config.i18n.default_locale = :ja

  :
  :
  end
end
```
この記述により、Rails アプリケーションのデフォルトの言語が日本語となり
次の手順で作成するymlファイルをもとに日本語化を行うといった流れとなります。

【３】　yml
config/locales フォルダに ja.yml というファイルを作成しましょう。このファイルに次のように記述します。
```diff_ruby:config/locales/ja.yml
　　 ja:
    enums:
      order:
        payment_method:
          credit_card: "クレジットカード"
          transfer: "銀行振込"
```
<details>
  <summary>補足</summary>
  ymlファイルの基本的な記述方法は<br>

![F968DAB4-0CFE-4F05-931B-10783E6339A9.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3503032/6e78f27f-3a85-b559-ef28-d0aa68005b66.jpeg)

になります。ymlファイルを記述するときはいくつか注意点があります。
- インデントを整える。ymlファイルはインデントに厳しいです。ズレていると対応できないのでルール守ってインデントを整えましょう。
- 同じ名前を使用してはいけません。例えばenumを使用するカラムが同じModelに複数存在していたとします。その時に同じModel名を二つ使用してしまうと日本語対応ができなくなります。同じModelを使用したなら同じ場所に記述しましょう。
この点を注意しないと日本語対応しない場合がありますので、もし日本語対応してないと思ったらymlファイルのコードが大丈夫か確認しましょう。

</details>

<details>
  <summary>他の日本語対応</summary>
enumの日本語対応のymlファイルの記述はしましたが、ymlファイルに記述するとバリデーションや、devise関係も日本語化できます。
ここでは長くなるので別枠で投稿させていただきます。
[ymlファイル日本語化]()

</details>

【４】　呼び出し
ここまでで日本語対応の準備はできましたので、呼び出してみましょう。
```diff_ruby:app/views/必要ファイル
　　 Order.payment_methods_i18n
```
上記のようにカラム名_i18nと記述することで日本語でenumを呼び出すことができます。


## 最後に
以上がenumの基本的な使い方になります。
ここから使用方法によっては多少アレンジしないといけない場合がありますが、私もまだまだ学習中の身なのでここに投稿できるほど理解しきれていません。
一緒に頑張っていきましょう！
URLセーフについて理解する

# 目次
1. URL Safeとは
2. URL Safeにする方法

# 1. URL Safeとは
URLにおいて特別な意味のある文字がある状態で適当にサーバに与えると意図しないことが起きたりしますし危険です。

[What does "URL-safe" mean?](https://stackoverflow.com/questions/72761577/what-does-url-safe-mean)
>This, combined with the RFC not specifying some other meaning explicitly, suggests it means simply "safe to put in a URL" (e.g., doesn't have unencoded / or ? or & characters, etc.).

URLに入れても安全
- エンコードされていない **/** や **?** 、**&** 文字などがない
  これらはURLにおいてGETパラメータのセパレータとして機能します。
    - **/** forward slash,ウェブサーバ上のリソースの階層的なパスの区切り、プロトコルの区切る為に使用される
    - **?** question mark,クエリー可能なオブジェクトのURIと、そのオブジェクトに対するクエリーを表現するために使用される単語のセットとの境界
    - **&** ampersand,クエリー文字列を区切る為に使用される

その他URL Safeではないもの

- 予約語
dollar ("$")
plus sign ("+")
comma (",")
colon (":")
semi-colon (";")
equals ("=")
'At' symbol ("@")
pound ("#").

- 一般的に安全でないと考えられているもの
space (" ")
less than and greater than ("<>")
open and close brackets ("[]")
open and close braces ("{}")
pipe ("|")
backslash ("\")
caret ("^")
percent ("%")

# 2. URL Safeにする方法
[HTML URL Encoding Reference](http://www.w3schools.com/TAGS/ref_urlencode.asp)
- 先ほど述べたURL Safeではない文字を"%"に続く2桁の16進数で置き換えます。
- 有効な[ASCIIフォーマット](https://e-words.jp/w/ASCII%E6%96%87%E5%AD%97.html)に変換します。
- URLにスペースを含めることはできません。
- URLエンコーディングは通常、スペースをプラス（+）記号または%20に置き換えます。

JavaScriptだと[encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent)があります。
以下のようにurlが変換されているのが分かります。
```javascript
const rawUrl = 'https://qiita.com/drafts/sample/edit';
const encodedUrl = encodeURIComponent(rawUrl);
encodedUrl;
//'https%3A%2F%2Fqiita.com%2Fdrafts%2Fsample%2Fedit'
```

# 参考
- [URL Safeとは](https://scrapbox.io/onigiri-it-tips/URL_Safe%E3%81%A8%E3%81%AF)
- [What is the meaning of ? (question mark) in a URL string? [duplicate]](https://stackoverflow.com/questions/33041449/what-is-the-meaning-of-question-mark-in-a-url-string)
- [Basic Syntax](https://www.markdownguide.org/basic-syntax/)
- [What do "?" and "#" mean in a URL?](https://www.quora.com/What-do-and-mean-in-a-URL)
- [What are the safe characters for making URLs?](https://stackoverflow.com/questions/695438/what-are-the-safe-characters-for-making-urls)
-[ASCII文字](https://e-words.jp/w/ASCII%E6%96%87%E5%AD%97.html)

# 参考になる記事を書いて下さった皆様に感謝致します!
Appsで登録したデータをAutomateで承認者に送ったら日時が世界時間で表示されて困った話　

こんにちは！
私は、元々VBAをちょっとだけ触れるくらいの**文系女子**でした。
しかし、その後、ITの世界にどっぷりとハマってしまいました。
2年前、**PowerAutomateDesktop**に出会い、それがきっかけでマイクロソフトのローコードツールに興味を持ち始めました。そこからPower　BIに興味を持ち、そして最近では**PowerApps と　PowerAutomate**でのアプリ開発にも手を出しています。

> ローコードの魅力って、初心者でも手軽に始められること。でも、ちょっとつまづくと、そこから先は大変。
>自分には基礎的な知識がないと、本買ってみたり、インターネットで情報を探しまくったり、GPTに質問したり。
>そして、答えが出ない時は、なにかアイデアないかとマイCPU（脳みそ）動かして色々と試してみたり。
　試行錯誤の最中は苦しくて苦しくて、心の中で
「_やっぱり私なんかが手を出してはいけないものだったのかなぁ_」
「_はぁ、もうやめよっかな_」
「**ケーキでも食べよ..あ、ハイボールのんだら脳みそ柔らかくなっていいアイデアでるかも...**」
「Zzzzz・・・・・・・・」
となることもしばしば。

>で、そんなこんなで、解決せぬまま　会社帰りに電車に揺られながらぼーっとしていると、突然、
「**あれ？これってこうしたらできるんかも？**」というアイデアが浮かんで
　結果、うまく動いたときの喜びや達成感は、何とも言えない気持ちになります。


今回の記事では、私が最近経験した**PowerAutomate**の小さなトラブルについてお話ししたいと思います。

勤務報告書をPowerAppsで作成する際、PowerAutomateの承認依頼通知に勤務日時が表示されるはずが、
何故か世界標準の時間に変換されて上司に知らせられてしまったんです！

このトラブル、実は解決するのに、私の隙間時間を含めて2週間もかかってしまったんです💦
わかってしまえばしょうもない、そんな小さな問題なのに、なぜこんなに時間がかかったのか...


それでは、今回の動作について説明しながら解決策を紹介します。

アプリ名：休暇/在宅アプリ

動作１：下記のAPPSの画面に必要事項を入力し、
　　　　☑ボタンを押すとPowerAutomateが動き出して、「承認１」で指定した人に承認依頼が届きます

　　　　　　![スクリーンショット 2023-09-23 APPS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3073811/4316c588-3275-cabb-a8d9-ce4a781952a6.png)

動作２：承認者側には下記の画面が届く。申請者・申請内容・開始日時・終了日時を表示されているので、
　　　　問題なければ承認ボタンを押してもらうんですけど、、、、、、
　　　　**時間がなんかおかしなっとるぅ～💦💦💦**ｼｸｼｸ
　　　　というのが今回の問題です。

　　　　![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3073811/cbce5076-5561-ce28-bf36-4d6b207a3b78.png)

　　　　ほんとは申請したままの時間（ﾜﾀｼﾆﾎﾝｽﾝﾃﾞﾙ　ﾀﾞｶﾗ東京時間ｼﾞｬ）でこんな感じで表示されたい
　　　　![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3073811/ff6cfa53-aa21-6361-0333-bb14dadd39ec.png)


で、2週間GPTにきいたり調べたりして、結局うまくいかなくて、電車の中で気づいたのがこれ‥

**【解決策】PowerAutomate側の時間を東京時間にするため、
　　　　　APPSで表示している変換元のタイムゾーン（東京時間）を
　　　　　改めて（東京時間）に変換する**
　　　　　![画像5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3073811/9195eb8e-3bfd-27ca-6948-405c7d94818f.png)


という、一人ボケツッコミのような事をすればうまく動作しました泣笑
（そうなんです、気付けばしょうもない話なんだけど、、、、）



どうもAPPSやSharepointは利用者の国の時間表示にあわせて何もせずとも表記がその国の時間で表示されてるようなんですが、PowerAutomate上だけは世界標準に自動で戻されてしまうみたいですね‥‥


ちなみに、タイムゾーンの変換の設定で今回の設定をするときに気づいたのですが
変換元・変換先が同じタイムゾーンの場合は「書式設定文字列」（下図で緑で囲っている部分）は必ず入れないとエラーになっちゃうみたい。
なので必ず入れるようにしてくださいね♪

　　　![画像6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3073811/129cb77c-e93f-3586-2055-573f0cced9a6.png)


それでは♪

またこれからも頑張って挑戦しつづけるぞ、オー♡