OmniAICreator/Qiita-1.07M huggingface dataset:
PHP: Swift Mailer の使い方

## ライブラリーのインストール

```bash
composer require swiftmailer/swiftmailer
```

次の警告が出ますが、使えます。

```text
Package swiftmailer/swiftmailer is abandoned, you should avoid using it. Use symfony/mailer instead.
```

## プログラム

ツリー構造

```text
$ tree -L 2
.
├── composer.json
├── composer.lock
├── swiftmailer.php
└── vendor
    ├── autoload.php
    ├── composer
    ├── doctrine
    ├── egulias
    ├── swiftmailer
    └── symfony
```

```php:swiftmailer.php
<?php
require_once 'vendor/autoload.php';

// 送信設定
$transport = new Swift_SmtpTransport('hi-ho.mose-mail.jp', 587);
$transport->setUsername('user@hi-ho.ne.jp');
$transport->setPassword('password');

$mailer = new Swift_Mailer($transport);

$str_out = 'Hello,Everybody
Test
';
$str_out .= 'Dec/20/2023
';
$str_out .= 'Dec/20/2023
';
$str_out .= 'Dec/20/2023
';
// メール作成
$message = new Swift_Message('Test Message PM 16:45');
$message->setFrom(['user@hi-ho.ne.jp' => 'Uchida']);
$message->setTo(['user@example.com']);
$message->setBody(
	$str_out, 'text/plain'
);

// メール送信
$result = $mailer->send($message);
var_dump($result);
```

## 送信

```bash
php swiftmailer.php
```

```text
$ php swiftmailer.php 
int(1)
```

## 送信結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/20982005-7b0b-a9b3-e748-fc027def4cbb.png)

## 確認したバージョン

```text
$ php --version
PHP 8.2.10-2ubuntu1 (cli) (built: Sep  5 2023 14:37:47) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.10, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.10-2ubuntu1, Copyright (c), by Zend Technologies
```
GitHubActionsのワークフローを強制的にキャンセルする

## GitHubActionsのワークフローがいつまで経っても終わらない・・・！
GitHubActionsのワークフローが実行待ち/実行中のまま、いつまで経っても終わらないことはありませんか？
私はちょこちょこあります。
ワークフローのキャンセルボタンを押しても、全然終了してくれないのです。

こういうときは、翌日になってもそのままです。

### 困っている方々の声
 :point_down: 2019年から2023年に至るまで、「まだ発生しているんだけど！！！」という怒りの声が詰まっているコミュニティのディスカッション
https://github.com/orgs/community/discussions/25570


## 強制的にキャンセルする前に要確認
- runnerがself-hostedの場合、self-hostedが正常に稼働しているかを確認しましょう。ワークフローがいつまで経っても開始/終了しない理由が、runnerにある可能性があります。
- 大丈夫だったら、思い切って強制終了しちゃいましょう。


## ワークフローを強制終了する！！！
このforce-cancelというAPIを叩けば、強制終了できます。
下記の`OWNER` `REPO` `RUN_ID`の3点を、終了したいものに合わせて変えてから、ターミナルで実行してください。
もしtypoがあると、404が返ってきます。
正常終了すると{}だけ出力されます。

```
$ gh run list
-> runs_idを確認する

$ gh api \
  --method POST \
  -H "Accept: application/vnd.github+json" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  /repos/OWNER/REPO/actions/runs/RUN_ID/force-cancel

$ gh run list
-> ワークフローが終了していることを確認

```

https://docs.github.com/ja/rest/actions/workflow-runs?apiVersion=2022-11-28#force-cancel-a-workflow-run
エクセルのワークシートを直接開くショートカット作成方法を探したけど見つからなかった

# やりたいこと

エクセルの特定シートを開くようなショートカットを作りたい。
エクセル自体にマクロやVBAは仕込みたくない。
VBSでエクセル操作もしたくない。

# ChatGPTくんの答え

なんかいけそうなショートカットパスだったけど、これだとダメでした。

```
"C:\Program Files\Microsoft Office\root\OfficeXX\EXCEL.EXE" "path\to\your\file.xlsx" -e "SheetName"
```

```
"C:\Program Files\Microsoft Office\root\OfficeXX\EXCEL.EXE" "path\to\your\file.xlsx"#SheetName
```

# ネット検索したけど見つからず

『エクセル自体にVBA仕込む』『VBSで操作する』みたいな方法くらいでした。

# 参考サイトさん

https://xtech.nikkei.com/it/article/COLUMN/20071204/288714/

https://oshiete.goo.ne.jp/qa/6488098.html

https://ameblo.jp/peco-1002/entry-12720456684.html

https://nextrpa.com/excel/excel-fileopen-jp.php
SUQLという技術の論文を読んだ感想と活用方法の検討

## はじめに

この記事では「SUQL: Conversational Search over Structured and Unstructured Data with Large Language Models」という論文でLLMを利用して構造化データと非構造化データを検索できるSUQLという技術について書かれていたので概要と活用できそうなことを考えた内容を書いてみました。

原論文は以下のリンクから読めますのでそちらをご参照ください。
- 論文名: SUQL: Conversational Search over Structured and Unstructured Data with Large Language Models
- 著者：Shicheng Liu, Jialiang Xu, Wesley Tjangnaka, Sina J. Semnani, Chen Jie Yu, Gui Dávid, Monica S. Lam
- 公開日：2023年11月16日
- URL：https://arxiv.org/abs/2311.09818


## SUQLとは？
構造化データと非構造化データからなるデータの両方にまたがる会話形式の検索に焦点を当てた技術。

例えば数値で表されるようなデータとテキストを持つようなデータを同時に持っている場合、SUQLを使用することで解析を行うことができるようになるとのことです。

SUQLは、テキストを処理するための機能をSQLをもとに追加しています。
githubでインストールの仕方や使い方などがREADMEに記載されていますが、中身を見てみるとPythonで書いたユーザー定義関数をPostgreSQLで使えるようにしているようです。
https://github.com/stanford-oval/suql/tree/main

## SUQLで拡張されている機能
SUQLではSQLのテキスト型を使って新しいテキストの型を導入しています。
新たな型をもとにしてSUQL特有の機能を拡張しているようです。
それぞれの関数や機能はLLMを活用することで実現されています。

### answer関数
answer関数は、例えば、reviewsというレストランのレビューの内容が記載されているカラムがある場合、answer(reviews, 'このレストランは家族向けですか？')と書くことで、レビューの内容からレストランが家族向けかどうかを判定できます。
Where句の条件文として記載することができます。

### summary関数
Summary関数は、テキスト情報の概要が必要な場合に使用されます。例えば「レストランAのレビューを要約する」はSELECT summary(reviews) FROM Restaurants WHERE name = 'A';として表現できます。

### =演算子のオーバーロード
SUQLでは、例えば、料理の傾向を持つcuisinesというカラムがあったときに'coffee' = ANY(cuisines)という式は、料理属性が'コーヒー'である場合だけでなく、関連する他の料理の値（例: 'コーヒー＆ティー'、'カフェ'）に対してもTrueと評価されます。

## 活用できそうな場面
論文を読んでみて業務に活かせそうなことがないかと考えてみました。

#### 不具合分析
- 目的：検証中に記録されたバグレポートの分析
- データの種類：
  - 構造化データ：バグランクなど。
  - 非構造化データ：事象や機能名など。
- 類似している事象や機能からバグランクなどの構造化データに紐づけた分析を行い、傾向を分析する。

#### 研修用のアンケートの分析
- 目的：研修後のアンケート結果を分析する。
- データの種類：
  - 構造化データ：数値による研修の評価。
  - 非構造化データ：研修に対してのコメントや感想。
- 特定のキーワードや感情が含まれるアンケートが高評価か低評価かといった分析。

#### 進捗分析
- 目的：タスクの進捗状況を分析する。
- データの種類：
  - 構造化データ：タスクの完了率。
  - 非構造化データ：進捗報告のテキスト
- 進捗報告と完了率からのボトルネックの発見。

## 感想
論文の中では金融や法律などの分野固有の応用などについて触れられていましたが、
汎用的に使うことができれば分析という作業において様々な現場で使うことができそうだと感じました。 
現状だとGithubに記載されている使い方はPostgreSQLを使っていましたが、他のDBでも応用ができれば使う場面が増やすといったこともできそうです。

使用するデータのテーブル情報などについてはプロンプトで指示していくことが必要となりますが、この点などもカスタマイズしていけば応用する幅が広がりそうです。

論文を読んでみただけの感想にはなりますので、Githubにある説明をもとに年末年始にもし空き時間があれば触ってみて業務に応用することができないかを動作させてみた内容をもってさらに検討してみたいと思います。

## 参考
https://arxiv.org/abs/2311.09818

https://github.com/stanford-oval/suql/tree/main
STM8で温度計を作る(STTS751)(I2C)


STM8で温度計を作る(STTS751)


目的
STM8のテスト
PE1 PE2

いろいろ
動いてちょっとうれしい


![o_cop872.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/bccbdd4c-e176-8b0b-cb95-ace88e66e333.jpeg)

![o_cop873.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/9446745b-6e2b-f9a2-110f-1e9fbbf9cdc6.jpeg)


```c++



//STTS751_STM8_1


//インクルド
#include "I2C.h"


//定義
#define STTS751 0x39


//初期化
void setup()
{

  //シリアルの初期化
  Serial_begin(9600);
  Serial_println_s("START");

  //I2Cの初期化
  I2C_begin();

}//setup


//メインループ
void loop()
{
  uint8_t val; //センサーの値

  //内部アドレスを0番にする
  I2C_write(STTS751, 0);

  //温度の読み出し
  I2C_read(STTS751, 1);
  val = I2C_receive();

  //温度の表示
  Serial_print_s("TEMP=");
  Serial_print_u(val);
  Serial_println();

  delay(1000);//1秒待つ

}//loot



```
Qiita CLIを始めてみた


今更感はありますが、Qiita CLIがリリースされたということだったので、もう何年も記事などまったく投稿していないというのになぜか使ってみようと思い立ちました。

少し検索してみればいろいろな方が関連する記事を上げてくれているのでインストール自体は問題なく完了。早速記事を書いてみようかと思って、記事作成のコマンドを確認するとこんな感じ。

```bash
npx qiita new 記事のファイルのベース名
```

「こんな時、記事のファイルのベース名とかって考えるの面倒くさいよな」などとふと考えてベース名を作るスクリプトを作ることにしました。

といっても非常に簡単な作りで、実行時のシステム日付を取得してそこからMD5ハッシュを求めればいいかなと安易に考えたのが次のスクリプトです。ベース名を考えるだけではなくサブプロセスで記事作成コマンドも実行します。

```python
import hashlib
import datetime
import subprocess


def newid():
    now = datetime.datetime.now()
    timestamp = now.strftime('%Y%m%d%H%M%S')
    md5 = hashlib.md5(timestamp.encode('utf-8')).hexdigest()
    return md5


def main():
    id = newid()
    cmd = "npx qiita new %s" % id

    result = subprocess.run(
        cmd,
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True
    )
    print(result.returncode)
    print(result.stdout)


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

スクリプトを実行すると次のようなFrontmatterが含まれるマークダウンファイルが作成されました。どうやら指定したベース名がtitleに書かれるみたいです。

ファイル名: `f60698f78b6b0468c60eddc1a5cfa1b4.md`

```markdown
---
title: f60698f78b6b0468c60eddc1a5cfa1b4
tags:
  - ''
private: false
updated_at: ''
id: null
organization_url_name: null
slide: false
ignorePublish: false
---
# new article body
```

しかし、いざ使ってみるとMD5ハッシュなのでファイル名は32文字と長いし並び順もわかりにくいのではないかと考え直して修正したのが次のスクリプトです（ID生成部のみ抜粋）。

```python
def newid():
    now = datetime.datetime.now()
    timestamp = now.strftime('%Y%m%d%H%M%S')
    return '{:x}'.format(int(timestamp))
```

タイムスタンプを数値とみなして16進数に変換したものをベース名にしてみました。これならファイルは作成した順序で並ぶはずだから前述のMD5ハッシュを使った時よりわかりやすいのではないでしょうか。

ということでしばらくこれを使ってみようかなと考えています。

ファイル名: `126672b0a357.md`

```markdown
---
title: 126672b0a357
tags:
  - ''
private: false
updated_at: ''
id: null
organization_url_name: null
slide: false
ignorePublish: false
---
# new article body
```

まあ、「タイムスタンプをそのままベース名として使えばいいのでは」というご意見はもっともだなと素直に受け入れたいと思います。
【Python入門】openpyxlを使ってみる

Body:この記事は、[【完走したい】楽しくいろいろやる Advent Calendar 2023](https://qiita.com/advent-calendar/2023/notbeginner)の12日目です。
PythonでExcelを作れると聞いたので、自分でも試してみます。
googleにColaboratoryとかいうのがあって、無料でpythonを学習できたのでこれを使います。

https://colab.research.google.com/?hl=ja#scrollTo=5fCEDCU_qrC0

# Excelを動かす
Excelをpythonで動かせます。同じ作業を繰り返すときなどに便利です。
Pythonのopenpyxlを使ってExcelファイルを作ると、作成者がopenpyxlになります。
![スクリーンショット 2023-12-19 192829.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/ff28f26f-8b58-6526-2165-ffae1d2b5a4f.png)

# どうやって動かすか
以下のように作ります
```Python
import openpyxl as px
#　pythonでExcelファイルを動かすにはこれが必要です
def AdventA():
   #　:をつけるとTabキーを打った状態になる
   wb = px.Workbook()
   # openpyxlはpx。pxのexcel(workbook)
   ws = wb.active
   # 現在のシート
   wb.save("AdventTest2023.xlsx")
AdventA()
```
必要と思われる個所には説明を加えました。
まず、importでopenpyxlをpxという名前でインポートします。
Workbookがwbという名前で動くようにします。
Wsで現在のシートを表せるようにしています。
最後に、saveを使ってExcelを生成します。
まっさらで何も書かれてないExcelが生成できました。
# いろいろ書きこむ
for文などを組み合わせることで、繰り返し処理をさせることができます。
せっかくなので、100行目まで一列目に1から順番に数字を入れて、2列目(n<=100)に1から100までの数字を入れてみます。100が出たら、あたりに変えます。
```python
import openpyxl as px
import random
from random import randint

def AdventB():

  wb = px.Workbook()
  # openpyxlはpx。pxのexcel(workbook)
  ws = wb.active
  # 現在のシート
  for a in range(1,100):
    ws.cell(row=a, column=1, value=a)
    RndA = randint(0, 100)
    if RndA == 100:
      Tex = "当たり"
    else:
      Tex = RndA
      
    ws.cell(row=a, column=2, value=Tex)
   
    a = a + 1
  wb.save("AdventTest2023.xlsx")
AdventB()
```
できました。
これを実行してできたExcelファイルが
![スクリーンショット 2023-12-20 161641.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/b69fe8df-7aab-0c10-24b1-2d1b65cdf16e.png)

できました。
# まとめ
Excelファイルはpythonでも作れる。

参考

https://atmarkit.itmedia.co.jp/ait/articles/2202/08/news031.html
ChatGPT新規登録【2023/12/20版】

# 概要
ChatGPTを利用するために必要な登録を行う.
また,簡単に使い方を記録する.

**用意するもの**
 - Googleアカウント
 - 電話番号(要検証)

:::note info
重要情報 : 2023/12/20
登録方法確認のために新規アカウントで試したところ
**電話番号が不要でアカウント登録できました.**
OpenAIの設定が変わったのか,どこかにキャッシュ等があって不要だったのか不明なので,要調査とします.
:::


正直いろんな場所で書かれてある内容なので,この記事に特別な価値はありません.下記にもっと詳しく書いてあります.

https://aismiley.co.jp/ai_news/chatgpt-tsukattemita/

# アカウント登録
以下,アカウントの登録方法を記載します.
## ①公式サイトへ
下記のサイトに飛びます.

https://chat.openai.com/auth/login

## ②「Sign up」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/90b9d0cd-a141-2148-6c43-8b4229f29ad5.png)

## ③「Continue with Goole」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/a06bd3d9-fd1d-0efd-082d-905a443ee2a9.png)

## ③「紐づけたいアカウント」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/2503c58a-6698-5a54-054c-bc318ef30bba.png)

## ③‐2 本人認証をします.(状況次第で出たりでなかったりします.)
メールにパスワードが届いたり,GoogleAuthenticaterにパスワードが届いたりしますので,各自お願いします.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/a5c59287-898e-c3bc-3bfe-2318e2939a3a.png)

## ④個人情報入力
個人情報入力画面に移ります.
ここら辺は忘れない範囲で適当に入力しましょう.
おそらくChatGPTのインターフェースで表示される名前となるので,わかる名前にしましょう.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/3e6df324-a105-788e-ef8e-9b3dfa50d811.png)

## ④-2 電話番号不要！？(要検証)
大体のサイトでは,電話番号が必要とされています.
しかし今回作成したGoogleアカウントでは電話番号を聞かれませんでした.

## ⑤ChatGPT使用可能
認証が終わると,ChatGPTが使えるようになる画面になるかと思います.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/d3deb653-52d1-d5dc-38f6-a9939684f1bc.png)


## エラーケース
こういう画面が出たら,失敗です.
アカウント作成に成功していてもこの画面が出ることがあるので,
一度ログインを試みてください.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/11361272-a37e-7765-6ac7-155369017193.png)

# 簡単な使い方
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/0d88ddd9-3ee9-8b33-5962-3b306335ba3f.png)

下のチャット入力欄に調べたいこと,話したいことを入力すると,ChatGPTが返答してくれます.

左のタブには,会話のスレッドが表示されます.
スレッド名は[・・・]部分から編集できます.

# 終わりに
ChatGPTの新規登録に電話番号が不要になった可能性が高い.
これはユーザーがもっと増える可能性がある！

# 追加テスト
以下を調べてみよう

 - ソースコード生成問題
     - 下記のサイトを用いてJavascriptで「FizzBuzz」を作成してみよう.
     - https://paiza.io/ja/projects/new

:::note info
**注目ポイント** 
そもそもFizzBuzzとは何か知りたい
ソースコードを出力したい
動かした結果エラーが出たが,どう対処すればいいか質問したい
:::

 - 法律についての問題
     - 休日出勤と振出による土日出勤の違いを調べる

:::note info
**注目ポイント** 
労働基準法的にどういう扱いになっているか？
給料面にはどう影響するか？等
:::

 - 創造的な問題
     - 3歳の子供に読み聞かせる物語を作成してください
     - 子供はウサギが好きです

:::note info
**注目ポイント** 
どのような口調にすれば子供に喜ばれるか？
文章の量はどれくらいが適切か？
物語の内容をちょっと変えてみるにはどうすればいいか？
:::
ros2bagをカットできる!!

# はじめに

こんにちは!!B4の黒田です!!
本記事は，ros2bagをカットする方法についてです!!

1. git cloneからbuildまでの流れ
1. 実際にros2bagをカットする

※重要
OS: ubuntu22.04
Supported ROS: galactic，humble
/HOME内でCtrl+Hを押して，.bashrcを開く．
.bashrc内に
```
$source /opt/ros/humble/setup.bash 
$source /opt/ros/galactic/setup.bash
```
上記の2つの内，1つ書いてあればOK!!
次の，buildする際に必要です．

## 1. git cloneからbuildまでの流れ

まずは，下記のurlを開いてください!!
「https://github.com/tier4/ros2bag_extensions」

これからbuild，git cloneします．
```
$mkdir -p $HOME/extension_ws/src
$cd $HOME/extension_ws/src
$https://github.com/tier4/ros2bag_extensions.git
$source /opt/ros/humble/setup.bash 
$rosdep install --from-paths . --ignore-src --rosdistro=${ROS_DISTRO}
$colcon build --symlink-install --catkin-skip-building-tests --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Release
```

上記のコマンドを打つ上で，
```
$sudo apt install python3-rosdep2
```

## 2. 実際にros2bagをカットする

ros2 bag slice

```
$cd extension_ws/
# 1. from 1629430104.911167670 to the bag end time
$ros2 bag slice input_bag -o sliced_from -s 1629430104.911167670

# 2. from the bag start time to 1629430124
$ros2 bag slice input_bag -o sliced_till -e 1629430124

# 3. from 1629430104.911 to 1629430124
$ros2 bag slice input_bag -o sliced_between -s 1629430104.911 -e 1629430124
```
上記の「1」を用いて例を書きます．
```
$cd extension_ws/
$ros2 bag slice '/home/megken/0_data/kota/bag/2021-10-14_run2_cut' -o sliced_from -s 1634174820.738
```

また，startとendの時間はコマンドで見ることができます
```
$ros2 bag info '/home/megken/0_data/kota/bag/2021-10-14_run2_cut' 
```
![Screenshot from 2023-12-20 16-11-31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3305414/b39bbe39-b712-890d-8175-d171ff9ff93d.png)

以上です．
【Python入門】Pythonの基礎を学ぶ　

この記事は、[【完走したい】楽しくいろいろやる Advent Calendar 2023](https://qiita.com/advent-calendar/2023/notbeginner)11日目です。
Google Colaboratoryを使って勉強します。
間違ってたらごめんなさい。
# pythonとは
よく使われる言語のひとつです。
# 使いかた
### import
最初にimportするものを宣言します。
例えば、「numpy」を使う場合
```
import numpy as np
# import 名前 as 略称（別名）
```
とか書きます。
asの後に書いた名前でその後呼ぶことになります。たいていのものはすでに決められています。
### def
define(定義)の略です。書いたプログラムをまとめることができます。書き方は、
```
def A():
 ここに内容を書く
A()
```
といった感じに、
```
def 任意の名前():
```
ではじめます。
```
任意の名前()
```
で終割ることもありますが、省略できます。
↓こんな時に便利です
```
# PythonTest
import numpy as np

def A():
  a=1
  print(a)
A()
def B():

  b=2
  print(b)
B()

```
defが二つあります。ここで新しく、
```
A()
```
とか書きます。
新しくというのは、
![スクリーンショット 2023-12-20 090209.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/62ccd017-69fd-a5e6-f74c-5c750342864c.png)
こんな感じで新しくコードを書くということです。
すでに答えが出ていますが、A()と書くと、上で定義したAだけが実行され、Bは実行されません。使い分けたいときにdefは非常に便利です。
せっかくなので、def 任意の名前　の後に来る()と:の意味についても書いておきます。
### ()
()の中には引数を入れることができます。
引数の例）
```
def TestA(A):
  if A==1:
    print("OK")
  else:
    print("NG")
TestA(1)
```
これを実行すると、OKが出力されます。引数は、Aです。
defの最後に「任意の名前()」を書くといいましたが、()の中身は一番上の()と対応しています。
例２）
```
# A,Bは最後の1,2と対応
def TestA(A,B):
  if A==1:
    if B==2:
     print("OK")
    else:
      print("NG")
  else:
    print("NG")
TestA(1,2)
```
もちろんOKが出ます。
defの中でAの値を変えることもできます。
変数とそこまで変わらないと思います。（細かな違いがあるようですが、よくわかりませんでした。）
### return
引数の中身を見れます。
```
def TestA(A,B,C):
 
  return A,B,C
TestA(1,1,3)
```
結果は(1, 1, 3)になります。律儀にかっこを付けて返してくれます。
### for 
繰り返しです。
```
for a in range(1,100):
```
こんな感じで書けます。a はrangeで1から100までだと言っています。
これでaは1から始まって100まで繰り返されます。
# まとめ
もっといろいろ書くことはあると思うので、また学んだら記事に書こうと思います。
参考

https://tutorials.chainer.org/ja/08_Introduction_to_NumPy.html

https://www.javadrive.jp/python/userfunc/index3.html
Steam Deckのデスクトップモードを試してみる日

Steam Deckにはデスクトップモードなる機能があるらしい。
つまりはゲーム機というよりも持ち運びサイズのゲーミングPCという訳である。
# デスクトップモードを起動してみよう
手順は以下の通り
1. 電源を付け、ホーム画面に移動
1. 電源ボタンを長押しし、電源メニューを表示
1. `デスクトップに切り替え`を選択しデスクトップモードに切り替え

### 1. 電源を付け、ホーム画面に移動
![ダウンロード.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649647/4b684ac4-8eac-2125-5df0-9a79874082e7.jpeg)
### 2. 電源ボタンを長押しし、電源メニューを表示
![ダウンロード (1).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649647/6a037854-bc6f-ee55-8036-c69dc46a86d0.jpeg)
### 3. `デスクトップに切り替え`を選択しデスクトップモードに切り替え
![Screenshot_20231220_033535.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649647/25d0907e-82ad-583f-2086-d8ce07500bd6.png)
しっかりとPC然とした画面が表示される。
基本的な操作方法は以下
| 動作                     | キー(キーコンフィグに依存する為、割り当て変更をしている場合は注意) | 
| ------------------------ | ------------------------------------------------------------------ | 
| 左クリック               | R2(又はタッチも可能)                                               | 
| 右クリック               | L2                                                                 | 
| マウス操作               | 右ジョイスティック                                                 | 
| スクリーンキーボード起動 | steamボタン+X                                                      | 

その他操作は以下を参照

https://gamers.wariichi.com/blog/steamdeck-basic-operation/

ゲーミングモードに戻る際は、デスクトップの`Return to Gaming Mode`を選択して戻る
#### デスクトップモード時のスクリーンショット
ゲーミングモード時は`Steamボタン+R1`にてスクリーンショットが起動するが、デスクトップモードでは適用されない。
デスクトップモード時は
1. スタートメニューを開く
1. `Utilities` -> `Spectacle`を選択
1. 起動したウィンドウにて`Save`を選択

これによって`Spectacle`ウィンドウを除いたスクリーンショットが撮影される。
# Pythonを動かしてみよう
物理キーボードが手元に無い異常環境なので非常に苦労した。
取り敢えずスタートメニューから`terminal`と検索し、コンソールを開いてみる。
![Screenshot_20231220_034430.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649647/6248072a-bb6e-6549-d491-8a3bbf59cb13.png)
スクリーンキーボードに苦労しつつも、なんと初めからpythonが入っている事が確認出来た！
折角なのでHello World
![Screenshot_20231220_035834.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649647/318f2a27-c0cf-4e36-06d3-586ab11bcb73.png)
しっかりpythonが起動され、Hello World出来ている。
(ちなみにvimもnanoも標準で入っている)
# 他のPCにSSHさせてみよう
https://qiita.com/pokurin123/items/20eeaeb0117f65321dca

以前書いたこの辺と組み合わせてRaspberry PiにSSH出来ればお手軽にラジコンとかが作れそう。
前段階として適当なPCにSSH接続させてみると...
![Screenshot_20231220_152108 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649647/e891839f-795c-ba4c-384d-97e6c06627db.png)
すんなり出来た。
# 他のPCからSSHさせてみよう
逆にSteam Deckに接続してみよう。
基本的には以下の記事の通り

https://zenn.dev/akibaburari/articles/392d51a6baf053

```bash: steam deck
# rootのパスワードを設定
$ passwd

# SSHを有効化
$ sudo systemctl start sshd
$ sudo systemctl enable sshd

# ユーザ名を確認
$ whoami

# ipアドレスを確認
$ ip a
```
あとは普通に`SSH user@ipアドレス`で接続
![スクリーンショット 2023-12-20 15.31.12 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649647/354ebbee-aa26-27ba-f25c-a42ab59032c2.png)
# 終わりに
触っていたら小さい頃にゲーム機替りに持っていたポケットサイズの変なPCを思い出した。
どちらにせよ物理キーボードが無いとデスクトップモードは厳しいな〜
【PostgreSQL】oid2nameツールについて

## はじめに
PostgreSQLは、パワフルなオープンソースのリレーショナルデータベースシステムであり、その機能の一部としてさまざまな管理ツールを提供しています。その中の一つが、oid2nameツールです。この記事では、oid2nameツールの基本的な使い方や、それがどのように役立つのかについて解説します。

## OIDとは？
OIDとはObject Identifierの略で、PostgreSQL内で各オブジェクト（テーブル、インデックス、関数など）を一意に識別するためのIDです。このOIDは、内部的な管理やデバッグ作業で非常に重要な役割を果たします。

しかし、OIDは通常のSQLクエリからは見えないため、OIDと対応するオブジェクト名を調べるのは一見難しそうに思えます。そこで登場するのが、oid2nameツールです。

### oid2nameツールとは？

oid2nameは、PostgreSQLが提供するコマンドラインツールの一つで、OIDから対応するオブジェクト名を調べるためのツールです。逆に、オブジェクト名からOIDを調べることも可能です。

このツールを使用すると、対象データベースに接続し、OID、ファイルノード、テーブル名情報を抽出します。
また、データベースOIDまたはテーブル空間OIDを示すようにさせることもできます。

### oid2nameの基本的な使い方

oid2nameツールはコマンドラインから使用します。基本的な使用方法は以下の通りです。

```
oid2name -d [データベース名] -t [テーブルOID]
```

このコマンドを実行すると、指定したデータベースの指定したテーブルOIDに対応するテーブル名が表示されます。

逆に、テーブル名からOIDを調べることも可能です。その場合は以下のように使用します。

```
oid2name -d [データベース名] -T [テーブル名]
```

### oid2nameの活用方法

oid2nameツールは、特にデータベースのデバッグ作業において便利です。

例えば、データベースのログにOIDが記録されている場合、そのOIDが何のオブジェクトに対応するのかを素早く調べることができます。また、OIDとオブジェクト名のマッピングを一覧表示することで、データベースの構造を理解するのに役立ちます。

さらに、oid2nameは他のPostgreSQLの管理ツールと組み合わせて使用することも可能です。例えば、pg_dumpツールでデータベースのバックアップを取る際に、特定のテーブルだけをバックアップするためのOIDを調べるのにoid2nameを使用することができます。

### まとめ

oid2nameは、PostgreSQLのOIDとオブジェクト名間のマッピングを調べるための強力なツールです。データベースのデバッグや管理作業において、このツールを活用することで作業の効率を大幅に向上させることが可能です。

また、oid2nameはコマンドラインから簡単に使用することができ、他のPostgreSQLの管理ツールと組み合わせて使用することも可能です。PostgreSQLを使用している全てのデータベース管理者にとって、oid2nameツールの理解と活用は非常に有用です。
WebAPIについて

# `WebAPIについて`

皆さんはWebAPIという言葉をご存知でしょうか。WebAPIとは、APIの呼び出しをWeb上で行うAPIのことを指します。現在はかなりWebAPIの利用が進んでいるため、APIというとWebAPIのことを指すことも多いみたいです。

WebAPIがどんなものか簡単に説明すると、Web上でプログラム同士が会話するようなものです。例えばですが、スマートフォンの天気のアプリに<font color="skyblue">「今日の天気はどうなりますか。」</font>や<font color="skyblue">「気温はどうなりますか。」</font>などと聞いて、その情報を取得して表示するような仕組みです。

API(Application Programming Interface)というのは、アプリケーションや、ソフトウェアが情報のやり取りをする際に使われるインターフェースのことです。APIを使用することで異なるソフトウェアやアプリケーションなどの統合をしてくれます。

身の回りでも多く利用シーンがあるWebAPIですが、どのような場面で使われているのかをいくつか紹介したいと思います。

<font color="Green">1.ソーシャルメディア連携</font>:異なるウェブサイトやアプリケーションでアカウントのログインを行う際などに使用されます。そして、異なるプラットフォームで色々なデータを共有することができるようになります。APIを使用しているため安全な連携が可能になっています。
(Instagram、Spotifyなど)

<font color="Green">2.位置情報サービス</font>:位置情報や地図を利用するアプリケーションなどはAPIを利用し、地理データを取得しています。経路情報なども見ることが可能でとても便利です。
(Google Mapsなど)

<font color="Green">3.支払い処理</font>:オンラインでの決済でもAPIは使用されています。APIを通じて決済できるゲートと通信することによってクレジットカードやデジタルウォレットを介して決済を処理しています。
(Apple Payなど)

ここまでWebAPIについて簡単にですがまとめてきました。冒頭でもWebAPIの利用シーンが多いと述べましたが、本当にさまざまな場面で使われており、必要不可欠なものとなっています。新しいアプリケーションの開発を一から始めるというのはとても大変なことで、ITの人材が不足している中で始めるとなると更に難しいです。ただ、APIを公開することでそれらの問題は解決し、より良い発展も見込まれます。APIエコノミー(開発者が相互的に機能を共有していろいろなサービスを構築していくためにAPIを活用するという概念)という考え方がありますが社会にとってとても大切なことですし、それは今後もそうであり続けると思います。

WebAPIを使ったことがない人は便利なものなのでぜひ使ってみて欲しいと思います。使ったことがある人は自分が欲しいと思うものを作ってみるのも面白いかもしれません。


参考
https://blog.hubspot.jp/website/api-web
https://techmania.jp/blog/interface0004/
Sonar Scan/Qube：(error) java.lang.IllegalStateException: Unrecoverable indexation failures


Sonar Scannerを実行した後、下記のようなエラーが出ていました。

```
java.lang.IllegalStateException: Unrecoverable indexation failures: 1 errors among 1 requests
	at org.sonar.server.es.IndexingListener$1.onFinish(IndexingListener.java:39)
	at org.sonar.server.es.BulkIndexer.stop(BulkIndexer.java:131)
	at org.sonar.server.measure.index.ProjectMeasuresIndexer.doIndex(ProjectMeasuresIndexer.java:162)
	at org.sonar.server.measure.index.ProjectMeasuresIndexer.indexOnAnalysis(ProjectMeasuresIndexer.java:87)
	at org.sonar.ce.task.projectanalysis.step.IndexAnalysisStep.execute(IndexAnalysisStep.java:45)
	at org.sonar.ce.task.step.ComputationStepExecutor.executeStep(ComputationStepExecutor.java:81)
	at org.sonar.ce.task.step.ComputationStepExecutor.executeSteps(ComputationStepExecutor.java:72)
	at org.sonar.ce.task.step.ComputationStepExecutor.execute(ComputationStepExecutor.java:59)
	at org.sonar.ce.task.projectanalysis.taskprocessor.ReportTaskProcessor.process(ReportTaskProcessor.java:81)
	at org.sonar.ce.taskprocessor.CeWorkerImpl$ExecuteTask.executeTask(CeWorkerImpl.java:212)
	at org.sonar.ce.taskprocessor.CeWorkerImpl$ExecuteTask.run(CeWorkerImpl.java:194)
	at org.sonar.ce.taskprocessor.CeWorkerImpl.findAndProcessTask(CeWorkerImpl.java:160)
	at org.sonar.ce.taskprocessor.CeWorkerImpl$TrackRunningState.get(CeWorkerImpl.java:135)
	at org.sonar.ce.taskprocessor.CeWorkerImpl.call(CeWorkerImpl.java:87)
	at org.sonar.ce.taskprocessor.CeWorkerImpl.call(CeWorkerImpl.java:53)
	at com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.runInterruptibly(TrustedListenableFutureTask.java:125)
	at com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:69)
	at com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:78)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)

```


原因：
ストレージ足りないようです。flood stage disk watermark [95%] exceeded

解決方法：
１、log fileを探す

 ```
 $ sudo find / -name es.log\* | less

```

２、es7 folderを削除




 参考：https://stackoverflow.com/questions/74913401/sonarqube-unrecoverable-indexation-failures-1-errors-among-1-requests-check-el
SNDPTFORD DLVRYFMT(*SAVF)  でPTFをオーダーする場合、長時間、入力不可で画面が占有されることがあります 

累積PTFやグループPTFなどのサイズが大きいPTFを配信形式*SAVFでオーダーする場合、ダウンロード中、対話型セッションが長時間、入力不可で占有され使用できなくなります。
例えば、HAのグループPTF SF99676を「配信方式=*SAVF」で取得してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633718/ec66240e-91de-0e4d-ed24-f1cfa4af5b66.png)

9:37にSNDPTFORD PTFID((SF99676))を実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633718/ef17af19-f546-7751-3299-a030519e0258.png)

しかし、14:00になっても下図のようにX SYSTEM（入力不可）で5時間近く対話型画面が占有されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633718/3b56c4f3-c1bd-3b88-e5df-2cc9d8b5381d.png)

結局、終了したのは15:58:23でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633718/657fd9cf-769b-9f2f-7567-2e1ed40c19fa.png)



検証のため、サイズの大きい累積PTFを「配信方式=*IMAGE(DVDイメージ)」で取得してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633718/2b0da38c-2b60-9951-4896-a0a03c7b7e20.png)
5分程度で、「光ディスクイメージがダウンロード用に作成されます。」というメッセージが画面下部にでて、対話型画面が使えるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633718/dce7993a-2719-2dcc-a8cf-bb6aa136af60.png)
大きいサイズのPTFをダウンロードする場合、SNDPTFORDコマンドのDLVRYFMTパラメーターに気を付けましょう。
Azure VM を 一般化する  - Windows 編 -

本記事は、[Microsoft Azure Tech Advent Calendar 2023](https://qiita.com/advent-calendar/2023/microsoft-azure-tech) の 12/02 の投稿です。

こんにちは、アーキテクトのやまぱんです。
補足コメントや質問は是非お願いします🥺！
今回は一般化しイメージ化する際にAzure VM を一般化する必要があります、今回はAzure VM 一般化する手順についてご案内します。

なお、<font color="red">一般化した VM はログインできず、正常に使えなくなります。</font>
もしそれが困る場合はあらかじめ、Azure VM Backup や Azure VM を停止した状態 (整合性の観点から) でディスクスナップショットを取得しておいてください。
そうすることでそれらからリストア (複製) することが可能です。

なお今回は Window OS をベースにしています。
Linux の 一般化については[こちら](https://learn.microsoft.com/ja-jp/azure/virtual-machines/generalize#linux)を参考に実施してもらえればと思います。


## 一般化とは
一般化とは 仮想環境を使っている場合、環境内の仮想マシンで共通にしたい設定を行ってからOSテンプレートを作成することになります。 しかしながら、OSには仮想マシンごとにユニークにならないといけないパラメータがあります。 こういった値を削除・初期化して再度設定される状態にしておくことです。
Window の 場合は Sysprep が必要になります。

## Window VM 一般化 手順


+ 1.panther ディレクトリ (C:\Windows\Panther) を削除します。

+ 2.レジストリ操作
```cmd:cmd (Administrator)
reg add "HKLM\SYSTEM\CurrentControlSet\Services\cdrom" /v start /t REG_DWORD /d 1 /f
```
このコマンドは、Windowsのレジストリを変更してCD-ROMドライブのサービスを開始するものです。

+ 3.Sysprep 実行
```cmd:cmd (Administrator)
cd %windir%\system32\sysprep
sysprep.exe /oobe /generalize /mode:vm /shutdown
```
シャットダウンして立ち上がらないようにしておきます。

完了するとRDPが途切れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/17aa260c-d35e-eaac-a736-5219e7fb7241.png)

+ 仮想マシンのステータスを[一般化(Generalized)]に設定
Azure PowerShellや Cloud Shell で対象の Subscription にログインして下記のコマンドを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/5cd95249-9216-8ecb-79f8-f74a41d41664.png)

```Azure PowerShell:Azure PowerShell
Set-AzVm -ResourceGroupName $rgName -Name $vmName -Generalized
```
実行例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/35688a85-b593-59cb-75e8-c80ddb5000ff.png)


:::note warn
<font color="red">一般化した VM はログインできず、正常に使えなくなります。</font>
もしそれが困る場合はあらかじめ、Azure VM Backup や Azure VM を停止した状態 (整合性の観点から) でディスクスナップショットを取得しておいてください。
:::


## 参考
+ 親愛なる同僚の記事です。Azure VM  Imagae Builer を使ったイメージ作成方法について

https://qiita.com/ueda_it/items/7a3aade1e86944c431d1

+ Azure VM 一般化に関する公式ドキュメント

https://learn.microsoft.com/ja-jp/azure/virtual-machines/generalize

+ Microsoft の Azure VM サポートチームのAzure VM 複製に関するブログ記事
  
https://jpaztech.github.io/blog/vm/vm-replica-1/
VBA - OracleへのODBC接続とSELECT文の実行

### 前提条件
オラクルクライアントのインストール及び設定は完了済みであること。
参考文献-[Oracle Database 21c Clientのインストールを試す](https://qiita.com/plusultra/items/917849449835faa74e75)

### Excel側
セル"A1" に SQL SELECT 文を記載。
[SQL実行ボタン]クリック → イベント処理発動。

### 処理内容
A4行をヘッダー行とし、データは"A5"からスタート。
1000行目以降は、セルへの転記を回避。

```vb
Sub テキストボックス1_Click()

    Dim SQL As String
    Dim i As Long
    Dim row As Long
    Dim ws As Worksheet
    Dim dispRowMAX As Long
    Dim overFlag As Boolean

    Const Provider = "OraOLEDB.Oracle" 'Provider
    Const DATA_SOURCE = "hoge"           'Data Source
    Const USER_ID = "hoge"               'userid
    Const Password = "hoge"              'password

    Set ws = ActiveSheet
    SQL = Range("A1").Value
    
    
    'SQL文-空欄チェック
    If SQL = "" Then
        MsgBox "SQL文を指定して下さい。", Buttons:=vbExclamation
        Exit Sub
    End If
    
    Dim conn As New ADODB.Connection
        
    conn.ConnectionString = _
                    "Provider=" & Provider & ";" & _
                    "Data Source=" & DATA_SOURCE & ";" & _
                    "USER ID=" & USER_ID & ";" & _
                    "Password=" & Password & ";"
                    
    conn.CursorLocation = adUseClient
    
    conn.Open
    
    Dim rs As New ADODB.Recordset
    
    Range("A1").CurrentRegion.Offset(3, 0).ClearContents

    rs.Source = SQL
    rs.ActiveConnection = conn
    rs.Open
    
    overFlag = False
    
    If rs.RecordCount > 1000 Then
        MsgBox "1000行を超えています。" & vbCrLf & "1000行目以降は表示しません。", Buttons:=vbExclamation
        dispRowMAX = 1000 + 4
        overFlag = True
    Else
        dispRowMAX = rs.RecordCount
    End If
    
        
    With ws
        
        '列名の表示
        For i = 0 To rs.Fields.Count - 1
            .Cells(4, i + 1) = rs(i).Name
        Next i

        '値の表示
        row = 4
        
        If overFlag = True Then
            Do Until row = dispRowMAX
                For i = 0 To rs.Fields.Count - 1
                    .Cells(row + 1, i + 1) = rs(i).Value
                Next i
                rs.MoveNext
                row = row + 1
            Loop
        Else
            Do Until rs.EOF
                For i = 0 To rs.Fields.Count - 1
                    .Cells(row + 1, i + 1) = rs(i).Value
                Next i
                rs.MoveNext
                row = row + 1
            Loop
        End If
        
    End With
    
    rs.Close
    conn.Close
    Set rs = Nothing
    Set conn = Nothing
End Sub

```
:::note warn
警告
SELECT文以外のSQL処理も実行可能なはず。
なので、ご注意ください。
:::
既存のNext.jsプロジェクトにshadcn/uiを導入してみました | yarnでの導入

## はじめに
現在プログラミングスクールに通っている者です。個人開発をする中で、Next.jsプロジェクトを作成した後に、shadcn/uiを導入したいと思い公式サイトを確認していたのですが、いまいちよくわからなかったため導入した内容を備忘録として残したいと思います。

https://ui.shadcn.com/

:::note warn
注意
プロジェクトの内容によってはこちらのやり方で正しく動作するとは限らないため、一度テスト環境等で試していただくことをお勧めいたします。また、私の場合はyarnを使用しているため、基本的にはyarnを使用したセットアップとなることご了承いただけますと幸いです。
:::

## shadcn/uiの導入
プロジェクト内に移動してから実施してください。
まず、yarnを使用してshadcn/uiをプロジェクトに追加します。
```bash
$ yarn add shadcn-ui
```

インストール後、shadcn/uiの初期化を行います。

```bash
$ yarn shadcn-ui init
```
以下、選択していきます。入力項目もあるため、注意しながら進めてください。
```bash
yarn run v1.22.19
$ /app/node_modules/.bin/shadcn-ui init
✔ Would you like to use TypeScript (recommended)? … no / yes
✔ Which style would you like to use? › Default
✔ Which color would you like to use as base color? › Slate
✔ Where is your global CSS file? … src/app/globals.css
✔ Would you like to use CSS variables for colors? … no / yes
✔ Where is your tailwind.config.js located? … tailwind.config.js
✔ Configure the import alias for components: … @/components
✔ Configure the import alias for utils: … @/lib/utils
✔ Are you using React Server Components? … no / yes
✔ Write configuration to components.json. Proceed? … yes

✔ Writing components.json...
✔ Initializing project...
✔ Installing dependencies...

Success! Project initialization completed.

Done in 971.71s.
```

### 今回の私の選択肢
- TypeScriptの使用： `yes`を選択して、`TypeScript`を使用。
- スタイルの選択： `デフォルトスタイル`を選択。
- ベースカラー： `Slate`を基本色として、選択。
- グローバルCSSファイルの位置： 
    - `既存プロジェクトのglobals.css`の場所を指定します（私の場合：`src/app/globals.css`）
    - `デフォルト`では、`app/globals.css`となっているため要注意
    - Next.jsプロジェクト作成時のApp Routerの選択有無やsrcディレクトリの有無によって変わってくるかと思います。
- CSS変数の使用： ここではnoを選択。
- tailwind.config.jsの位置： `既存の設定ファイル`の場所を指定。（私の場合はそのまま）
- コンポーネントのインポートエイリアス： `@/components`を設定。
- ユーティリティのインポートエイリアス： `@/lib/utils`を設定。
- Reactサーバーコンポーネントの使用： ここでは`yes`を選択。
- components.jsonへの設定の保存： `yes`を選択して設定を保存。shadcn/uiに関する設定が保存されるファイルとなります。

設定が完了すると、プロジェクトの初期化とインストールが完了します。

## Bottunコンポーネントの導入
例として、Buttonコンポーネントをプロジェクトに追加してみたいと思います。
```bash
$ yarn shadcn-ui add button
```
`src/components/ui/button.tsx`が生成されるため、`src/app/page.tsx`から呼び出してみたいと思います。

```javascript:src/app/page.tsx
import { Button } from "@/components/ui/button";

return (
  <main>
    <Button>クリック</Button>
  </main>
);
```
先ほど導入したButtonコンポーネントのimport及びJSX内でコンポーネントの呼び出しを定義します。

画像のようにボタンが表示されることを確認できたら完了となります。
![スクリーンショット 2023-12-20 13.49.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535583/eaa1c24c-a3b7-877c-e049-d4b87e4f84ef.png)

以上です。

## 参考資料
https://ui.shadcn.com/
Rigifyで作成したHumanoidアニメーションをUnityにインポートすると足がガクガクする問題の忘備録

# Rigifyで作成したHumanoidアニメーションをUnityにインポートすると足がガクガクする問題の忘備録

以下BlenderでRigifyを使いアニメーションを作成するとUnity内でIKがうまく反映されずに足がガクついてしまう問題を解決した経緯

## どこで起きてる不具合か
Unity側にインポートする時、もしくはHumanoidに変換する際に生じる問題だと思っていたが、実際はBlender側(Rigify自体)の問題だった。

一度アニメーションとメッシュをFBX出力し、それをBlenderにインポートし直したところ問題が再現されたため発見。

## 何が問題？

どうやらボーンコンストレイントが悪さをしている模様。
Unityに出力する際には直接メッシュに影響を与えるデフォームボーンがHumanoidのボーン構造と一致し割り当てることが出来るが、RigifyではIKを含む補助ボーン以外のデフォームボーンにもコンストレイントが設定されており、この設定をUnityに持ち込めないためズレが生じてしまう。

具体的にはDEF_Shinボーン(ひざ下のボーン)に踵との距離の調整のためにストレッチコンストレイントが割り当てられており、角度しか出力しないと踵の位置が伸び縮みの分ズレてしまう。

## 解決方法

Rigifyのボーンの内部構造とコンストレイントの関係性をすべて調べあげ、Unityに反映できないコンストレイント(位置、角度、拡縮以外の全て)を取り除かなければならない。

が、そんなことするなら自分でリグを組んだ方が間違いなく早いし問題も起こりにくい。

## 本末転倒では？

Rigifyを使用する人はリグを組む工程を短縮したい人であるハズ。しかしこのIKのズレを解消するには1からリグを組むのに必要な知識と作業量を求められる。これでは結局自力でリグを組むしかないのでとても困る。

## 最善策

### 金はすべてを解決する
Blenderには有料のリグアドオンとして「AutoRigPro」が存在している。
このアドオンではUnity、UnrealEngine4への出力をワンボタンで調整してくれる機能があるため非常に使い勝手が良い。もちろんHumanoid変換を前提とした出力が可能なので、デフォームボーンにはボーンコンストレイントを使用しておらず、手足のIKのズレもなくなる。

### Rigifyがうまく動かなかったらAutoRigProを買おう！
elixir/phoenixでnewrelicを利用する

# はじめに

この記事は、[New Relic Advent Calendar 2023](https://qiita.com/advent-calendar/2023/newrelic)のシリーズ3の17日目の記事です。

この記事では、NewRelicのAPMをElixir/Phoenixに適用する情報についてまとめています。

サンプル実装のURLは[こちら](https://github.com/ohr486/elixir-nr-demo)です。

# phoenixのセットアップ

デモとなるphoenixを以下の手順でセットアップします。ここではDBはsqlite3を利用しています。

```
$ mix phx.new demo --database sqlite3
$ cd demo
$ mix setup
```

データベースを確認するために、簡単なユーザー管理画面を作成します。
`mix phx.gen.html ...`でusers関連リソースを作成します。

```
$ mix phx.gen.html Account User users name:string age:integer
$ mix ecto.migrate
```

ルーティングがないので、[lib/demo_web/router.ex]()で以下のルーティングを追加します。

```
  scope "/", DemoWeb do
    pipe_through :browser

    get "/", PageController, :home

    resources "/users", UserController # ここを追加!
  end
```

以上で準備完了です。`mix phx.server`でサーバーを起動して`localhost:4000/users`にアクセスすると以下の画面が表示されます。

![スクリーンショット 2023-12-20 14.56.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28174/4d28546b-9f3b-9747-452a-e59b6334e833.png)

これで準備は完了です。

# NewRelicAgentの組み込み

それでは、phoenixにNewRelicを国混んでいきます。elixirのnewrelicエージェントライブラリは[こちら](https://github.com/newrelic/elixir_agent)です。

[mix.exs](https://github.com/ohr486/elixir-nr-demo/blob/main/mix.exs#L54)に、elixir_agentを追加します。

```
  defp deps do
    [
      ...略...
      {:plug_cowboy, "~> 2.5"},
      {:new_relic_agent, "~> 1.0"} # これを追加!
    ]
  end
```

次に、ライセンスキーをconfigに設定します。
[config/config.exs](https://github.com/ohr486/elixir-nr-demo/blob/main/config/config.exs#L64-L66)に以下を追加します。

```
config :new_relic_agent,
  app_name: "AC2023 DEMO",
  license_key: "ここにライセンスキーを設定"
```

`mix deps.get`でライブラリを取得して、サーバーを再起動すると、NewRelicにデータを飛ばすようになります。

```
$ mix deps.get
$ mix phx.server
```

![スクリーンショット 2023-12-20 15.05.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28174/24fb180e-c2a7-512d-5049-108ce6240992.png)

![スクリーンショット 2023-12-20 15.06.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28174/8af29d9e-2df6-e7a0-2286-8b954cb634ac.png)

セットアップは以上です！
とても簡単です。

# 何が見れるの？

elixir_agentで取得できる情報(telemetry)は以下になります。

* [Plug](https://hexdocs.pm/new_relic_agent/NewRelic.Telemetry.Plug.html)
* [Phoenix](https://hexdocs.pm/new_relic_agent/NewRelic.Telemetry.Phoenix.html)
* [Ecto](https://hexdocs.pm/new_relic_agent/NewRelic.Telemetry.Ecto.html)
* [Redix](https://hexdocs.pm/new_relic_agent/NewRelic.Telemetry.Redix.html)

また、APMにBEAMの項目があるので、VMの状態もチェックすることができます。

![スクリーンショット 2023-12-20 15.21.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28174/1058f89d-807d-6c39-a083-5a6fe3717c46.png)

![スクリーンショット 2023-12-20 15.24.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28174/b7db0e72-24af-1ffe-950c-c589998ae893.png)

# まとめ

この記事で、PhoenixにNewRelicを導入する方法を紹介しました。

phoenixアプリであれば簡単に(ほぼ実装なしで)NewRelicを導入できるので、まだAPMを導入していない方は、ぜひ試してみてください。
ChatGPTやAIを利用したプログラミング作成についての書簡

# 初心者としてのChatGPTやAIを利用したプログラミングについて

私もプログラミング初心者の一人ですが、最近ではChatGPTやAIを利用したプログラミングが注目を集めていますね。
自分も試してみた結果、メリットとデメリットがいくつか浮かび上がりました。
こちらに共有させていただきます。

## 筆者のスペック
年齢30代、職業訓練校通い中
プログラミングには触れて1年経たない程度
## メリット:

手軽な学習環境: AIを利用することで、プログラミング学習が手軽になります。
専用の環境や言語のインストールも聞けばやり方を教えてくれるので、従来より容易に環境が構築できる

質問応答: 
ChatGPTは質問に対して迅速で理解力のある回答ができます。
これにより、自身が知識がなくとも、プログラミングに関する疑問を素早く解決することができます。

コード生成の助け: 
AIはコードの一部を生成するのに役立ちます。
特に、基本的な構造や文法を理解するのに役立つコードサンプルを生成してくれるので、初学者にとっては非常に助かります。


## デメリット:

理解の深さ: AIはあくまでツールであり、基本的な概念や原則を理解する手助けとなりますが、深い理解を得るためには実際に手を動かし、自分で考えることが必要です。
※これができる人は基本いないと思ってます。
　できる人ならこのデメリットはないです。

依存の危険:
AIを頼りすぎると、自分で考える力が鈍化する可能性があります。
重要なのは、AIをサポートツールとして使いつつ、自分で問題にアプローチする習慣を身につけることです。
※便利だと、どうしても使ってしまいます。自分の手を動かすのがどんどん面倒になります。
　できる人ならこのデメリットはないです。

情報の精度が不明: 
ChatGPTは強力ですが、時折正確な情報を提供できないこともあります。
完全に信頼してしまうと、誤った情報に基づいたコードを生成してしまう可能性があります。
※これが一番多いです。単純なことならほぼ正答に近いものを出してくれますが、複数の要因が絡み合うと、誤った情報が出てくることが多いです。
必要な情報がわからない初学者これをやると最後どうしようもなくなり、エラーをコピペするだけのマシーンになります。

以上が私が感じた初心者がChatGPTやAIを利用したプログラミングのメリットとデメリットです。簡
単な始め方や注意点についても気になる方はお気軽にお聞かせください。
お互いにプログラミングの世界を楽しんで勉強していきましょう！

## 補足
個人的な感想ですが、
下の下レベルの人がAIでそれらしいコードを書いてきたのを、
下の中レベルの人が見ると直すとめちゃくちゃ勉強になります。
なぜ、動かないのかをコードをみて理解する経験がいいのかもしれません。
マルチステージビルドがわからない


## 背景

### ◯ 経緯

1. 開発環境と本番環境で Dockerfile をわけたいと思いました
2. 共通部分が多いので条件分岐で対応したいと思いました
3. 検索したところ以下の記事がみつかりました

https://zenn.dev/isana/articles/tips-for-dockerfile-standardization-across-env



### ◯ 疑問

* 条件分岐なのに条件分岐していると思しき記述がわからなかった
* 条件分岐をしていると思しき箇所は `FROM ... AS ...` という名前をつけている箇所
* リンク先で掲示されている Dockerfile は以下のようなステップを踏んでいる。これをマルチステージビルドを使って途中で止めることで条件分岐を実現している。

```
build -> dev  -> prod
ビルド -> 開発  -> 本番
```







## マルチステージビルド

本来はステージをわけることで容量を下げることを目的にした機能

> イメージ構築にあたり最もチャレンジングなものの１つに、イメージ容量を小さくし続けるというものがあります。
> [マルチステージ ビルドを使う](https://docs.docker.jp/develop/develop-images/multistage-build.html)



### 1. `FROM ... AS ...` でステージに名前をつけることができる

```dockerfile:Dockerfile
FROM build as dev  # <--- dev という名前のステージ
```


### 2. `--target` で途中でビルドを止めることができる

```
# ビルドを dev ステージで止める
docker build . --target dev -t example-dev
```

### 3. `--from` で指定したステージからファイルを引っ張って来れる

`composer:latest` の `/usr/bin/composer` から `/usr/bin/` にコピーしている。

```dockerfile:Dockerfile
# composer本体を持ってくる
COPY --link --from=composer:latest /usr/bin/composer /usr/bin/
```

### 4. 各ステージは 0 から作られる

各ステージごとに独立した Dcoker イメージが作成される。各ステージで過去に作った Docker イメージから必要な成果物だけを引っ張ってくる（これは理解が間違っている気がします）。これによってマルチステージビルドを活用することで容量を抑えることができる。

### 5. CMD コマンドは最後の１つだけ実行される

あれ？開発環境の `CMD` と本番環境の `CMD` がバッティングしないのかなと思ったのですが、うまい具合にやってくれるそうです。

> `CMD` は `Dockerfile` 内で一度だけ使用でき、複数の `CMD` がある場合は最後のものが使用されます。また、`docker run` コマンドで追加の引数を指定すると、それらは `CMD` で指定したコマンドに上書きされます。
> ChatGPT 先生に聞きました



## 参考

* これで気づけた...
  * [docker: multi-stage builds (intermediate) anthony explains #503 - YouTube](https://www.youtube.com/watch?v=OVYNUg0aODw)
* 環境変数でもハマった
  * [Docker で環境変数を設定する際の挙動について - Qiita](https://qiita.com/domodomodomo/items/e0e9af5cb7c40b00759f)
Firebaseの初期化設定

Firestore Databaseを初期化するときに躓いたのでその備忘録

```javascript:firebase.js
import { initializeApp, getApps } from "firebase/app";
import {getFirestore} from "firebase/firestore"
import 'firebase/firestore';

const firebaseConfig = {
//apikey, authdomain, projectId, strageBucket, messagingSenderId, appId の情報を入力
  };

let db;

if (!getApps().length) {
  const app = initializeApp(firebaseConfig);
  db = getFirestore(app);
}

export default db
```
UWSCRの新機能：HTTP Request

HTTPリクエストを送るための関数が追加されました。Web APIやスクレイピングに利用できます。

:::note warn
スクレイピングを推奨するものではありません。近年では規約でスクレイピングを禁止しているサイトも多いので注意してご使用ください。
:::

# HTTPリクエスト

## WebRequest

指定URLに対して`GET`リクエストを送信します。戻り値は`WebResponseオブジェクト`です。

```php
res = WebRequest("https://gist.github.com/stuncloud/7aebcedb917e8d73d4a1887bc3ab22dd/raw/b43ccf465b27b7483a4747271633d73f7085d276/webmod.uws")
// WebResponseオブジェクトはprintするとレスポンス本文を表示する
print res
// module WebMod
//   public Name = "Web module"
// endmodule
```

## WebRequestBuilder

`WebRequestBuilder`関数は`WebRequestオブジェクト`を返します。`WebRequest`関数とは異なりメソッド等を詳細に設定できます。

## WebRequestオブジェクト

`WebRequestオブジェクト`にはオブジェクト自身の状態を更新するメソッド(`header`や`body`)とリクエストを送信するメソッド(`get`や`post`)があります。前者は戻り値として自身を返し、後者は`WebResponseオブジェクト`を返します。

```php
// WebRequestオブジェクトの作成
request = WebRequestBuilder()

// リクエスト本文を追加、UObjectを渡した場合はjsonに自動変換
request.body(@{"foo": 1}@)
// ヘッダにContentTypeを追加
request.header('Content-Type', 'application/json')
// 指定URLにPOST
response = request.post("https://httpbin.org/post")

print response
```

以下のようにメソッドチェーンを書くこともできます。

```php
response = WebRequestBuilder() _
    .body(@{"foo": 1}@) _
    .header('Content-Type', 'application/json') _
    .post("https://httpbin.org/post")

print response
```

## WebResponseオブジェクト

レスポンス情報を示すオブジェクトです。以下のプロパティを持ちます。


| プロパティ |    型    |                       詳細                      |
|------------|----------|-------------------------------------------------|
| status     | 数値     | ステータス値                                    |
| statusText | 文字列   | ステータス文                                    |
| succeed    | 真偽値   | リクエスト成否                                  |
| header     | 連想配列 | レスポンスヘッダ                                |
| body       | 文字列   | レスポンス本文を示す文字列、ない場合EMPTY       |
| json       | UObject  | レスポンス本文がJSONの場合のみ有効、無効時EMPTY |

```php
if response.succeed then
    print reeponse.body
else
    print response.status + ': ' + response.statusText
endif
```

# HTTPパーサー

## ParseHTML

HTML文字列をパースし、`HtmlNodeオブジェクト`を返します。

:::note alert
#### `0.14.0`に含まれていませんでした。

実装はあるのですが組み込み関数としてエクスポートされていませんでした。ウッカリ！
`0.15.0`以降でお試しいただけるようになります。
:::

## HtmlNodeオブジェクト

パースされたHTMLドキュメントやエレメントを示すオブジェクトです。CSSセレクタによる要素の検索、エレメントのアトリビュートやテキストノードの取得などができます。

```php
html = WebRequest('https://example.com').body
document = ParseHTML(html)
print document.findfirst("h1").text // [Example Domain]
```
【ポエム】ウォータフォール開発、スクラム開発を経験して感じた良し悪し


# はじめに
私はWebエンジニアとして１０年目になります。
前職の会社がSIerで、約８年ほどWebシステムの開発ENとして従事していました。
ウォータフォールで開発が主流で、規模にもよりますが１案件３名くらいがアサインしていました。
こちらの人員の内訳としては窓口兼PM的なベテランENが１名、実装をするEN（自分）が１名〜２名、両者を取り持つENが１名、みたいな開発体型でした。
現在は転職を経て、スクラムで開発している現場で業務をして１年ほどになるので、フォータフォールと比べて、個人的な感想ベースでそれぞれの開発手法の良し悪しをまとめたいと思います。
後述はあくまで上記の経歴で、 ***それぞれの開発手法を体験してどのように感じたかという、主観混みのただの感想である旨をご了承ください。***


# ウォータフォール開発
## 良かったところ
- 要件定義の時点で、注文した顧客が望むシステムや、機能単位でのゴールの解像度が高くなるため下流でどのような技術、サーバスペック、開発コストが大体想像ができる（見積もりがしやすい）
    - 要件定義をきちんとしないとむしろ見積もりが高すぎる or　低すぎる といった理由で結局のところ値段交渉で時間を取られてしまう。
- （本来は）細かいマイルストンで顧客と合意をとるため、仕様の追加、変更、漏れがあった場合は注文者であるお客さんに追加の機能であるためという理由で、追加請求しやすい。
## 悪かったところ
- お客さんの窓口がENじゃないと上流での成果物をこちらが説明して理解してもらうのに時間がかかる。
- 仕様の変更、追加が発生した時にドキュメントの修正→お客さんに確認と合意が都度発生するため、上流のコミュニケーションコストが初期の見積もり（時間的な見積もり）ができない。
  - Zoom,Meetを使わないでお客さん先で説明する回数が増えると尚きつい。
- 設計までの工程で宙ぶらりんの仕様があると、実装段階で気が付き手戻りが発生する可能性がある。
- 納期がタイトな時は、先行して設計まで完了している、仕様がほぼ固まっている機能を先に実装することが多く、他機能の仕様変更で巻き添えをくらうことがある。

# スクラム開発
## 良かったところ
- 開発のスコープが小さいため、スコープ内の考慮すべき点に集中して要件定義から開発ができる。
    - スコープ内がはっきりすると関連する機能への影響そのものも解像度上がる。
    - 大きすぎる場合は分けることができる。
- スプリント完了時に振り返りを行うことでPDCAを回す仕組みが備わっている。
    - スクラムイベントを通して、個人プレーではなくチームとして改善していくため、１ヶ月、２ヶ月の短いスパンでもチームクオリティがが上がっているのを感じる。
- 開発EN、QA　EN、POのチーム全員がリファインメントに参加し、各ポジションで意見が出てくるため、様々な角度からスコープとなる機能の要件、仕様について揉むことができる。
- SECIモデル（※1）による共通認識が浸透しやすく、現場の違いによる細かい認識の齟齬がしやすくなる。
    - PRレビューの指摘傾向、リファインメントでのスコープの調整等
- 上流から参加することができるため、各工程のメインとなる作業者へのリスペクトを考慮した、コミュニケーション能力を得ることができる。

## 悪かったところ
- 向上心がないと、スクラムのチームとして成長していくスピードについていけない可能性がある。
    - 多分これが一番重要
- 要件定義、仕様決めをチームで行うため、１つの工程だけやってきたENだと（開発しかしない、テストしかしない）、アウトカムの妥当性が判断するのに苦労しそう。
- チームメンバーの意見を尊重した上で言動できないと、チームの雰囲気が悪くなる。
- チームメンバーの入れ替わりが激しいとSECIモデルで築いた共通認識がリセットされる。
- ある程度大きいエピックをメンバー揃って中期的に回さないとスクラムの成長に時間がかかりそう。
- ルール化しすぎるとスクラムとしての柔軟性がなくなってしまう側面がある。
- 実装後のスプリントレビューで「もう少し◯◯にした方が...」といった細かい調整があるため、場合によっては手戻りが発生しやすい。

# おわりに
冒頭でお伝えした通り、ウォータフォール開発、スクラム開発を用いた各現場での業務経験を経て自分が感じた内容を良し悪しでまとめただけなので、扱うプロダクト、現場、メンバーの数、といった要素でまた別の感じ方があると思います。
ウォーターフォールの方が、各工程の担当の責任が大きく、前の成果物をきちんと読み取りクオリティを担保した上で自工程で作った成果物を次工程へパスすることが重要で、スクラム開発は、メインの工程を担当とするメンバーはあれど、チーム一丸となって開発を進めている感じがしました。
実装するENだからと言って、お上から降りてくるエピックを淡々とこなしていくだけではダメで、アウトカムをきちんと考えることも能力として必要のため、ある程度上流も下流もできるENでないとスクラム開発についていくのは難しいと感じました。

# 補遺
※1・・[（参考）SECIモデル](https://it-trend.jp/knowledge_management/article/25-0019#d0e9d87eb78fa54e47cd213ca7606442)
[20日目] Node.jsとpm2をインストールする最強スクリプト

こんにちは、なりかくんと申します。
この記事はなりかくん Advent Calender 2023の20日目の記事です。

今回は、私が普段VPSにNode.jsとpm2をインストールする際に利用している秘伝のコマンドを教えていこうと思います。
Ubuntuが実行できる環境です。

# コマンド
```
curl -sSL https://gist.githubusercontent.com/narikakun/d50ba6efd739a1fb3d08e46fa0b0077b/raw/d94cff02e57523839b78a1cff760044d077200db/install-node-lts-pm2.sh | sh
```

このコマンドを実行するだけで、Node.js v20とpm2をインストールすることが出来ます。

# 内容
まず、読み込んでいるシェルスクリプトはこのようになっています。
```shell
#!/bin/sh
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
NODE_MAJOR=20
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
sudo apt-get update
sudo apt-get install nodejs -y
npm install -g pm2
pm2 startup
pm2 save
node -v
```

NODE_MAJORでNode.jsのバージョンを指定しています。それだけです。

# 最後に
是非皆さんも使ってみてください。これを使うだけでVPSのセットアップ作業が100倍楽になります。