OmniAICreator/Qiita-1.07M huggingface dataset:
ESP32でBluetoothキーボードを自作してみた

今回はとあるお客様より
「計測器の値をPCへキーボードで入力するような感じで
データを送りたい」
と言われたのでESP32で試作器を作ってみました。

## ハードウェア
1、ESPr® Developer C3
https://www.switch-science.com/products/9185?variant=42767371010246
2、LED　1個
3、押し釦　1個
4、スイッチ　1個

## ソフトウェア
1、まずはArduinoIDEにライブラリをダウンロード
https://github.com/T-vK/ESP32-BLE-Keyboard/releases/tag/0.3.0
ESP32-BLE-Keyboard.zipをダウンロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/38256810-67af-dd73-f249-6234adc7253f.png)

2、ZIP形式のライブラリをインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/2704b239-0e0b-ca03-2e02-5da5217684bb.png)

3、ボード選択「ESP32C3 Dev Module」
※事前にESP32のライブラリはインストールしておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/c9869593-8ffe-2e67-3068-9fbfe8fa5777.png)

4、ライブラリマネージャーで「NimBLE-Arduino」をインストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/8ef0624b-77e8-378f-8344-bcebdc475801.png)

5、ESP32-C3の場合は、ESP32_BLE_Keyboardライブラリ内の「BleKeyboard.h」の
　#define USE_NIMBLEのコメントアウトを外す

【変更前】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/21492dc3-827d-f681-e5c2-02073242d095.png)
↓
【変更後】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/422384e3-0942-8e3d-68ab-f8a8497ebe00.png)

※ちなみにESP32-C3の時だけこの処理が必要！ほかのESP32でこれをすると逆に接続がおかしくなる


6、以下のソースコードでプログラム作成
```c
#include <BleKeyboard.h>

BleKeyboard bleKeyboard("TESTBLE");

int LED_PIN = 5;
int BUTTON_PIN = 6;
int SWITCH_PIN = 7;
int back_data = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(SWITCH_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);

  bleKeyboard.begin();
}

void loop() {
  if (bleKeyboard.isConnected()) {
    digitalWrite(LED_PIN, HIGH);
    if (digitalRead(SWITCH_PIN) == 0) {
      if (back_data == 0) {
        bleKeyboard.print("1");
        delay(100);
        bleKeyboard.print("2");
        delay(100);
        bleKeyboard.print("3");
        delay(100);
        bleKeyboard.press(KEY_LEFT_SHIFT);
        bleKeyboard.press(KEY_TAB);
        delay(200);
        bleKeyboard.releaseAll(); // すべてのキーを離す
        back_data = 1;
      }
    } else if (digitalRead(BUTTON_PIN) == 0) {
      if (back_data == 0) {
        bleKeyboard.write(KEY_TAB);
        delay(100);
        back_data = 1;
      }
    } else {
      digitalWrite(LED_PIN, LOW);
      back_data = 0;
    }
  } else {
    digitalWrite(LED_PIN, LOW);
  }
}


```


これでスイッチをONにすると「123」が書き込まれ、
ボタンをONにするとTABが押されます。
 ~~ちなみに始めは
bleKeyboard.print("123");
で入力しようとしたのですがたまに「12」しか入力されないという
バグがあったので一文字づつ入れるようにしました。~~
↓
bleKeyboard.setDelay(50);
を入れることで問題は解決しました。
詳細は以下の記事を参照。
https://qiita.com/Kurogara/items/ca26d59989fb56ca53b4
【UniRX】ObservablePointerClickTriggerを使ったタッチイベントの処理の処理の繰り返しをスッキリさせたい

## 背景
- 何かしらのオブジェクトが複数並んでいるとする。
- オブジェクトは01〜XXと名前がついており、同じものが複数あるイメージ。
- オブジェクトをクリックした時の長いコードをスッキリさせたい。
- オブジェクトの数のXX分同じ処理をコードで繰り返して書いているので、ループ処理でスッキリさせたい

改修前は以下のようなコードでしたが、改修後のような感じで綺麗にできました。

## 改修前

```
var clickTrigger01 = this.gameObject01.AddComponent<ObservablePointerClickTrigger>();
var clickTrigger02 = this.gameObject02.AddComponent<ObservablePointerClickTrigger>();
var clickTrigger03 = this.gameObject03.AddComponent<ObservablePointerClickTrigger>();
…

clickTrigger01.OnPointerClickAsObservable().Subscribe(p => 
{
    this.Method(1);
}).AddTo( this );

clickTrigger02.OnPointerClickAsObservable().Subscribe(p => 
{
    this.Method(2);
}).AddTo( this );

clickTrigger03.OnPointerClickAsObservable().Subscribe(p => 
{
    this.Method(3);
}).AddTo( this );
…

```

## 改修後

```
GameObject[] gameObjects = {this.gameObject01, this.gameObject02, this.gameObject03, …};
for (int i = 0; i < gameObjects.Length; i++)
{
    var clickTrigger = gameObjects[i].AddComponent<ObservablePointerClickTrigger>();
    int count = i;
    clickTrigger.OnPointerClickAsObservable().Subscribe(p => 
    {
        this.Method(count);
    }).AddTo( this );
}
```


## 起きた問題点
forループのiを`this.Method(i);`と渡したらどれをクリックしても `gameObjects.Length` の値が渡ってしまった。
`int count = i;` とローカル変数にコピーして`this.Method(count);`と渡すと`0 〜(g ameObjects.Length - 1)`の値を渡すことができた。
Windows起動時にHamachiを自動起動させない

# 結論
1. タスク マネージャーを起動
1. "サービス"タブを選択
1. 下部にある”サービス管理ツールを開く”を押下

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515829/681ee27a-23f1-4a9c-40e1-6bf52b816c44.png)

1. 開いたウィンドウから「LogMeIn」と「LogMeIn Maintenance Service」を探してダブルクリック
1. 開いたウィンドウで「スタートアップの種類：」を「手動」に変更
1. 「OK」を押して完了

# ちょっとハマった
方法をググって、いくつか試したみた。
例えば、
・設定→アプリ→スタートアップ　でHamachi関連のものをオフにする
・msconfigで検索→システム構成のスタートアップを選択→※特に変更箇所無し
など。

しかしどれも解決には至らなかったところ、下記に記したサイト様の記事を参考に上記のようにやってみたところ成功した。

大体のアプリケーションって、
設定→アプリ→スタートアップの画面上でオンオフを切り替えられるものだけど、Hamachiはそれだけではだめだったという話。

私の環境だけかもしれないけど、誰かの助けになれば！

# 参考にさせていただいたサイト（わすれなぐさ様）
https://forgetmenots.doorblog.jp/archives/34599917.html
SSH接続を閉じてもリモートのサーバでプログラムが動作し続けるようにする

## 要約
リモートのコンピュータでプログラムを実行し、そのプログラムをバックグラウンドで継続したいということがあるかと思います。例えば、時間のかかるスクリプトを実行して一度パソコンを閉じるときや、APIサーバのような常駐させるプログラムを実行するときです。

その時には、以下のようにコマンドを実行することで、リモート接続を切断してもプログラムが動作し続けます。

```shell
nohup 実行したいコマンド &

例）
nohup python main.py &
```

環境によっては`nohup`がなくてもバックグラウンドで持続するのですが、違いをあまり理解できていないです…。[参考](#参考)にあげた[こちらの記事](https://www.glamenv-septzen.net/view/854)が詳しく説明してありました。

## 背景
実行に時間のかかるスクリプトがあり、研究室のサーバで実行をしておくことにしました。VSCodeのRemote SSHからサーバに接続し、`python main.py &`のように実行してVSCodeを閉じ、少し後に確認をするとプログラムの実行がキャンセルされて止まっていました。

プログラムをサーバ上で動かし続けてローカルのVSCodeは閉じておきたかったので、その方法を確認しました。

## 原因
ターミナルが終了したときに`SIGHUP`というシグナルが送られるようです。

元々、コマンドの後ろに`&`と付けることでプログラムをバックグラウンドで実行できると聞いたことがあったので、`python main.py &`と実行していました。ですが、このように実行した場合でも上記の`SIGHUP`のシグナルを受け取るとプログラムが停止されてしまうそうです。

したがって以下のような流れでプログラムの実行がキャンセルされていたようです。

1. VSCodeを閉じたことによりターミナルが終了し`SIGHUP`のシグナルが送られる。
2. バックグラウンドで実行されていたプログラムが`SIGHUP`のシグナルにより終了させられる。

## 対策
一番シンプルだったのが、`SIGHUP`を受け取っても実行が止まらないように設定することです。実行コマンドの前に`nohup`と付けることで、そのコマンドは`SIGHUP`を受け取っても終了しないようになるそうです。

したがって、`nohup python main.py &`のように実行することで、pythonのスクリプトがバックグラウンドで実行され、かつターミナルが終了しても実行され続けるようになりました。

## 動作の確認

### 今までの実行方法
まず、VSCodeのリモートSSHを使ってサーバに接続します。

サーバ内で確認のために以下のようなプログラムを作成しました。このプログラムは3秒おきに現在時刻を出力し続けます。print関数の`flush=True`は、printの出力のバッファリングをしないようにしています。これをしないと後述の`nohup.out`に出力が記録されませんでした。

`python main.py &`としてプログラムを実行します。この際、プログラムはバックグラウンドで実行され、`ps aux | grep python`などでプロセスを確認するとpythonのプログラムが実行されていました。

```python:main.py
import time
from datetime import datetime

while True:
    now = datetime.now()
    print(now.strftime("%Y-%m-%d %H:%M:%S"), flush=True)

    time.sleep(3)
```

一度VSCodeを閉じてターミナルを終了します。

再度リモートSSHでサーバに接続し、`ps aux | grep python`のようにプロセスを確認してみると、先ほどのPythonのプロセスは見られませんでした。

### nohupを付けた実行方法
上と同様のプログラムを、今度は`nohup python main.py &`として実行します。`ps aux | grep python`で該当のプログラムを確認できます。

ここで一度VSCodeを閉じて、再度リモートSSHでサーバに接続します。

`ps aux | grep python`でプロセスを確認すると、まだ先ほどのPythonのプログラムが実行され続けていました！

## nohupのときの標準出力
`nohup`を使ってプログラムを実行すると、出力はターミナルには表示されなくなります。代わりに実行したディレクトリに`nohup.out`というファイルが作成されて、そこに出力が記録されるようです。

ただ、Pythonの標準のprint関数だと出力がバッファリングされてnohup.outファイルに出力が記録されませんでした。そのため、上記のプログラムでは出力をバッファリングしないようにしています。

## 参考

https://www.glamenv-septzen.net/view/854

https://qiita.com/sinsengumi/items/759ce48e844a46ed8091

https://atmarkit.itmedia.co.jp/ait/articles/1708/04/news015.html

https://blog.mktia.com/nohup-and-bg-process-on-remote-server

https://qiita.com/inosy22/items/341cfc589494b8211844

https://qiita.com/yushin/items/732043ee23281f19f983

https://simpleonedesign.com/blog/programming/print-nohup/

https://qiita.com/mmsstt/items/469a9346ce545709f53c
Slack：絵文字の名称を変更する（Enterprise Grid）

# はじめに

Slack Enterprise Gridは、他のプランに比べてセキュリティやガバナンス、コンプライアンスに効果的な機能が充実しています。

Slackを組織で運用していると、自社のガイドラインから外れた使われ方が行われるケースがあります。このようなケースにおいて、なるべく速やかにガイドラインに沿った運用へ是正することが、ガバナンスの観点からは望ましいといえます。

# Slackの絵文字の名称を変更する

Slackの絵文字をユーザーに自由に追加させていたら、いつの間にかガイドラインを逸脱した絵文字が増えてしまった・・・というのは、良くある問題ではないでしょうか。しかし、絵文字を制限するのはユーザービリティの観点から避けたいという思いもあり、放置状態になっているケースもあると思います。

先に述べた通り、Slack Enterprise Gridには、他のプランに比べてセキュリティやガバナンス、コンプライアンスに効果的な機能が充実しています。APIも同様で、活用することで効果的にSlackを管理することができます。

例えば、Slackの絵文字の名称を変更したい場合、APIで絵文字の名称を変更することができます。

https://api.slack.com/methods/admin.emoji.rename

このAPIを利用することで、例えばガイドラインに沿った命名となっていない絵文字の名称を、ガイドラインに沿った名称へ変更することが可能です。


# 手順

[こちら](https://api.slack.com/methods/admin.emoji.rename) のAPIの要求に合わせて、User OAuth Scopeの設定と、User OAuth Tokenの発行を行います。

その後、以下のパラメータを指定のうえ、APIリクエストを行います。

- name: 旧名称
- new_name: 新名称

※PostmanでAPIリクエストする場合の例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/7607b933-d132-7064-0500-b1daae438172.png)

このAPIを実行すると、次の通り指定された絵文字の名称が変更されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/fcd9bcf9-fff3-c4af-c7e1-ff6e34ded327.png)


# 制限事項

## 投稿済みのメッセージ上の絵文字の名称（文字列）は置換されない

本APIで絵文字の名称を変更しても、投稿済みのメッセージ上の絵文字名（文字列）の新旧置換は行われません。このため、絵文字の名称を変更すると、投稿済みのメッセージ上の絵文字が無効化され、絵文字の旧名称が単なる文字列として表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/df6b62ed-c532-3dea-0c70-7d7fcff195b8.png)

なお、ユーザーが投稿したメッセージをAPIで書き換えてしまうと（オリジナルを本人以外が書き換えられる状況は）、メッセージの真正性が失われることや、改竄などの問題に繋がる恐れがあるため、このような動作（絵文字の名称変更に合わせてメッセージを置換できない）はやむを得ないといえます。
MCT 特典の Azure サブスクリプションを Microsoft 365 Developer テナントで使用する方法

## 背景
[MCT (Microsoft 認定トレーナー)](https://learn.microsoft.com/ja-jp/credentials/certifications/mct-certification) になると、毎月 $150  まで無償で利用できる Azure のサブスクリプションが発行されます。

しかし、このテナントには Microsoft 365 のライセンスが無く、また Entra ID のライセンスも Entra ID Free となります。
そのため、以下のような Microsoft 365 ライセンスや Entra ID Premium が必要な検証が行えません。
例：
 * Azure Automation から Teams PowerShell のコマンドを実行する
 * Microsoft 365 の Graph API によるアクティビティログを Log Analytics Workspace へ保存する
   ※ Entra ID Premium ライセンスが必要

一方で、[Microsoft 365 Developer プログラム](https://learn.microsoft.com/ja-jp/office/developer-program/microsoft-365-developer-program) の Microsoft E5 Developer ライセンスには、Entra ID P2 ライセンスも含まれています。

この記事では、Microsoft 365 Developer のテナントで、MCT 特典の Azure サブスクリプションを利用する方法をご紹介します。こうすることで、Microsoft 365 Developer のテナントで Azure と Entra ID Premium が必要な検証も行うことができます。

## 概要
以下の説明で使う用語です。
| 用語 | 意味 |
|:-:|:-:|
| MCT テナント  | MCT 特典の Azure サブスクリプションの所有先となるテナント  |
|  Developer テナント  | Microsoft 365 Developer テナント  |
| MCT サブスクリプション  | MCT 特典の Azure サブスクリプション  |
| MCT 管理者  | MCT テナントの管理者ユーザーである Microsoft アカウント  |

MCT テナントの MCT サブスクリプションの所有先を、Developer テナントに変更します。
そのためには、MCT テナントのグローバル管理者である Microsoft アカウントのユーザーを、Developer テナントにゲストユーザーとして招待します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/ee0b0f01-bdb5-0e75-6d90-4f53f33f7a02.png)

## 手順
### ステップ1：Developer のテナントで、 MCT 管理者ユーザーをゲストユーザーとして招待する

1. Developer テナントのユーザーで Azure ポータルへサインインします
2. [Microsoft Entra ID] - [ユーザー] - [新しいユーザー] - [外部ユーザーの招待] から、MCT 管理者をゲストユーザーとして招待します
3. MCT 管理者に招待メールが届くので、招待を承諾します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/a4eafa67-8d34-26f9-7a74-04c52a4aad91.png)

### ステップ2：MCT テナントで、MCT サブスクリプションのテナントを Developer テナントに変更する

1. MCT 管理者で Azure ポータルにサインインします
2. [サブスクリプション] から MCT サブスクリプションを選択し、[ディレクトリを変更する] をクリックします
3. [フェールオーバー先] として Developer テナントを選択します
Developer テナントのテナント名は "MSFT" になっています。
4. チェックボックスにチェックし、[変更] をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/7a050ace-5faf-66e0-41d0-4461edbad8ba.png)

### ステップ3：Developer テナントで、管理者ユーザーを MCT サブスクリプションの所有者に設定する

1. MCT 管理者でテナントを Developer テナントに切り替えます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/2ed6da84-e077-48f6-ce15-800184b94919.png)
2. [サブスクリプション] から MCT サブスクリプションを選択します
3. [アクセス制御 (IAM)] - [追加] - [ロールの割り当ての追加] から、Developer テナントの管理者を MCT サブスクリプションの所有者に変更します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/306f4ca8-ae1b-4d07-8c18-721713ec6e77.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/e7794632-0bbf-d4dd-8d5c-01e03c4a339e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/0906c78a-8156-0815-8a08-9fba3da9fe77.png)

これで Developer テナントのユーザーで MCT サブスクリプションを使用して検証が行えるようになりました！

Microsoft 365 の検証をする機会が多く、せっかくの MCT 特典の Azure サブスクリプションを活用できていなかったので、方法がないか調べてみた内容を投稿させていただきました。お役に立てば幸いです。
高校生が今勉強したいことを書いてみた

# 高校生が今後学びたいこと

## React

https://ja.react.dev/blog/2023/03/16/introducing-react-dev

言わずもがな超有名なWebフレームワークです。
今までWindowsやAndroid向けでアプリを作っていたので、Webアプリも作れるようになりたいです。

## GCP

https://cloud.google.com/free/?utm_source=google&utm_medium=cpc&utm_campaign=japac-JP-all-ja-dr-BKWS-all-core-trial-EXA-dr-1605216&utm_content=text-ad-none-none-DEV_c-CRE_602341359562-ADGP_Hybrid+%7C+BKWS+-+EXA+%7C+Txt+-GCP-General-core+brand-main-KWID_43700071566406798-kwd-87853815&userloc_1009127-network_g&utm_term=KW_gcp&gad_source=1&gclid=Cj0KCQjwvb-zBhCmARIsAAfUI2sHj-PgsTUrzE5ms-V_tTq8JGmVCh4QuYwhPbp5n5m-_tlGfgzCh9kaAoPCEALw_wcB&gclsrc=aw.ds

AWSを使っていますが他のクラウドも使えるようになりたい！
それぞれ得意領域があるようだし、どれも使える人材は強いと思うので。
でもAWSを完璧に理解しているとは言えないから最初はそっちが優先かな。

## TypeScript

https://www.typescriptlang.org/

これもWeb系の技術。スクリプト言語はGolangくらいしか使ったことがないので、気合を入れて勉強しないと。

## Stripe

https://stripe.com/jp

超有名な決済サービス。これを使えるようになれば、自分でサービスを作っても決済ができるようになるし、ビジネスとしてのサービスを作れるようになるから勉強したい。
これは他のやつよりも簡単に勉強できるだろうから最初にやるかも。

## ドメイン駆動設計

https://amzn.asia/d/7VZl9ms

リファクタリングの本を読んでいたらこの本が出てきた。
Dockerを勉強していたときもドメイン駆動っていう言葉を見かけたので実は超重要な概念なのかもしれない。
しかし、まだ俯瞰して見られていないのでまずはそこから。

## デザインパターン

https://amzn.asia/d/blrZ8jF

自分はシングルトンとかFactoryパターンとか有名なやつしかわからないので、もっと知識を増やしたい。
座学で知識を増やしたら効率的にコードをかけるようになるだろうから、スキマ時間に読んでいきたい。

## セキュリティ

クラウドを使うにあたってセキュリティは超重要。
だけど何から勉強していこうか。IPAの試験でどんな攻撃があるか知ったけど、もっと深い知識を得たい。
UdemyでKali Linuxの講座を見つけたけど自分のやりたいことと関係あるのかな

## Linux

rm ls ps kill pwd chmod...
超基本的なコマンドは分かってきた！
だけどユーザーのコントロールとか知らない概念が超ある予感
だけど何をしたいかで勉強することが決まるだろうから、まずは体系的に勉強して勉強するものを決めよう

## SQL

MySQLとかなんとな～くで使ってきた。
最近はNoSQLとかで勉強から逃げている。
でもSQLは昔から使われているし、データ分析とかやりにも高度な知識が必要だから、やっぱり勉強しないといけないかな。
Pythonで九九の表を作成してみた

Pythonを使って、九九の表を作ってみました。

## 二重for文

九九になると、　for文を二重で使うのが一般的だ。
コードを書いていきましょう。

```
for i in range (1,10):
  for j in range (1,10):
    if j == 9:
      print (f"{i} x {j} = {i *j}")
      print ()
    elif i*j < 10:
      print  (f"{i} x {j} = {i *j}")
    else:
      print  (f"{i} x {j} = {i *j}")
```

### コードの出力結果

```
1 x 1 = 1
1 x 2 = 2
1 x 3 = 3
1 x 4 = 4
1 x 5 = 5
1 x 6 = 6
1 x 7 = 7
1 x 8 = 8
1 x 9 = 9

2 x 1 = 2
2 x 2 = 4
2 x 3 = 6
2 x 4 = 8
2 x 5 = 10
2 x 6 = 12
2 x 7 = 14
2 x 8 = 16
2 x 9 = 18

3 x 1 = 3
3 x 2 = 6
3 x 3 = 9
3 x 4 = 12
3 x 5 = 15
3 x 6 = 18
3 x 7 = 21
3 x 8 = 24
3 x 9 = 27

4 x 1 = 4
4 x 2 = 8
4 x 3 = 12
4 x 4 = 16
4 x 5 = 20
4 x 6 = 24
4 x 7 = 28
4 x 8 = 32
4 x 9 = 36

5 x 1 = 5
5 x 2 = 10
5 x 3 = 15
5 x 4 = 20
5 x 5 = 25
5 x 6 = 30
5 x 7 = 35
5 x 8 = 40
5 x 9 = 45

6 x 1 = 6
6 x 2 = 12
6 x 3 = 18
6 x 4 = 24
6 x 5 = 30
6 x 6 = 36
6 x 7 = 42
6 x 8 = 48
6 x 9 = 54

7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63

8 x 1 = 8
8 x 2 = 16
8 x 3 = 24
8 x 4 = 32
8 x 5 = 40
8 x 6 = 48
8 x 7 = 56
8 x 8 = 64
8 x 9 = 72

9 x 1 = 9
9 x 2 = 18
9 x 3 = 27
9 x 4 = 36
9 x 5 = 45
9 x 6 = 54
9 x 7 = 63
9 x 8 = 72
9 x 9 = 81
```
しかし、これだけでは、九九の計算結果が羅列されているだけだ。
ここで、綺麗な九九の表を書くにはどうしたらいいだろうか。

### 綺麗な九九の表の作り方
```
for i in range (1,10):
  for j in range (1,10):
    print (f'{i * j:2}', end = '')
  print ()
```
ここでは、フォーマット文字列を使用した。
フォーマット文字列を使用すると、書式を指定した表示ができるようになる。

### コードの出力結果
```
1 2 3 4 5 6 7 8 9
2 4 6 81012141618
3 6 9121518212427
4 812162024283236
51015202530354045
61218243036424854
71421283542495663
81624324048566472
91827364554637281
```
このような結果が得られます。
九九の表を生成することができ、二重for文を使用した時より見栄えが良くなった。

今度は、10000 x 10000 を計算できるプログラムコードに余力があれば挑戦したいです。
次の記事は、Fizz Buzz 問題の応用について投稿します。お楽しみに。

皆さんもこのプログラムコードを参考にして、時間のある時に九九の表を作成してみてはいかがでしょうか。
デコレーターについての備忘録

### デコレーターとは
デコレーターは、関数を修飾する関数です。これにより、関数を書き換えることなく、その関数に処理を追加したり、変更したりすることができます。

### デコレーターを使わない例
まず、デコレーターを使わない例を見てみましょう。

```python
def add(a, b):
    print(a + b)

print('Start!!')
add(1, 2)
print('Finish!!')

print('Start!!')
add(3, 4)
print('Finish!!')
```

このコードでは、`add`関数を呼び出す前後に同じメッセージを表示しています。

### デコレーターの使用例
次に、デコレーターを使って上記の処理を簡略化する例を見てみましょう。

```python
# デコレーター関数を定義
def my_decorator(func):
    def wrapper(a, b):
        print('Start!!')
        func(a, b)
        print('Finish!!')
    return wrapper

# 通常の関数
def add(a, b):
    print(a + b)

# デコレーターを手動で適用
add_result = my_decorator(add)
print(add_result)  # <function my_decorator.<locals>.wrapper at 0x...>

# デコレーターが追加された関数を実行
add_result(1, 2)
add_result(3, 4)
```

### デコレーターの簡略化
デコレーターを関数の上に直接書くこともできます。これにより、デコレーターの適用が簡単になります。

```python
# デコレーター関数を定義
def my_decorator(func):
    def wrapper(a, b):
        print('Start!!')
        func(a, b)
        print('Finish!!')
    return wrapper

# デコレーターを使用して関数を修飾
@my_decorator
def add(a, b):
    print(a + b)

# 修飾された関数を実行
add(1, 2)
add(3, 4)
```

### 汎用性の高いデコレーター
引数が固定されていると汎用性が低くなるため、可変長引数（`*args`）と可変長キーワード引数（`**kwargs`）を使って、どんな関数にも使えるようにします。

```python
# 汎用性の高いデコレーター関数を定義
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print('Start!!')
        func(*args, **kwargs)
        print('Finish!!')
    return wrapper

# デコレーターを使用して関数を修飾
@my_decorator
def add1(a, b):
    print(a + b)

@my_decorator
def add2(c, d, e):
    print(c + d + e)

# 修飾された関数を実行
add1(1, 2)
add2(3, 4, 5)
```

### まとめ
デコレーターを使うことで、関数の前後に共通の処理を追加することが簡単にできます。これにより、コードの再利用性が高まり、可読性も向上します。
C#のインターフェースを初心者なりにまとめてみた

# はじめに
オブジェクト指向プログラミングにおいて重要な部分にも関わらず、初心者には理解が難しいインターフェイスについて解説する！
自分もここで躓いたので、他の人を救えるような記事にしたいと思って書きました。

# インターフェース VS 抽象クラス

C#でインターフェイスと抽象クラスの違いは実はこれだけ！

|            | インターフェース | 抽象クラス |
|------------|----------|-------|
| 多重継承       | できる      | できない  |
| フィールド      | 持てない     | 持てる   |
| ※1 継承元の関数の影響を... | ※2 受けない    | 受ける   |

※1 継承元の影響とは関数のデフォルトの実装のことを言っています。
```C#
    public virtual void SomeMethod()
    {
        // 継承先でオーバーライドされる前に実行したい共通処理
        Console.WriteLine("共通の処理");
    }
```
こんな感じで共通の処理の行のプログラムが書き換わった場合、全ての継承先に影響が伝播します。

※2 C# 8.0 でデフォルト実装ができるようになりました。しかし※1で説明した通り、interfaceの実装側で影響がいかないようにできるだけ使わない方が良いと考えています。
(要勉強)


要はインターフェイスは呼び出し元に対して「こういうメソッドがあるよ」と教えるためのものである！

...だから?

# インターフェイスの使いどころ

## 良い例
ズバリ、インターフェイスを使うことは同じ関数を減らす営みである！
さっそく例を見てみよう！

```csharp
interface IChatAI
{
    string Chat(string message);
}

class ChatGPT : IChatAI
{
    private string apiURL = "https://api/chatGPT";
    public string Chat(string message)
    {
        string response = GetResponse(apiURL, message); // GetResponseは省略 messageを送信して返信を受け取る
        return response;
    }
}

class MyChat : IChatAI
{
    public string Chat(string message)
    {
        if (message == "こんにちは")
        {
            return "こんにちは！";
        }
        else
        {
            return "わかんないや";
        }
    }
}

// 使い方
class Main
{
    private ChatGPT chatAI;
    private MyChat myChat;
    
    public void Main(string[] args)
    {
        chatAI = new ChatGPT();
        myChat = new MyChat();
        
        Chat(chatAI, "こんにちは");
        Chat(myChat, "こんにちは");
    }
    
    private void Chat(IChatAI chatAI, string message)
    {
        string response = chatAI.Chat(message);
        Console.WriteLine(response);
    }
}
```

この例では、IChatAIというインターフェイスを使ってChatGPTとMyChatを使い分けている。
このようにインターフェイスを使うことで、関数を呼び出すだけで処理を切り替えられる！
これがポリモーフィズムの力だ！

## 悪い例

```csharp
class ChatGPT
{
    private string apiURL = "https://api/chatGPT";
    public string Chat(string message)
    {
        string response = GetResponse(apiURL, message); // GetResponseは省略 messageを送信して返信を受け取る
        return response;
    }
}

class MyChat
{
    public string Chat(string message)
    {
        if (message == "こんにちは")
        {
            return "こんにちは！";
        }
        else
        {
            return "わかんないや";
        }
    }
}

// 使い方
class Main
{
    private ChatGPT chatAI;
    private MyChat myChat;
    
    public void Main(string[] args)
    {
        chatAI = new ChatGPT();
        myChat = new MyChat();
        
        Chat(chatAI, "こんにちは");
        Chat(myChat, "こんにちは");
    }
    
    private void Chat(ChatGPT chatAI, string message)
    {
        string response = chatAI.Chat(message);
        Console.WriteLine(response);
    }
    
    private void Chat(MyChat chatAI, string message)
    {
        string response = chatAI.Chat(message);
        Console.WriteLine(response);
    }
}
```

お気づきだろうか？ 同じような関数が2つもある！
このような状況に陥っている場合は抽象化がミスっている。
同じ部分を共通化するためにインターフェイスがある。

# まとめ

インターフェースは

- 同じような関数を減らす
- 継承元の影響を受けない

という特徴がある。

Unityを扱った人はよく分かると思うが、Interfaceはコンポーネントのようなものです。
依存関係を減らすためにも、インターフェイスを使いこなせるようになろう！
[AWS #7] 第三者認証

## ■はじめに
こんにちは
今回も**セキュリティ分野**について取り上げたいと思います。

:rolling_eyes:今回の内容は何でしょうか
:upside_down:今回は第三者認証ということで **「AWS Artifact」** について紹介いたします。
:rolling_eyes:あーてぃふぁくと？
:upside_down:セキュリティやコンプライアンス、**契約の確認などをサポートするサービス**だよ

## ■AWS Artifact
▶**AWSコンプライアンスレポートをダウンロードできるサービス**
▶**重要なコンプライアンス関連の情報の頼りになる一元管理型のリソース**
▶**ISO、PCI、SOCなどの第三者による監査レポートをダウンロードできます。**

[・ISO（International Organization for Standardization/国際標準化機構）](https://www.jqa.jp/service_list/management/management_system/)
[・PCI（Percutaneous Coronary Intervention）](https://www.ncvc.go.jp/static/pci/)
[・SOC（Security Operation Center）](https://www.nec-solutioninnovators.co.jp/ss/insider/security-words/03.html)

:::note info
監査レポートを確認することで、**AWSの安全性を確かめる**ことができます。
:::
### ▶ アクセス
:rolling_eyes:このArtifactには**誰がアクセス**できるのですか？
:upside_down:基本的には **「全てのAWSアカウント」** がアクセスできます。他には **「ルート及び管理者アクセスを持つIAMユーザー」** や **「Artifactへのアクセス権」** を持つユーザーとか挙げられます。

### ▶ ダウンロード
:rolling_eyes:**どんなファイル**をダウンロードすることができますか？
:upside_down:金融業界、ISO、PCI、医薬、SOCなどのレポートです。
一例は以下のようなものがあります。
・Global Financial Services Regulatory Principles（金融系）
・ISO
・Payment Card Industry(PCI)
・Service Organization Control(SOC)
・Quality Management System Overview

試しに「Global Financial Services Regulatory Principles」をダウンロードしました。
金融系のレポートということでどんなことが記載されているのでしょうか…
![スクリーンショット 2024-06-18 150246.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/e408a2b7-a318-57fc-2e0c-57fce3f603bd.png)
![スクリーンショット 2024-06-18 151049.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/449384c3-98e9-c432-205c-943250345b56.png)
:rolling_eyes:最初のページだけど何が何やらさっぱりですな
:robot:読めないなら訳せば良いのに・・・

ChatGPTに訳してもらいました（正確とは言えませんが大まかなイメージを掴むために使用しました）
![スクリーンショット 2024-06-18 151342.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/cff894f9-2df2-6807-707f-896d40c9ca72.png)
どうやらこのレポートは世界各国（一部を除く）の金融業界に関して
・規制法（どこが、誰が規制しているか、主な規制法の出典など）
・活動（ライセンス取得に必要なこと）
などについて記載されていると考えます。

## ■おわりに
今回は第三者認証ということでAWS Artifactというサービスについて簡単にご紹介しました。

:rolling_eyes:Artifactは無料で、セルフサービス型で、AWSコンプライアンスのレポートをダウンロードできるサービスなんですね。

:upside_down:これにより、**AWSがいかに安全で安心して使用できるかを情報としてユーザーに共有**します。（IAM権限さえ付与すれば数分でダウンロードできます）


最後までお読みいただきありがとうございました！
>日頃より活用している参考書です。
>> **「参考書」**
[AWS認定クラウドプラクティショナー改定第3版](https://x.gd/19i6N)
>
> **「AWS公式サイト」**
[AWS Artifact](https://aws.amazon.com/jp/artifact/)
>
>**「参考元」**
>[AWS Artifactってなんだろ？](https://zenn.dev/mn87/articles/de5840d73aec9d)
>
> **「Youtube」**
[【CLF-C02：AWSクラウドプラクティショナー】第16回 AWS KMS・AWS Artifact (セキュリティとコンプライアンス分野)](https://x.gd/vCuic)
Streamlitで画像をUpload/Download

# はじめに

以下の記事を参考に、画像をUpload/Downloadする機能をGoogle Colabで実装してみました。

https://zenn.dev/ohtaman/articles/streamlit_tips

プログラム自体はほぼ参考記事と同じですが、保存先のフォルダが存在しない場合は作成するようにしています。

~~~python
# 画像保存先のディレクトリを設定
IMG_PATH = '/content/images'

# 画像保存先のディレクトリが存在しない場合は作成
if not os.path.exists(IMG_PATH):
    os.makedirs(IMG_PATH)
~~~

# Webアプリの画面

画像をアップロードする前のスクリーンショット

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/05102c29-d43a-466c-be9e-655d444f25ee.png)

画像をアップロードした時のスクリーンショット

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/0eb97a58-57c0-e108-f06d-2e2e6211ef04.png)

画像が存在する場合はダウンロードボタンを押すことでダウンロードが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/c44c3768-82db-f2f3-4a5d-723e587ebf2b.png)

# プログラム

~~~python
def list_imgs():
    # IMG_PATH 内の画像ファイルを列挙
    return [
        filename
        for filename in os.listdir(IMG_PATH)
        if filename.split('.')[-1] in ['jpg', 'jpeg', 'png']
    ]

def main():
  st.markdown('# 画像を保存するデモ')
  # IMG_DIR 以下の画像から選択
  filename = st.selectbox('ダウンロードする画像を選択', list_imgs())
  # ダウンロード
  st.download_button(
    'ダウンロード',
    open(os.path.join(IMG_PATH, filename), 'br'),
    filename
  )

  file = st.file_uploader('画像をアップロードしてください.', type=['jpg', 'jpeg', 'png'])
  if file:
    st.markdown(f'{file.name} をアップロードしました.')
    img_path = os.path.join(IMG_PATH, file.name)
    # 画像を保存する
    with open(img_path, 'wb') as f:
      f.write(file.read())
            
    # 保存した画像を表示
    img = Image.open(img_path)
    st.image(img)
~~~


# Google Driveに保存する場合

Driveのマウントと承認が必要

~~~python
from google.colab import drive
drive.mount('/content/drive/')
~~~

~~~python
# 画像保存先のディレクトリを設定
IMG_PATH = '/content/drive/My Drive/images'
~~~

# Streamlitの起動

~~~python
!streamlit run app.py & sleep 3 && npx localtunnel --port 8501
~~~
【DAY1】MVCモデルとは

# MVCモデルとは
MVCモデルとは、システム開発における設計パターンの一つです。
このモデルでは、プログラムを役割ごとに「Model（モデル）」、「View（ビュー）」、「Controller（コントローラー）」の3つに分けて管理します。

## Modelとは
Modelとは、システムの中でビジネスロジックを担当する部分です。
ビジネスロジックとは、ざっくりいうとシステム固有の処理を行う部分のことのようです。
ここでは、データベースとやりとりし、データの保存、取得、更新、削除などの操作を行うことを指します。
ちなみに、ビジネスとはプログラムにおける処理の内容、手順、方法です。

## Viewとは
Viewとは、ユーザーに対する表示や入出力といった処理をする部分です。

## Controllerとは
Controllerとは、ModelとViewを制御する部分です。
ユーザーの操作に応じてModelを更新し、その結果をViewに反映させます。
最終課題を終えて

2024年２月からプログラミングオンラインスクールに入学し早4ヵ月。
PCを購入するところから:sweat_smile:始まり、ようやく最終課題のフリマアプリを完成できたので全体を通して振り返りや今後についてまとめたいと思います。

#### きっかけ
プログラミングを習おうと思ったきっかけは現職（美容師）であと何年働けばいいんだろう・・・？という不安からでした。
一人息子を一人で育てる親として、現職では収入も時間も満足に確保できないと考えていました。

#### なぜプログラミング？
これは単純に憧れです:flushed:
現場で立ち仕事、カラー材でシャツは汚れ、手は荒れ、長時間労働している美容師からすると（スマートに仕事をこなす美容師さんもいます！あくまで私の現状です:pray_tone1:）、
PCカタカタ（カッコいい！）、リモートワークで家事育児仕事をこなせる仕事って魅力的過ぎました！
また、淡々と同じスタイルを100回切ってようやく１スタイル身につけたり、毎日何十人・月何百人の初めましてのお客様と約２時間マンツーマン対応する臨機応変能力は、プログラミング初心者に必要な探求心・勤勉さに通じるのかも？とも思いました。

#### 学習を始めてみて
私の１週間はこんな感じです。
| 　 | 8:00～18:00         | 21:00～24:00 | 
|:---|--------------------:|:------------:|
| 月 |家事・育児   　　　　 |  学習        |
| 火 |子供保育園・１日学習日|  学習        |
| 水 |仕事                 |  学習        |
| 木 |仕事                 |     学習     |
| 金 |仕事                 |    学習      |
| 土 |仕事                 |    学習      |
| 日 |家事・育児           |　休み　      |

何かとズレますが大体こんな感じでした。
学習は基本夜派、１～３時間程度です。
はじめる前はこの時間帯はSNSで時間を溶かす、海外ドラマで寝落ち、セルフネイル・・・などひとり親にしてはのんびりと過ごせていました:stuck_out_tongue_closed_eyes:

#### 良かったこと
中堅・ベテランといわれるようになって、良くも悪くも仕事に慣れて収入のために働いている状態でした。
新しいことへのチャレンジが単純に楽しいし刺激です！
SNSは見る専門でしたが新たにXを始めて定期的に投稿していると、同じ分野の方の能力の高さや考え方のレベルの違いに驚きます。

#### これから
オリジナルアプリを作ります！！
質の高いものが作れるように試行錯誤します。
年内には**職業：エンジニア**になっています！！！
なぜ私はQAエンジニアに戻ったのか


# はじめに
はじめまして。HRBrainでQAエンジニアを担当しています。
今回は転職で一度QAエンジニアを離れた私が、もう一度QAエンジニアに戻ってきた理由について書きたいと思います。


# QAエンジニアとの出会い
QAエンジニアという職業を知ったのは、1社目に入社してからでした。入社前には「事務の仕事をお願いしたい」と言われていましたが、初日に「じゃあまずデータ登録からやってみよう！」と言われ、私は今何をしているんだろうか…？という状態でした。

当初は苦しいことも多かったですが、不具合の原因切り分けや、テストパターンを考えて仕様書を作成したりすることが楽しくもしかして向いているのでは！？」と思うようになりました。特に、QAを担当した機能がリリースされ、 **「顧客の反応が良かった」とCSや営業から聞いた時には、道中がどれだけ苦しくても「やっていてよかった！」** と感じました。

## QAエンジニアから他職種への転職
向いているかも、楽しいかも！と感じていたQAエンジニアの仕事ですが、一度転職により離れています。

1社目でQAエンジニアを約4年半努めたのち、一度バックオフィスに転職をしました。QAエンジニアの仕事自体は好きでしたが、もともとやりたかった事務系の仕事に就いてみたかったこと、自分が本当にやりたいことを見つけたかったことから、転職を決意しました。

転職先の2社目では、資料を作成して提案する機会が多く、未経験の職種だったため全く知識がない分野についても一から企画運営することがありました。この経験を通じて、コミュニケーション能力が向上し、QAエンジニア時代とは異なる面でやり切る力が身についたと感じています。

# 再びQAエンジニアへ
転職先で色々なサービスを利用する中で、ただ使いにくいと感じるだけではなく「このボタンはこの位置にない方が良いのでは？」「この導線はこうなっていたほうが分かりやすい」等、ユーザーとしてではなくもはやQAをしながらサービスを触り、それが楽しくなっている自分がいました。

そういった経験から「QAエンジニアにもう一度戻りたい」と考え始め、また、一度QAエンジニアの職を離れたことで「サービスを使う側」でいるよりその **「サービスを提供する側」として、品質という面から関わっていくこと** にやりがいを感じていたことにも気づきました。

![モチベーショングラフ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815983/d5c8360d-b3e2-7de7-2aae-36b0d93ea8cc.png)


# なぜHRBrainを選んだか
HRBrainを選んだ理由は、QAエンジニアの役割が **品質保証業務だけにとどまらず、不具合の作り込みを防ぐという考えや取り組み**が魅力的に感じたためです。テスト工程ももちろんと重要ですが、不具合が発生しなければいろいろな面でみんなが幸せになれると思っています。1社目ではリリースに向けて目の前の仕事を消化しているだけの感覚がありましたが、自分の守備範囲を広げて働ける環境に身を置けると感じ、HRBrainを選びました。また、面接でお話をするなかで、この人たちと一緒に働きたいと率直に感じたことも理由の1つです。

### 入社してみて
実際に入社して一番嬉しかったことは、QAエンジニアが **開発チームの一員としてしっかり役割を持っていること**です。QAエンジニアからの指摘や提案がチームの意見として検討され、取り入れてもらえると感じました。
1社目では、QAエンジニアがあまり重要視されず、意見を言っても聞いてもらえないことが多かったので、正直身構えていました…。
このような環境が実現できているのは、先輩QAエンジニアの皆さんに対する信頼によるものだと思うので、私自身もチームから信頼されるQAエンジニアになれるよう、これからもより一層頑張っていきたいと思います！

![イラストや_会社2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815983/f28d2a76-51ee-fc5a-9e3a-659783f3b492.png)

# 最後に
この記事を通して、私がQAエンジニアの道を歩んだきっかけや、再びQAエンジニアに戻ってきた理由についてお話ししました。キャリアの転換点では多くの悩みや迷いがありましたが、それぞれの経験が私の成長に繋がっていると感じています。

QAエンジニアとしての仕事に戻ってきた今、QAエンジニアの仕事ができている嬉しさを感じつつ、一方で自分には足りない部分がまだまだあり、日々学んで成長しなければいけないと感じています。新しい領域や今まではと違う技術や経験にチャレンジすることに対して、HRBrainはとてもポジティブでチームのメンバーを後押ししてくれる環境なので、もし機会があればぜひ一度HRBrainをご検討いただければと思います!

最後まで読んでいただき、ありがとうございました。

https://www.hrbrain.co.jp/recruit
Nuxt3でESLint Flat Configを導入する際にprettierとの競合を回避する

Nuxt3でESLint Flat Configを以下ページのとおりに導入すると、prettierと競合する場合がある
(stylisticを使う前提の手順なので当然といえば当然だが)

https://eslint.nuxt.com/packages/module

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177673/2558a0a2-160a-3b38-5872-071b7021d32c.png)
↑ `@stylistic/quotes`エラーが出ている
prettierはデフォルトだと`singleQuote: false`のため、手でシングルクォートに修正しても`Ctrl + S`すると自動でダブルクォートになる
(VSCodeにて保存時に修正設定あり)

Flat Configになってからもprettierを使い続けることの是非は置いておくが、今までのルールからできるだけ変えずにFlat Configに移行したい場合もあると思われる

`nuxt.config.ts`に以下設定があるとESLintのスタイリングルールである`stylistic`が有効になってしまいprettierと競合する
```typescript
eslint: {
  config: {
    stylistic: true,
  },
},
```
上記を削除するか明示的にfalseとすることで`@stylistic`関連のルールがすべて無効化され、prettierと競合しなくなる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177673/468d9bb0-9a35-a365-eed0-57ec012a6aeb.png)
IBM Cloud - Getting help from the AI assistant (watsonx) 

#### Getting help from the AI assistant (watsonx) 
IBM Cloud で、watsonx を活用した AI アシスタントが実装されました。

https://cloud.ibm.com/docs/overview?topic=overview-ask-ai-assistant&locale=ja

現時点では Experimental (試験運用）相当の位置づけですが、IBM が提供する LLM を使用した、より精度の高い回答が期待されます。

##### What is the AI assistant?
>
>No matter where you are working in the IBM Cloud console, the AI assistant is available to help with your questions about IBM Cloud. The AI assistant is designed as a retrieval-augmented generation (RAG) implementation that is running against IBM® large language models (LLMs) using IBM's watsonx.

IBM Cloud コンソールのメニューバにある `?` アイコンから `Launch AI (Experimental)` をクリックする事で、簡単にアクセスできます。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128125/5ddcdc30-b1b2-dc6b-9c43-f8853862c7f9.png)

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128125/6ecbb8b5-1868-1887-de7d-c4ac5007172c.png)

試しに、`OpenShift AI` を `Red Hat OpenShift on IBM Cloud (ROKS)` に導入する方法を尋ねてみます。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128125/75b1c368-e3ea-a51c-4820-6900290c832c.png)

AI を活用した、より生産的な活動が実現できそうです。
CanonのカメラでTechnicolor Cinestyleを使う方法と、DaVinci ResolveでCineStyle S-Curveを使う方法（2024年）

### 概要

Canonカメラで動画を撮る際、Canon C-Log非対応機種でもダイナミックレンジを可能な限り残して録画する方法として、Technicolor Cinestyleがあります。また、Technicolor Cinestyleで撮影した動画を視聴に好ましいコントラストを与えるためのLUTとして、Technicolor S-Curveがあります。

2024年現在このワークフローはレガシーとなり、あまりお勧めできなくなってしまいましたが、個人的にやってしまったので記録を残しておきます。

<iframe width="560" height="420" src="https://www.youtube.com/embed/8nE8yoqubQE?si=lzOK3Dqs8vFDKYsV" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

### Cinestyleダウンロード

2024年6月現在、Technicolor社のサイトからCinestyleが削除されてしまいました。(桜が咲いていた頃にはまだ有効でした)

redditのスレッドによると、archive.orgから取得できるとあり、実際可能でしたので、それぞれURLを貼っておきます。

https://www.reddit.com/r/canon/comments/1d60v4j/technicolor_cinestyle_not_available_for_download/

https://web.archive.org/web/20201101115712/https://www.technicolor.com/cinestyle

### Cinestyleをカメラにインポート

CanonのサイトからEOS Utilityをダウンロードします。

https://canon.jp/support/software/os/select/dc/EU-Installset-W31607

EOS Utilityからピクチャースタイルとして、Technicolor_CineStyle_v1.0.pf2 をカメラにインポートします。

カメラにピクチャースタイルとして、CineStyleが追加されていますので、これで動画撮影します。

### DaVinci ResolveでCinestyle S-Curveを使う方法

残念ながら、Cinestyleに同梱のLUTはDaVinci Resolveで認識しないフォーマットでしたので、Pythonでコンバータを作りました。

https://github.com/yorung/SCurveLUTConverter

S-curve_for_CineStyle.txtをコンバータに通すと、S-curve_for_CineStyle.cubeというファイルが得られます。WindowsのDaVinci Resolveであれば C:\ProgramData\Blackmagic Design\DaVinci Resolve\Support\LUT以下に任意の名前でフォルダを作り、S-curve_for_CineStyle.cubeを格納することで使えるようになります。

### Cinestyle S-Curve適用前後の比較

Cinestyle S-Curve適用前
<iframe width="560" height="420" src="https://www.youtube.com/embed/M_384Pmkkos?si=mTO84iU1NXMGcfEW" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

Cinestyle S-Curve適用後
<iframe width="560" height="420" src="https://www.youtube.com/embed/8nE8yoqubQE?si=lzOK3Dqs8vFDKYsV" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
Macでお手軽にモックファイルを作る

## はじめに
フォームのバリデーション等を確認する際に、100MBのファイルや1GBのファイルをアップロードする必要がある場合があります。そのような場合、実際のファイルを用意するのは手間がかかります。そこで、Macで簡単にモックファイルを作成する方法を紹介します。

## 作成方法
Macには、`mkfile`というコマンドが用意されています。これを使うと、指定したサイズの空のファイルを作成することができます。以下のコマンドを実行すると、`1GB`のファイルが作成されます。(拡張子は適当で大丈夫です)

```bash
$ mkfile -n 1g foobar.png
```
> 1GBのファイルを作成する場合

```bash
$ mkfile -n 2m fizzbuzz.pdf
```
> 2MBのファイルを作成する場合

![スクリーンショット1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/fa1e2131-c439-90a8-554c-ea2526d5bb52.png)


![スクリーンショット2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/bd14ed20-e480-2096-655b-14564fe046e3.png)
もちろんファイルの中身はありません。

## まとめ
以上、Macで簡単にモックファイルを作成する方法を紹介しました。ファイルのサイズを指定して空のファイルを作成することができるので、非常に便利です。ぜひ、お試しください。
Vue3 + VeeValidate4 を SFC 無しで使用する

VeeValidate4をSFC無しで使用する場合のサンプルコード。
自分の場合、ASP.NET MVCのフロント側のコードとして使うことが多く、SFCではなくRazorと組み合わせたりコードもJavaScript直書きの事が多い為。

自分用のメモとして。

- Vue3、VeeValidate4はCDNから読み込む
- SFCではないので事前のbuild等は不要
- 以下のサンプルコードをhtmlファイルに保存してブラウザで開けば動く

```html
<!DOCTYPE html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>VeeValidate Example</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.29/vue.global.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vee-validate/4.13.1/vee-validate.js"></script>

  <style>
    span {
      display: inline-block;
      color: red;
    }

    input {
      display: inline-block;
    }

    button {
      display: block;
    }
  </style>

</head>

<body>
  <div id="app">
    <v-form @submit="onSubmit">
      <v-field name="name" type="text" placeholder="Who are you" rules="isRequired"></v-field>

      <error-message name="name" class="alert"></error-message>

      <button>Submit</button>
    </v-form>
  </div>

  <script>
    // Define the rule globally
    VeeValidate.defineRule('isRequired', (value) => {
      return !value
        ? '入力必須です'
        : true;
    });

    const app = {
      components: {
        VForm: VeeValidate.Form,
        VField: VeeValidate.Field,
        ErrorMessage: VeeValidate.ErrorMessage,
      },
      setup() {
        const onSubmit = (values) => {
          // 入力値をalertで表示
          alert(JSON.stringify(values, null ,2));
        };

        return {
          onSubmit
        };
      }
    }

    Vue.createApp(app).mount('#app')
  </script>
</body>

</html>
```
Arcって便利

表題の通りです。

界隈で噂のArcをデフォルトブラウザに変えたのですが、これがまた便利で…

Arc公式サイトは[こちら](https://arc.net/)

Arcといえば、
タブが経過時間で自動削除されたり、
タスク管理やメモ、クイックアクセス機能があったり、
カスタマイズが豊富な最先端を行くユーザー体験型ブラウザといったイメージです。

そんな中、自分が最も活用している機能は、
**Split View**でございます。
（これはまぁChromeでもできるっちゃできるのですが…）

何かというと、ブラウザを2画面に分割し操作ができるという機能です。

これをピン留めして名前をつけることで、

例えば公式マニュアルを見ながら、ブラウザでコード実行して学習する

などといった活用ができるようになります。

![スクリーンショット 2024-06-18 14.31.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511372/e809b82d-9025-8423-1576-f78d663137b3.png)


なんと便利なのでしょう(=^x^=)

学習が捗りそうです。
Dify実装で詰まった点

# Dify備忘録
この記事は、Difyとollamaを使って遊ぼうとした際に詰まった点についてまとめます。

## 環境
M2 Macbook pro 
Dify　Dockerで実行
Ollama　ローカルで実装（使用モデルはllama3:latest）

## 詰まった点1
Difyにollama　を認識させる所で詰まりました。

### 解決策
Base URLを以下に変更すると大丈夫でした

http://host.docker.internal:11434/

どうやらDifyをDockerで実行していることが関係しているようです。


これでDify側がollamaを認識してくれるようになります。

## 詰まった点2

先ほどのやり方でollamaの認識はできました。
これをDifyで使用するためには、
設定　→ モデルプロバイダー　→ システムモデル設定

このシステムモデル設定で利用するLLMを選ぶ必要があります。

「詰まった点1」でLLMの認識ができても、ここでそのLLMを選ぶことができません！

### 解決策

一度Difyからログアウトしてください。
Dockerを落とす必要はありません。
一度ログアウトし、再度ログインすればDifyが更新？されるのかLLMを認識してくれます。

## まとめ
以上がDify（Docker）で動かす際に私が詰まった点です。
金融×DX エンジニア勉強会

AI×フィンテックの領域において、 勉強会(LT)と交流会を通して知識の幅を広げることを目的として２ヶ月に１回程度開催しているイベントです。

開催：2024/06/26(水)・18:50〜21:30
場所：A YOTSUYA　地下イベントスペース

タイムスケジュール：
18:50〜開場
19:20〜オープニング
19:25〜運営の紹介
19:35〜LT+ディスカッション10分×3~5本を想定
20:15〜交流会
21:30　終了予定

◆参加お申し込みは→コチラへ
https://figurout001.connpass.com/event/320205/

![IMG_6391.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757711/df43555e-bd98-2b83-8fb7-6f5814e65772.png)


◆以下のようなテーマに触れる予定です。
・企業価値を評価するモデルづくり 　
・開示情報（XBRL）のデータ化の取り組みのポイント 　
・AIと金融工学

◆技術領域： GCP/AWS/React/Nextjs/graphQL/Hasura/PostgreSQL/docker/CloudSQL/python/xbrl

◆第２回となる今回は以下のテーマでのLTを予定しています。
１:Hooolders Analytics のつくり方
２:React Summit & JS Nation 2024 レポート
３:自前で集める金融データ XBRL入門
４:J-Quants APIで始める株価財務データ分析

ARTをテーマにしたクリエイティブなスペースでの開催となります。ぜひ、お気軽にオフラインでご参加いただけると、とても嬉しいです。
（※内容は予告なく変更になる可能性があります）

◆こんなエンジニアにおすすめ
データ分析の最新トレンドや実践事例に興味がある方 金融業界でのDX推進に関心があるエンジニア React Summitに興味があるが参加できなかった方や次回参加を考えている方 Reactの最新情報をキャッチアップしたいフロントエンドエンジニア

インパクト領域、金融、資本主義の課題に興味がある、 WEBエンジニア（バックエンド、フロントエンド）・データサイエンティスト・デザイナーの方。

初心者の方も大歓迎です！！

![IMG_6438.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757711/719dfa4a-015e-edcf-da33-a33c78a96a35.png)


これは、株式会社Figuroutと株式会社MILIZEが共催するFinTech関連技術の勉強会です。

◆株式会社Figurout　https://figurout.co.jp/
資本主義のアップデートをテーマに、企業と投資家をつなぐSRM（Shareholder Relationship Management）Saas を運営しています。

◆株式会社MILIZE　https://milize.co.jp/
金融工学・ビッグデータ・AI・機械学習・ファイナンシャルプランニングなど、金融業界における広範な分野における豊富な知見を基にしたシステム開発および独自サービス開発に強みを有しており、DX化を加速させるサービスの提供を行っています。

◆参加お申し込みは→コチラへ
https://figurout001.connpass.com/event/320205/
バリデーションエラー サーバサイドレンダリング時のHTTPステータスコードについて

バリデーションエラーについてAPIは400を返す　ですんなり納得いったが、APIとしてではなく、SSR（サーバサイドレンダリング）するようなケースも400を返すのか？200のほうがよい？について少し気になったでメモ。

## 結論
個人的には以下に落ち着いた。
200と400どちらがよいかは、プロジェクト・チームで方針を合わせておけばよいと思う。

## 詳細
#### API
いくつか記事をみたところ400に着地していてこれは納得できる。
https://qiita.com/nesheep5/items/6da796f6ac628c430c36

#### SSR
これについての記事はみつけられなかった。
- SSRの場合に200を返してもよいのではと思った理由
    - SSRの場合、バリデーションエラーになったとしても、画面をレンダリングするということが責務だとすると、エラーメッセージとともに画面を再表示するという風に解釈すると200を返すことでも納得できる。
    - いくつかのフレームワークの実装などをみるとSSR時はそのまま200を返している(というより、テンプレートを指定しているだけで、httpStatusCodeをわざわざ設定していないからそのまま200になっている）がみられた。
    - spring bootだとbindingResultでvalidation結果を取得してそれをviewに返す例も多い(この場合も200を返す）
```java:sample.java
    @PostMapping("/register")
    public String registerUser(@Validated @ModelAttribute("userForm") UserForm userForm, BindingResult bindingResult, Model model) {
        if (bindingResult.hasErrors()) {
            return "register"; //registerというviewを返す HTTPステータスコードは200
        }
```
  - その他、近いような議論をしていた記事
      - https://stackoverflow.com/questions/3290182/which-status-code-should-i-use-for-failed-validations-or-invalid-duplicates
>200
>Ugh... (309, 400, 403, 409, 415, 422)... a lot of answers trying to >guess, argue and standardize what is the best return code for a >successful HTTP request but a failed REST call.

の箇所。ここではHTTPとRESTfulを混同しないように的なことで議論されていて近いものはあるかなと思った。記事を追ったが、そういう考え方もあるというのでどっちが正解というのはなさそうだった。

- SSR時でも400を返しておいた方が良いと判断するポイント
    - テストがやりやすい
        - ステータスコードが200だとバリデーションできたかはhtmlをみないといけない。400にしておけば楽。
    - 同じリポジトリ内にSSRとAPI呼び出しが混ざっている
        - APIはバリデーションエラー400で返しているのにSSRの箇所は200なの気持ち悪いという議論になりそうなのでこういう場合はもう400にしてしまったほうがよいのかなと思う。
【TCA】observe(_:)でトラッキングしている値をクロージャ内で変化させた場合は変更を検知しない

以下のコードで、ボタンをタップしたときにコンソールに出力される値はどうなるでしょうか？

```swift
// Feature
@Reducer
struct Feature {
    @ObservableState
    struct State {
        var flag = false
    }

    enum Action {
        case buttonTapped
        case finished
    }

    var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .buttonTapped:
                state.flag = true
                return .none
            case .finished:
                state.flag = false
                return .none
            }
        }
    }
}

// ViewController
observe { [weak self] in
    guard let self else { return }
    print("flag: \(store.flag)")
    store.send(.finished)
}
```

正解はこうです。

```
flag: true
```

僕はてっきりこうなると思ってました。

```
flag: true
flag: false
```

TCAの内部は追ってないのでこうなりますよというだけの話ですが、地味にハマったのでしっかり理解しておきましょう。
asdf移行メモ


今まで`pyenv`,`rbenv`,`nodebrew`を使っていましたが、`asdf`に乗り換えたので移行メモを残します。
https://asdf-vm.com/

# 環境
- M2 Mac

# インストール
```shell
$ brew install asdf
```
を実行

```shell
$ echo -e "\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ${ZDOTDIR:-~}/.zshrc
```
を実行してPATHを通す

# 各種導入🚀

```shell
$ asdf install python latest
$ asdf install ruby latest
$ asdf install nodejs latest
```
適宜、バージョンを指定する。

# お掃除🧹
`~/.zshrc`に書かれていたpyenv,rbenv,nodebrewの設定を削除

```text:./zshrc
 # pyenv
 export PYENV_ROOT="$HOME/.pyenv"
 command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
 eval "$(pyenv init -)"
 
 # rbenv
 [[ -d ~/.rbenv  ]] && \
   export PATH=${HOME}/.rbenv/bin:${PATH} && \
   eval "$(rbenv init -)"
  
 export PATH=$HOME/.nodebrew/current/bin:$PATH
```
手探りでGPT APIとSlack APIをGASで実装したときのメモ

GPTとのやりとりをGoogle App Scriptを経由してSlack Botで行おうと思ったら，ドツボにハマった話をメモ．

## GASのプリントアウト出力問題

課題:
`Logger.log`や`Console.log`を行っても，`doPost`関数はログを吐かない．

解決:
Spread Sheetにログを吐くようにメソッドを追加．Kotlinと同様のPrint形式を採用．

```javaScript
function sslog(tag, msg){
  const sheetForLog = SpreadsheetApp.openById(SPREAD_SHEET_ID).getSheets()[0]; //sheetIDはとりあえず0
  sheetForLog.appendRow([ // わかりやすいように1列目には現在の日時を書き込む
    Utilities.formatDate(new Date(), 'JST', 'yyyy/MM/dd HH:mm:ss'), 
    tag,
    JSON.stringify(msg)
  ]);
}
```

参考

* [Google Apps ScriptでdoPost関数のログを出力する方法3選【GAS】](https://prtn-life.com/blog/gas-log-gcp)

## Slack多重トリガ問題

課題:
なぜか1度のメッセージ送信に対して複数回のトリガが発生する問題．
どうやらGPTの処理待ちの時間にSlackが再送を行っているような状況．

解決:
`client_msg_id`を`cache`に蓄積し，一度送信した履歴があればスキップするよう実装する．

```javaScript
if (slackEvent.event.client_msg_id == null) { // NULL
  sslog("Retry", "Return; NULL");
  return;
} else if (cache.get(slackEvent.event.client_msg_id) == 'done') { // キャッシュからの取得; get(キー)
  sslog("Retry", "Return; client_msg_id is 'done'");
  return;// ContentService.createTextOutput(); // 新しい TextOutput オブジェクトを作成
} else {
  sslog("Retry", "Continue; This is First Time");
  cache.put(slackEvent.event.client_msg_id, 'done', 600); // キャッシュへの追加; put(キー, 値, 保持期限(秒))
}
```

参考

https://qiita.com/rh_taro/items/e5a76f24b744353d4bb9

* [slack api Document](https://api.slack.com/apis/events-api#retries)
  * リトライされたリクエストの場合ヘッダに`X-Slack-Retry-Num`がついてくるらしいが，GASではヘッダ検証が大変そう
クロージャーについての備忘録

### クロージャーとは
クロージャーは、関数の外で宣言された変数や引数を保持する機能のことです。これにより、関数が定義されたスコープの外からも変数にアクセスできます。Pythonでは、すべてがオブジェクトとして扱われるため、変数もオブジェクトです。

### 基本的な関数の例
以下は、円の面積を計算する関数の例です。

```python
def circle_area(pi, radius):  # 関数オブジェクトを作成してcircle_area変数に代入
  return pi * radius * radius

area = circle_area  # ()がないと、変数に代入されている関数オブジェクトを取り出すだけ
print(area)  # <function circle_area at 0x...>

print(area(3.14, 2))  # 12.56
```

### クロージャーの例
次に、クロージャーを使った関数の例を見てみましょう。

```python
def circle_area(pi):
  def calculation(radius):
    return pi * radius * radius
  return calculation

area1 = circle_area(3.14)
print(area1)  # <function circle_area.<locals>.calculation at 0x...>
```

ここで、`area1`は関数オブジェクト`calculation`を返しています。この関数は、`pi`の値を覚えていて、後で使うことができます。

```python
result1 = area1(2)
print(result1)  # 12.56
```

### 別の例
別の値で関数を生成することもできます。

```python
area2 = circle_area(3)
print(area2)  # <function circle_area.<locals>.calculation at 0x...>
```

ここで、`area2`も関数オブジェクト`calculation`を返していますが、`pi`の値は3です。

```python
result2 = area2(2)
print(result2)  # 12
```

### まとめ
クロージャーを使うことで、外部の変数を保持した関数を作成できます。これにより、関数が定義された環境の変数をそのまま利用することが可能になります。
MuleSoftでの403エラー



+ [MuleSoft Google Drive Connector On New File Trigger](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cm1RR)


Google ドライブの「新しいファイル トリガー時」コネクタに問題があります。 OAuth ダンスを実行しましたが、30 分ごとに 403 トークンの期限切れエラーが発生し続けます。同じ構成を使用している他のコネクタは正常に動作しています


https://community.auth0.com/t/403-forbidden-error-when-renewing-token/93187
>不明または無効なリフレッシュ トークン エラー メッセージは、Auth0 が何らかの理由でリフレッシュ トークンを認識できないことを示します。つまり、有効なトークンが何らかの理由で送信されていないか (このような状況では、何らかの理由でゴミを送信しているか、トークンが欠落しているか、切り捨てられているか、余分なトークンが埋め込まれている可能性があります)。

ですよね、403だからリフレッシュトークンが間違っていると思う尾ですが、質問者さんは正しいと言っている。
正直これ以上はこちらでは分からん。





# 分からない用語もあるな。


**OAuth ダンス**

"OAuth dance"
My unofficial term to describe the full OAuth authentication/authorization process.


完全な OAuth 認証/認可プロセスを表す私の非公式の用語。

https://developers.google.com/gdata/articles/oauth

**Google Drive Connector On New File Trigger**

この中に... パラメータしか書いてない

+ [Google Drive Connector 1.1 リファレンス - Mule 4](https://docs.mulesoft.com/jp/google-drive-connector/latest/google-drive-connector-reference)
PostgreSQL: SQL のサンプル （テーブルの一覧）

参考ページ

[37.54. tables](https://www.postgresql.jp/document/16/html/infoschema-tables.html)

## テーブルの数を数える

```sql
SELECT count(*) FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema');
```

実行例

```text
db_common=# SELECT count(*) FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema');
 count 
-------
  1583
(1 row)
```

## テーブル名が g で始まるものの数を数える

```sql
SELECT count(*) FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema') and table_name like 'g%';
```

実行例

```text
db_common=# SELECT count(*) FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema') and table_name like 'g%';
 count 
-------
  1241
(1 row)
```

## テーブルの一覧

```sql:all01.sql

SELECT table_name FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema') order by table_name;
```

実行例

```bash
psql -Uscott db_common < all01.sql > all01.txt
```

## テーブル名が g で始まるものの一覧

```sql:g01.sql
SELECT table_name FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema') and table_name like 'g%' order by table_name;
```

実行例

```bash
psql -Uscott db_common < g01.sql > g01.txt
```
【備忘録】Google ColabでStreamlit【Display編】

# はじめに

Google ColabでStreamlitを使ってWebアプリを作成し、様々な機能について試してみます。

Webアプリの起動までは以下のページを参考にしてください。

https://qiita.com/firesign2023/items/29a219b88b5b8f4ee502


# Toast

Toast messageを表示する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/010306f3-791f-7782-afe9-5ce92a1cb77c.png)

~~~python
st.toast("Warming up...")
~~~

# メッセージ

InfoやErrorなどのメッセージを表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/4aad6ff0-d6d8-ec53-7d78-bdfee055aafb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/0dad7528-0b2a-7bcf-ebc3-db3aef084001.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/3690518b-8b1b-8009-6f4e-155ea85729ee.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/7b293f8e-8bd1-424d-9672-b563a6245d73.png)

~~~python
st.error("Error message")
st.info("Info message")
st.warning("Warning message")
st.success("Success message")
~~~




# Balloons

バルーンを飛ばす

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/8b600d53-e220-af44-5dfc-28432ec6f605.png)

~~~python
st.balloons()
~~~


# Snow

雪を降らせる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/a0cb32c4-f7e4-a618-1d5b-261180f96f56.png)

~~~python
st.snow()
~~~