OmniAICreator/Qiita-1.07M huggingface dataset:
Snowpro Core[COF-C02] 試験受けてみた

業務系SEからデータエンジニアへのキャリアチェンジを目標にしており、会社で取得を推奨されているSnowflakeの認定試験を受けてました。

# 試験形式
SnowPro Core[COF-C02]を受験しました。
言語は日本語、会場はテストセンターで受験しました。

リモートとテストセンターでは選択できる日時が異なるため、余裕をもって申込をしておいたほうが良いと思います。
問題形式ですが、複数選択は2つ選択せよというパターンが大半でした。（3つ選択せよというパターンは出題されなかった気がします）

■試験バージョン：SnowPro Core [COF-C02]
■試験時間：115分
■問題数：100問
■問題形式：単一選択、複数選択
■試験会場：リモート or テストセンター　　　
■合格ライン：750点以上(1000点満点中)
■言語：日本語 or 英語
■受験料：175米ドル税抜(税込みで2万5000円くらいでした)
■有効期間：２年

# 申込方法
①Snowflake認定ポータルのアカウント作成
[Snowflake Certification Portal](https://snowflake.useclarus.com/login?forward_url=%2F)

②Snowflake試験をピアソンVue経由で登録
アカウントを作成すると、認定ポータルトップページに『ピアソンVUEで試験をスケジュールします。』のリンクから試験会場や日時を登録して申し込みをします。

# 出題範囲
公式発表では以下の割合で出題されるようです。

| 出題分野 | 予想される割合|
|:--|--:|
|Snowflake Cloud Data Platformの機能とアーキテクチャ  | 25%  |
|アカウントアクセスとセキュリティ  | 	20%  |
|パフォーマンスの概念 |  	15% |
|データのロードとアンロード   | 	10%  |
|データ変換   |  20% |
|データ保護とデータシェアリング   |  10% |

実際に試験を受けて以下の内容が多く出題された印象でした。

・アカウントのロール/権限やその管理
・ストアド/ユーザ定義関数(UDF/UDTF)の違いや使い方
・半構造化データ(JSON)の変換/ロード方法

# 勉強方法
①公式ドキュメントの読み込み
全体像の把握を行うために、ざっと目を通しました。
以下で取り組んだ問題を解いた際に知識の深堀りと周辺知識の確認をするために使用していました。

②Snowflake University Level Upシリーズ
各出題範囲ごとに数問～20問程度サンプル問題が用意されているのでこちらを全分野確認しておきました。

③無料トライアルアカウント(30日間)
無料トライアルアカウントを作成し、実際のWebインターフェースの使用感を確認しました。

④Udemyの入門セッションと模擬試験
以下のリンクの学習コースに取り組みました。

[ゼロから始める「Snowflake」最速入門コース](https://www.udemy.com/course/snowflake-basic/)
[模擬試験](https://www.udemy.com/course/snowflake-snowpro-core-certification-exam-practice-sets/)

# 受験をしてみて
3,4か月ぐらいダラダラと勉強していましたが、一応771点でギリギリ合格出来ました。
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730832/2730aaca-b0af-0129-7bb4-cea9b47fd081.png
">

学習期間に関しては業務でSnowflakeを使用されている方であれば1か月くらい、私のように非データエンジニアの方は2~3か月くらい勉強すれば合格できるのではないかと思いました。
試用アカウントの期限もありますので、短期間集中して勉強するのが効率のいい進め方だと思います！
Docker上のMysqlにDBeaverから接続する

個人用のメモ

ネットの記事を参考にしながら、接続を試行したがうまくいかなかったのでメモ。

【前提】
dockerのmysqlにコマンドコンソールでログインし任意のパスワードでrootユーザを作成していた。

【接続設定内容】
ホスト：127.0.0.1
Port：3306
ユーザ：root
パスワード：docker-compose.ymlに記載されたrootのパスワード（前提で作ったrootユーザのパスワード）

【詰まった原因】
パスワードを空欄にしていたから。
他人から引き継いだ環境を使っていて、ローカルのrootユーザは空だろうと決めつけていたら違ってた。（きちんと確認しましょう。というかちゃんとdocker-compose.ymlとかの設定ファイルを見ておこう←戒め。。。。）
C++ 初心者入門（まずはこれを知ろう）

# このコードについてしっかり理解できているか？
今回は、初学者(自分)が第一に学んでおかなければならないC++言語について学習していきます。

```c++
#include <stdio.h>
#include <iostream>

int main (){
    printf("関数を使った出力\n");
    std::cout << "ストリームを使った出力\n";
    return 0;
}
```



# include とは何をしているのか？
何かしらの機能を追加させている。

あらかじめ用意されたさまざまな機能を使えることができる

~を取り込む：include
外部の装置と入手力を行う機能：iostream

input output stream:入出力ストリーム
⇨文字の入出力を簡単に行うための機能

```c++
#include <stdio.h>
#include <iostream>

int main (){
    printf("関数を使った出力\n");
    std::cout << "ストリームを使った出力\n";
    return 0;
}
```
stdio.hでも同じ動作をすることができるが、
streamを使うことで、外部への装置への入出力を１つの方法でできること！
（異なる装置を同じように扱うための仕組み）

printf,scanf　関数⇨標準入出力に対して使用
fprintf,fscanf 関数⇨ファイルに対して使用
sprintf,vsprintf,sscanf関数⇨メモリに対して使用

入出力の対象によって関数を使い分ける必要があるから！

```c++
std::cout << "Helloworld" << std::endl;
```
これでいうcoutは標準出力ストリームオブジェクトを使用。
この部分を変えることによって、ファイルへの入出力などを可能にすることができるようになるのです。

# int main()は何をしているのか？
プログラムを作る上で必ずmain関数は必要
1番最初に実行されるのがmain関数と決まっているからなのです。

intという部分については、終了時にどの種類のデータを返すかを指定しています。
⇨ return 0;　として０を返却し、プログラムを終了させています。

## 名前空間について
そもそもなぜC++は開発されたのか？
⇨大規模開発に対応するため
⇨たくさんの人がプログラム開発に参加するため、同じ変数名・関数名がダブってしまう。

例：
Shouhizei::keisan()
Enshuuritu::keisan()

どちらもkeisan関数ですが、左側に書いてあるのがクラスと呼ばれているものです。

これが名前空間の意味で、クラスが違えば、同じ名前の関数であっても別の処理を行えるということです。

```c++
#include <streamio>
using namespace std;
int main (){
    cout << "おはよう" << endl;
    cout << "こんにちは" << endl;
    cout << "こんばんは" << endl;
    return 0;
}
```
cout (console out)：値を出力
endl (endline)：改行

using namespaceを使うことで、オブジェクト名の後にわざわざstd::をつけなくても良くなったということです。

## g++は何をしているのか？
このような実行コードは見たことないでしょうか？
```c++
g++ sample sample.cpp && ./sample
```
g++というのは、GNUプロジェクトが作っているコンパイラ用のソフトになります。
g++ 〇〇.cpp：実行ファイルの作成

./〇〇：実行ファイルの実行

![スクリーンショット 2023-04-26 0.26.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/85cfa642-f80e-413f-7699-1a7dc8088f0d.png)

こんな感じてHelloWorldが実行されましたね。
"PowerShell ウィンドウをここで開く"を非表示にする【Windows10】

Shiftを押下しながら右クリックで表示される ↓ これです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185453/7e95efa7-a515-681b-582c-365b1a029d90.png)

## 手順
※レジストリをいじりますので操作には十分注意してください。

#### 1.レジストリエディタを開く
Win + Rから``regedit``と入力してEnter。ユーザーアカウント制御の画面では「はい」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185453/5df2b87b-bfc6-9aff-861e-67666100644f.png)

#### 2.アクセス許可の変更
レジストリエディタが開いたら、次の場所まで移動します。
```
HKEY_CLASSES_ROOT\Directory\Background\shell\Powershell
```
本当ならここで値を追加するんですが、このままではエラーがでてしまうため色々いじります。

``Powershell``キーを右クリック → **アクセス許可(P)...** を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185453/18479ef4-8319-f0e4-24e3-1af3d0044e97.png)

**詳細設定(V)** を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185453/e171b92c-fbf3-332e-3fbb-b79117433cbc.png)


所有者がTrustedInstallerとなっているので、これをAdministratorsに変更します。
変更すると、**サブコンテナーとオブジェクトの所有者を置き換える** チェックボックスが表示されるのでチェックし、**OK**で閉じます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185453/f17f15e5-16cd-3946-5f0f-5ba64112b551.png)

先ほどのウインドウでAdministratorsの**フル コントロール**を許可し、**OK**で閉じます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185453/29a1a08c-a303-1bdc-12e0-333373f55032.png)

これで``Powershell``キーに値が追加できるようになります。

#### 3.値の追加
``Powershell``キーを選択した状態で右クリック → **新規(N)** → **文字列値(S)** を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185453/fb041f2b-abaa-a133-1b03-f01b4b581a6a.png)

名前を``ProgrammaticAccessOnly``にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185453/8e77f53c-c00d-0260-098f-340138808779.png)

#### 4.別のキーに対しても同じ手順を行う
このままではドライブをShift + 右クリックした際にPowershellで開くボタンが表示されたままなので、上記と同様の手順を次のキーに対しても行います。
```
HKEY_CLASSES_ROOT\Drive\shell\Powershell
```
これで非表示にすることができます。

## 元に戻す場合
元に戻す場合は、上記の手順で追加した``ProgrammaticAccessOnly``を削除するだけで大丈夫です。
キーの所有者も元に戻したい場合はそのままTrustedInstallerと入力しようとするとエラーがでてしまうので、その場合は``NT Service\TrustedInstaller``と入力すればおｋです。

↓参考

https://winaero.com/remove-open-powershell-window-here-from-context-menu-in-windows-10/
モバイルUIでpaddingが効かないときの対処法

スマホで表示させたときにpaddingが効かないときがあったのでメモ。（PCからデベロッパツールで見たときは、効いていたので少し戸惑った。。。）

【環境】
・Iphone 13 mini
・ChromeとSafariどっちでも発生した。

【内容】
モバイルUIでpaddingが効かず、レイアウトが崩れる

【対処法】
効かない要素にwidthを設定してあげる。以上！
Parallels DesktopでCoherence利用時に無作為に操作不能なウィンドウが表示される

## 環境

- Mac
    - 14インチ M1 MacBook Pro
- Parallels
    - バージョン 18.1.1 (53328)

## 状況

Parallels® Desktop 18 for Mac でCoherence利用時に、左側に謎のウィンドウが出現する。(画像はサンプル)

![スクリーンショット 2023-02-12 19.15.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395131/21f19d59-b162-1913-b8ac-444531e01360.png)

## 解決方法

Windows側の設定から 「スナップ機能をオフにする」 で発生しなくなった。
(その後、頻度はだいぶ減ったが数回発生した)

## 関連

https://forum.parallels.com/threads/phantom-window-while-in-coherence.357035/
https://forum.parallels.com/threads/phantom-window-appearing-while-in-coherence.359058/
torch.topkで巨大なテンソルを扱った際に生じるエラーと解決方法

# 概要
PyTorchの `torch.topk` 関数において巨大なテンソルを扱った際に発生するエラーと解決方法について紹介します。

# 環境
この記事では、下記の環境で動作確認をしています。

- PyTorch 1.13.1
- CUDA 11.7
- NVIDIA GeForce RTX 3080Ti (VRAM 12GB)

環境構築は `conda` コマンドにより行っています。

```shell
conda install pytorch==1.13.1 pytorch-cuda=11.7 -c pytorch -c nvidia
```

# `torch.topk` で巨大なテンソルを扱った際に生じるエラー
PyTorchでk近傍法などを実装する際に利用する関数として `torch.topk` があります。

https://pytorch.org/docs/stable/generated/torch.topk.html

この `torch.topk` に対して、一定のサイズを超えるテンソルを入力した際にエラーが発生します。筆者の環境で確認したところ、下記のコードでエラーとなりました。

```python
import torch

x = torch.randn((65, 1000, 1000), device="cuda")
topk = torch.topk(x, 10, -1)
print(topk)  # 正常

x = torch.randn((66, 1000, 1000), device="cuda")
topk = torch.topk(x, 10, -1)
print(topk)  # エラー
```

`(65, 1000, 1000)` の配列では動作していたものの、`(66, 1000, 1000)` になるとエラーが発生します。この時のエラーメッセージとしては下記の通りです。

```
RuntimeError: CUDA error: an illegal memory access was encountered
```

巨大なテンソルを扱っているので原因としてメモリ不足が第一に考えられますが、その際は `CUDA out of memory` と表示されるため、一般的なメモリ不足のエラーとは少し異なるようです。

# 解決方法
このエラーはPyTorchのIssueでも報告されていましたが、PyTorch 2.0.0で修正されたようです。

https://github.com/pytorch/pytorch/issues/82569

下記コマンドによりPyTorch 2.0.0の環境で試したところ、エラーとなっていた箇所も正常に実行できました。

```shell
conda install pytorch=2 pytorch-cuda=11.7 -c pytorch -c nvidia
```
master.cfの各フィールド

●Postfixは複数のデーモンから構成されており、これらデーモンの設定を「/etc/postfix/master.cf」ファイルで行います。
master.cfの書式はmain.cfとは異なり、以下のように8つのフィールドがあり、各行でそれぞれのサービス（デーモン）の設定を行う


以下はmaster.cfの各フィールドをまとめたもの

・service　Postfixのサービス(デーモン)名の指定
・type　サービスのタイプの指定。inetはインタ＾ネットソケット、unixはUNIXドメインソケット、fifoは名前付きパイプ
・private　メールシステムへのアクセス制限を行うかどうかの指定
・unpriv　サービスをrootまたは所有者で動作させるかどうかの指定
・chroot　chroot jail環境で動作させるかどうかの指定
・wakeup　サービスを何秒後に起動させるかどうかの指定
・maxproc　プロセスを同時に起動できる最大数の指定
・command+args　サービスの実体プログラムと、その引数の指定

chrootを「y」とすることで、指定したデーモンをchroot jailモードで起動させることができ、セキュリティを向上させることができます。
【VSCode】特定のローカルブランチにコミットする際にメッセージを表示する方法


## はじめに

VSCodeのソース管理からコミットする場合にローカルブランチを保護する方法について記載します。  
具体的にはソース管理から保護ブランチへコミットする場合に以下のメッセージが表示されるように設定します。  

![2720C7C3-C903-45FC-ABDA-3DD65D3F7AAF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/c3a8bf6c-a3ed-de31-5480-916deaad65b2.png)


設定は非常に容易ですがVSCodeのソース管理以外からのコミットに対しては機能しません。  
他の状況にも対応するにはGit Hooksを使用するなど他の方法を採る必要があります。  

## 設定方法

VSCodeのユーザー設定画面を開きます。  

`git.branchProtection`を検索します。  

![76F7E4A0-EC37-47D9-841F-E10F50965AEB.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/4fe7a0b0-39c8-d9c4-aa5e-6b713bec21e9.png)

項目の追加をクリックして保護したいブランチ名を入力します。  

![05B65771-3937-4A9C-9048-E268DBA6986C.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/780aae82-6742-9e46-6e17-529a52b77d97.png)

これで設定は完了です。  

なおワークスペースにのみ設定を適用したい場合には設定画面のワークスペースを選択して
上記の手順を行います。  

![2B7056C5-3648-40E0-910E-7EC7BBE77533のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/17ce246c-059a-2164-7ef2-b7d3cd3fb510.png)

## 動作確認

VSCodeのソース管理から先ほど追加したブランチへ直接コミットしようとすると以下のように
表示されます。

![2720C7C3-C903-45FC-ABDA-3DD65D3F7AAF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/c3a8bf6c-a3ed-de31-5480-916deaad65b2.png)
ローカル環境を立ち上げる

## 概要
PHPでのローカルサーバーの立ち上げ方。

## 手順

前提1：PHPはインストールされている状態
前提2:Macを使用

1. ターミナルを立ち上げる
1. 立ち上げたい「phpファイル」や「htmlファイル」のあるディレクトリに移動する　（ｃｄ {移動したいディレクトリのパス}）
1. コマンド :`puts 'php -S localhost:8080'`
1. ブラウザで　`puts 'http://localhost:8080/'`にアクセス
1. 表示される
COBOL書き方

## COBOLの特徴

英語のような自然言語に近い構文
変数名は英語の単語で表されることが多い
→数値の桁数やデータ型なども、単語に基づいて定義される



```cobol
IDENTIFICATION DIVISION.
PROGRAM-ID. program-name.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 variable-name PIC 9(9).
01 another-variable-name PIC X(10).

PROCEDURE DIVISION.
main-procedure.
    DISPLAY 'Hello, world!'.
    ADD 1 TO variable-name.
    MOVE 'ABC' TO another-variable-name.
    STOP RUN.
```

## セクション
IDENTIFICATION DIVISION：プログラム名や作成者などの情報を定義
DATA DIVISION：プログラムで使用される変数や定数などのデータを定義
PROCEDURE DIVISION：実際のプログラムの手順を定義


WORKING-STORAGE SECTIONの中で2つの変数が定義されている
１、PROCEDURE DIVISIONの中で、DISPLAY文でテキストを出力
２、ADD文で変数を加算
３、MOVE文で文字列を別の変数に代入
４、STOP RUN文でプログラムを終了
Midjourneyのコマンドまとめ

忘れて調べるのが面倒なのでメモ

## /settings
Nijiにするとか、relaxにするとか、ここで変えちゃうのが一番楽
設定を出す

## /info
残り使用量の確認

## /imagine
画像生成

## -s 数字
数字を上げると視野が広がる
1000くらいで映画のシーンみたいに

## /blend
画像合成

## /describe
画像からプロンプトを抽出

## -style expressive
Nijijourneyで綺麗なイラストを作る
大人っぽくなる

## --style cute
Nijijourneyでポップなイラストを作る
可愛らしい、癒し系

## --style scenic
Nijijourneyで風景を作る
風景の中にキャラを入れ込む

## --tile
Nijijourneyでイラストをタイル化する
--s 0だと一個一個がでかい
--s 500 くらいがちょうどいい
style cuteとの併用がオススメ

## --dimensions
blendで設定できる
縦横比の変更

Portrait 2:3縦長
Square 1:1正方形
Landscape 3:2横長
Midjourneyで狙い通りの画像を出すテクニック

## はじめに

Midjourneyという画像生成AIで自分が想像したイメージに近い画像を出すテクニックを紹介します。

簡単に手順と例だけ。

## 手順
**①ChatGPTにプロンプトの構成例を与える**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1956427/a12e074b-0f5c-f6d1-9e54-0db4e79462c4.png)

**②その構成例を元にChatGPTに「イメージのみを伝える」**

**③ChatGPTから貰ったプロンプトをMidjourneyに打ち込み生成**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1956427/0f0b49a5-c507-15ee-2d3f-38d8d294abd6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1956427/d2e3d565-440e-99fa-e9db-7aa1d2c40acb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1956427/6317ec6e-6a33-16e1-95fc-3549c9527726.png)

**まさにこれ！という画像が一発で出てきました。**

①の構成例は、出したいイメージの種類によって変更します。
写真のように美しいイメージを出力したいのであれば、**カメラの種類**などをChatGPTに考えてもらい
ファンタジーな世界観であれば、**画風や構図**など

その道のプロであれば簡単に思いつくけど、「調べるとなると中々難しいもの」
これをChatGPTに自動的に補完してもらいます。

## 例
(手順と同じ方法で出力)

**近未来都市の高層から街を見下ろす少女**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1956427/b251bb6d-392e-beb4-c20b-c5ba27e179e1.png)

**パフェとかすみ草とシャボン玉**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1956427/3cea4884-0f67-9606-b287-c0d3c706979e.png)
Pythonでのsqliteを使用してDB作成

<h2>英語の4択クイズを作成</h2>
    <p>pythonのTkinterで英語の4択クイズを作成していて、csvで問題と答えの設定をしていたのでDBで設定したらDBの勉強に繋がるのではないかと思い挑戦してみました。</p>
    <p>csvで問題と答えの準備を以下のように保存していました。</p>
        <ul>
            <li>問題</li>
            <li>答え1</li>
            <li>答え2</li>
            <li>答え3</li>
            <li>答え4</li>
            </li>答えの番号</li>
        </ul>

 <h3>DBのテーブル作成までの流れ</h3>
 ```

    import sqlite3

    # DB名設定 英語に関連するソフトウェアなのでDB設定
    dbname='English.db'

    # DBに接続する
    conn=sqlite3.connect(dbname)

    # sqliteを接続するためのカーソルオブジェクト
    cur=conn.cursor()

    
    # テーブル作成
    cur.execute("CREATE TABLE IF NOT EXISTS english(problem TEXT, answer1 TEXT, answer2 TEXT,answer3 TEXT, answer4 TEXT,correct INTEGER)")



 # 複数行の挿入データ
    data_english=[
       ("Exchangeはどういう意味?","やり取り","怖がる","食べる","喋る",0),
    ("Displayはどういう意味?","奪う","~を飾る","飲む","言語学",1),
    ("Speadはどういう意味?","を広げる","作動","真夜中","瞑想",0),
    ]

      
     # データをDBに登録する。
     cur.executemany('INSERT INTO english(problem,answer1,answer2,answer3,answer4,correct) VALUES(?,?,?,?,?,?)',data_english)     
  

    # dbにコミットする
    conn.commit()
    #dbの接続を切る
     conn.close()

```


<p>CREATE TABLE IF NOT EXISTS テーブル名とすることで、テーブルが既に存在している状態でもデータの追加をすることが出来た。</p>


<p>executeで複数あるデータを一つずつ書くのはめんどくさかったので、executemanyでデータを使用することで、複数あるデータを１活で登録出来た。</p>

:::
slack CLI(slack platform)を使ってchatGPTのbotを作る

# 背景
API版のchatGPTは入力データを学習データとして利用しないという情報を見て、(機敏な機密情報を含まない）業務のソースコードを使って質問し、作業効率化を図りたいと思い、slackでchatGPTに問い合わせられるbotを作ってみました。

# 概要
今回bot作成に利用したのは、[Slack 新プラットフォームの開発者用オープンベータ版](https://slack.com/intl/ja-jp/blog/developers/make-work-flow-faster-with-slacks-new-platform)です。
slack側でインフラ面を自動でやってくれるみたいです。
Beta期間中は、無料で使えるそうです。

# 手順
- OpenAIからAPIキーを取得する
- slack CLIのインストール
- 使いたいslackアカウントと連携する
```
slack login
```
- プロジェクトのテンプレートを作成する
```
slack create
```
- ロジックを実装する
- ローカルでテストする
```
slack run
```
- デプロイ
```
slack deploy
```
- デプロイ後に変更を適用する
```
slack update
```

# openAI chat completion API の仕組み
APIのパラメータには、
- 使用するモデル (GPT-3.5-turbo, GPT4, ...)
- 会話の情報
- APIキー

を最低限入れる必要があります。
特に、web版のリクエスト構造と違い、API版では必要な会話履歴をすべて入れる必要があります。
一つの質問を入れるだけだと、その前の文脈を含めて回答してくれません。

APIのレスポンスには、AIの返答に加え、入力文・出力文・合計のトークン数が返されます。
これは、このAPIが合計トークン数あたりの従量課金制だからです。
gpt-3.5-turboモデルを使用した場合、[$0.002/1000トークン](https://openai.com/pricing)なので数百行程度のコードを質問したり、記事の要約をするくらいなら、1円もかからない場合が多そうです。

# 実装
実装詳細は、他の記事に情報があるため、要点だけまとめます。
### スレッドに返信する
メンションしたメッセージにスレッドとして返信するには、[ReplyInThread](https://api.slack.com/reference/functions/reply_in_thread)というslack関数をワークフローの最後で呼び出します。

### スレッドを取得する
スレッドを取得するには、[conversations.replies](https://api.slack.com/methods/conversations.replies)というslackの関数を利用します。
スレッドIDに当たるものが**thread_ts**で、まだスレッド化されていない（まだ返信のないメッセージの）場合にはメッセージオブジェクトの中にプロパティが存在しないため、存在チェックはしておいたほうが良さそうです。
スレッド内から取得する最大のメッセージ数は**limit**で指定できます。

### スレッド全体をchatGPTに送る
APIの入力分のオブジェクト構造は、
```json
{
    "role": "user" または　"assistant" または "system",
    "content": ”質問文”
}
```
このような形式です。
会話履歴を送るとき、botのuser_idかどうかで条件分岐して、"user"か”assistant"かroleの値を自動的に決定するようにしました。

# つまりどころ
### slack platformの利用規約に同意する必要がある
デプロイの際に、ワークスペースの管理者にslack開発者プラットフォーム利用規約に同意してもらう必要がありました。
### slackのチャンネルIDの調べ方
チャンネル名をクリックして出てくるチャンネル情報の一番下に記載されています。

### botがメンションに反応するようにする場合は、指定のチャンネルでしか動かない
app_mentionedというイベントトリガーが用意されています。
トリガー定義内でイベントを以下のように定義します。
```
event: {
    event_type: "slack#/events/app_mentioned",
    channel_ids: [
      "XXX",
      "YYY"
    ]
}
```
ワークスペース内のどこでも使えるようにするためには、全てのチャンネルIDを登録しなければいけなそうです。

### デプロイされているアプリのロギング
```
slack activity
```
で直近のログを見れるようです。
https://api.slack.com/automation/logging

### Denoが使われている
普段denoを使用していないので、まだよくわからない部分があります。

# よくわからない部分
### たまにbotが反応してくれない
https://api.slack.com/automation/functions
> 関数を使用してワークフローを構築する場合、関数ごとに 15 秒のタイムアウトがあります。関数が開始されてから 15 秒以内に実行が終了しない場合、ログにタイムアウト エラーが表示されます。

タイムアウトは15秒に設定されているようなので、それが原因ではなさそうです。

# 感想
botレベルでlambda関数を用意して、権限を付与して...などやろうとすると面倒に感じた経験があるので、とても便利だなと思いました。
データストアもあるみたいなので、chatGPTの合計課金額の計算に今後使ってみたいです。

# 参考
・[ChatGPT APIリリースに伴ってOpenAIのAPIデータ利用ポリシーが改定されたので読んでみた](https://dev.classmethod.jp/articles/openai-data-usage-policy/)
・[生成系 AI の業務利用ガイドラインを紹介します](https://blog.zaim.co.jp/n/n641fc2e19933)
・[OpenAI API Reference](https://platform.openai.com/docs/api-reference/chat/create)
・[ChatGPT Bot を new Slack Platform で動かしてみた](https://tech.layerx.co.jp/entry/2023/03/06/chatgpt-on-slack-new-platform)
【AWS】「JAWS-UG横浜 #48 AWS re:Invent 2022 宇宙一早いヒーローだらけRecap‼️」認証/ネットワーク/サーバ 厳選

メモ程度なのでこれ見て興味湧いたら本編閲覧推奨
# JAWS-UG横浜 #48 AWS re:Invent 2022 宇宙一早いヒーローだらけRecap‼️

- CFのバックアップ
    - テンプレート単位でバックアップ可能（AWS Backup利用）
- PBAC
	- RBACとABACのいいとこ取りを実現
- CloudTrail Lake
	- クエリでAPIコールのログを追跡できるようになった
- Nitro
	- 前までEBSなどのそれぞれのコンポーネントは高速ネットワークによってつながっていた、それをソフトウェアで実現するとhypervisorの深エグい
	- Nitrosystem=ハードウェアチップ
	- NitroHypervisor=超軽量KVM
	- ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/7c6bcbe1-0e26-886f-b456-f0b67296498a.png)

- ENA Express
	- TCPは衝突する恐れがあり通信のジッタが頻繁
	- EFAというアダプタを使えばSRDというTCPの問題を解消するプロトコルでジッタ解消
	- ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/653e6f45-ad81-a8d3-77a9-d8cd87aa18bc.png)

	- ENA Expressを使えばEFAをわざわざ使わなくても対応できる（インスタンスタイプに制限ある）
- Lambda SnapStart
	- コールドスタートの問題を解消するもの（Java限定）
	- 一回目のinitフェーズでスナップショット取る
	- キャッシュする
		- キャッシュすることにより例えば乱数を生成するプログラムが入っていたときに同じ乱数が使われてしまうので実装の際は注意
- Verified Access
	- ゼロトラストに基づいてGA
		- VPN不要で外部から安全にアクセス
		- OIDCやSSOなどで認証
	- ユーザからのリクエストを承認した（認証通った）あとにVPC Latticeが動作
		- LatticeはAppMeshの巨大版
		- コンテナ以外にも対応（LambdaやEC2など）
- ServiceConnect
	- コンテナ間の通信パターンは従来３つ
		- ELB
			- コスト高い
		- ServiceDiscovery（Route53とCloudMap）
			- メトリクスを観測するのが大変
		- AppMeshとCloudMap
			- コンポーネントが複雑で大変
			![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/12a30dc1-b7aa-3235-66fb-b3893110986d.png)


	- それをService Connectで解消
		- 下記の制約がある
		- ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/b737c192-3c3a-d014-5187-5bdd5655f5ac.png)

			- ECS Service Connect Procxyのリソース考慮
    			- Envoyが利用されたコンテナ（プロキシ）が自動で追加される（CPUユニットとメモリの未割り当て分を食うのでそこを考慮）


ソース：https://www.youtube.com/watch?v=z80RVfbJ1no&list=WL&index=18&t=80s
js.erbでHTML要素の削除ができなかった

## はじめに
ToDoアプリ作成中に非同期処理を実装中、HTML要素の削除に手間取ってしまいました。いくつか方法があるみたいなので書き残します。

## 実現したかったこと
作成したToDoの編集ボタンを押すとToDoがカーソル入力状態になり、編集ボタンは一旦消えることです。
以下では、editリンク内にペンのアイコンを表示しています。
```erb:app/views/tasks/edit_link.html.erb
<%= link_to edit_task_path(task), class: "btn", id: "edit-task_#{task.id}", remote: true  do %>
  <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
<% end %>
```
以下はコントローラーです。
js.erbのviewを呼び出しています。
```ruby:app/controllers/tasks_controller.rb
def edit
  respond_to do |format|
    format.js { render locals: { task: @task } }
  end
end
```
そしてjs.erbファイルでeditリンクのHTMLを消そうとしています。
```erb:app/views/tasks/edit.js.erb
$("#edit-task_<%= task.id %>").html("");
```
しかし、この書き方ではペンのアイコンの表示が消えるだけで、リンクのボタンはそのまま残ってしまいました。

## 原因
`.html("");`という記述は、指定した要素の子要素を削除する処理だから。
つまり以下の記述ではspan要素のみ削除されてしまいます。
```erb:app/views/tasks/edit_link.html.erb
<%= link_to edit_task_path(task), class: "btn", id: "edit-task_#{task.id}", remote: true  do %>
  <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
<% end %>
```
補足として、`$(要素).empty();'とした場合も同じです。

## 解決策
`remove()`を使用する。
```erb:app/views/tasks/edit.js.erb
$("#edit-task_<%= task.id %>").remove();
```
`remove()`は指定した要素自体を削除してくれます。
これで期待通りの動きになりました。
【SwiftUI】アプリ内でダークモードに切り替える方法

## 概要
アプリ開発をしていて、アプリ内の設定画面からライトモードやダークモードに切り替える機能が欲しくなりました。

そこで自分なりに調べた方法を簡単にまとめます。

::: note warn
筆者はSwift歴1年ちょっとの初学者です。よって間違ったコードや知識があるかもしれません。もし間違いを発見しましたら、ご指摘いただけると幸いです。
:::


### 環境
- M1 macOS Ventura 13.1
- Xcode 14.3
- Swift 5.8

## 動作
![425.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2278050/50b8a87d-3cdb-7b3e-8fb8-a6b73b815ec5.gif)

## 実装例
### AppearanceModeSetting
``` Swift
enum AppearanceModeSetting: Int {
    case followSystem = 0
    case lightMode = 1
    case darkMode = 2
    
    var colorScheme: ColorScheme? {
        switch self {
        case .followSystem:
            return .none
        case .lightMode:
            return .light
        case .darkMode:
            return .dark
        }
    }
}
```
ここでは見た目を設定するためのEnumを定義しています。
数値を持っているのは、後々`@AppStorage`で値を取得し、`rawValue`で指定するためです。

`ColorScheme`型は、ライトモードかダークモード化を指定するための型です。

### テーマ変更画面
``` Swift
struct TheamConfigurationView: View {
    @AppStorage(wrappedValue: 0, "appearanceMode") var appearanceMode
    var body: some View {
        Form {
            Picker("Appearance Setting", selection: $appearanceMode) {
                Text("システムに合わせる")
                    .tag(0)
                Text("ライトモード")
                    .tag(1)
                Text("ダークモード")
                    .tag(2)
            }
            .pickerStyle(.inline)
        }
    }
}

```
この画面でライトモードかダークモードかを指定します。
この場合デフォルトは`システムに合わせる`になっています。

### App構造体
```Swift
@main
struct MyApp_App: App {
    @AppStorage(wrappedValue: 0, "appearanceMode") var appearanceMode
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .preferredColorScheme(AppearanceModeSetting(rawValue: appearanceMode)?.colorScheme)
        }
    }
}

```
`@AppStorage`でInt型の値を取得して、`preferredColorScheme`で`AppearenceSetting`の`colorSheme`を指定しています。

## まとめ
`@AppStorage`をうまく活用すれば、意外と簡単に実装できます。

個人的にはライトモードとダークモードは、アプリごとに設定したいので、この機能があるととても嬉しいと思います。

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

## 参考にした記事
https://qiita.com/mashunzhe/items/e0b5cab0df689438379f

↑コードの大枠はほとんどこちらの記事を参考にさせていただきました。
しかしこの記事のコードだとダークモードに切り替えた途端に画面が戻ってしまうため、その辺を本記事で修正しました。

https://tech.amefure.com/swift-dark-mode-change
ReactアプリをGitHub Pagesで公開する

公式ドキュメントをもとに行った手順をメモとして残しておく。


# 手順1: package.jsonにhomepageを追加
場所はどこでもいいが迷ったら一番下でいい。
```json
{
    "homepage": "https://{GitHubのユーザー名}.github.io/{GitHubのリポジトリ名}"
}
```

# 手順2: gh-pagesのインストール

## 2-1: インストール
### npmの場合
```bash
npm install --save gh-pages
```

### yarnの場合
```bash
yarn add gh-pages
```

## 2-2: package.jsonへの追記
scriptsの中に`predeploy`、`deploy`をscriptsへ追記する。
なお、`predeploy`は`deploy`が実行される前に自動で実行される。
※コピペする場合は`+`は削除

```diff_json
{
    "scripts": {
+       "predeploy": "npm run build",
+       "deploy": "gh-pages -d build",
        "start": "react-scripts start",
        "build": "react-scripts build",
}
```

# 手順3: `npm run deploy`を実行

```bash
npm run deploy
```

この時に何が起こるか説明しておく。
まず、`/build`ディレクトリが作成され、この中にデプロイ用のファイル（Reactアプリがコンパイルした結果）が作成される。
これがGitHub Pagesへの公開のためのデータとなる。
そして、`gh-pages`というブランチが作成され、`/build`ディレクトリの中身がcommit・pushされる。
コマンド実行後にリポジトリを開いてみるとブランチが作成されていることがわかる。

![スクリーンショット 2023-04-25 22.45.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174359/7943b65c-548a-23b5-6ee9-794b745d1831.png)


# 結果を確認する
手順1で設定したhomepageのURLへアクセスすると、デプロイが上手くいっている場合はページが表示されるはず。

公式ドキュメントにはStep4としてPagesの設定について記載されているが既に設定されており、
デプロイもされている。

設定を確認したい場合、`Settings`の`Pages`タブから確認できる。
また、デプロイの状況は`Actions`から確認可能。もし問題がある場合はここで表示されている。


# 公式ドキュメント
公式ドキュメントにはGitHub userpageを利用する場合やカスタムドメインを設定する方法などが記載されている。
必要な場合はご参照ください。

https://create-react-app.dev/docs/deployment/#github-pages
Google Apps Scriptで、S3のファイルをGoogleDriveにダウンロードする

# はじめに

以前Google Apps Scriptを使い、S3のCSVをスプレッドシートに書き出す方法を記事にしました。

https://qiita.com/a_b_/items/d4d1400805a952052198

今回は、S3にあるファイルをGoogleDriveにダウンロードする方法になります。

# 参考

https://qiita.com/wata_sakura/items/0a96f3f0510d8bb9b3ee

# やったこと

## AWS側
以下を作成します。
- S3バケット
    - 対象のファイルを置く
- IAMユーザ
    - 上記S3バケットへのGetObjectの権限あり
    - アクセスキーを取得する

手順は以前の記事と同じになります。

https://qiita.com/a_b_/items/d4d1400805a952052198#aws

S3のバケットには以下の画像を`testfolder/アイコン画像.png`として置きました。

![アイコン画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/c83e5819-c44c-a6d9-2e02-45b861ecff72.png)


## Google側
以下を行います。
- Apps Script編集画面を開く
- S3ライブラリの追加
- スクリプト記述

こちらも、以前の記事の方法と同じになります。

https://qiita.com/a_b_/items/d4d1400805a952052198#google-%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7%E3%83%BC%E3%83%88

コードは以下になります。各設定値にはそれぞれの値を代入ください。

```js:コード.gs
function myFunction() {
  // 設定値
  //// AWSのアクセスキーの情報
  const accessKeyId = '';
  const secretAccessKey = '';

  //// S3のファイルの情報
  const bucketName = '';
  const objectName = encodeURI(''); // パスに全角文字があった場合のためにエンコード
  
  //// Google Drive上のフォルダID
  const folderId = '';

  // 処理
  ////　S3インスタンスを作成
  var s3 = S3.getInstance(accessKeyId, secretAccessKey);
  //// ファイルを取得
  const data = s3.getObject(bucketName,objectName);

  //// 格納フォルダを指定
  var destfolder = DriveApp.getFolderById(folderId);
  /// フォルダ内にファイル作成
  destfolder.createFile(data);
}
```

### フォルダIDとは

`folderId`に代入するフォルダIDについて、URLの以下の画像の赤い部分が、フォルダIDになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/bbf50a19-00f2-8e2b-1ccb-38f3f329038d.png)

詳細は以下を確認ください。

https://tetsuooo.net/gas/748/

## 実行

実行すると、IDで指定したフォルダに、ファイルが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/32a4ffe3-a237-53cc-831f-ee9586e94443.png)

# おわりに
S3ライブラリにファイルをダウンロードする関数がなかったため、若干手間取りました。
わかってしまえばシートの操作がない分、以前よりかなり簡素な内容になりました。

本記事がどなたかの参考になれば幸いです。
2023年5月の個人目標

# 何をするか

1. 「SQLアンチパターン」を読み、学んだことをQiitaにまとめる
2. 6月の[Go conference](https://gocon.jp/2023/)への参加に向けてGoの基礎を勉強する
3. 今取り組んでいる個人開発を完成させて、tech BlogとしてQiitaにまとめる
4. 研究室の研究計画を終わらせる

## 「SQLアンチパターン」を読み、学んだことをQiitaにまとめる
先日、お世話になっているインターン先で新規機能開発を主導でやらせていただいたのですが、DB設計に関する技術力が足りなすぎると感じたので、ここで一度体系的に学ぼうと思います。


## 6月の[Go conference](https://gocon.jp/2023/)への参加に向けてGoの基礎を勉強する
現在、バックエンドエンジニアとして主にRubyを用いているのですが、ステップアップとしてGo言語の習得を考えている。
まずはGo言語の基礎学習を個人的に行い、基礎を理解した上でGo conferenceに参加する

## 今取り組んでいる個人開発を完成させて、tech BlogとしてQiitaにまとめる
詳しくは出来上がったらまた書くのですが、使用技術自体は以下です
- [ ] Ruby on Rails
- [ ] Next.js
- [ ] TypeScript
- [ ] ECS(Fargate)
- [ ] CloudFront
- [ ] github actions

です。（笑）

## 研究室の研究計画を終わらせる
これが一番達成がしんどそうです。
何がやばいのかって、何をすればいいのかがわからないことです。。
しんどいですが、地道にやっていこうと思います

## 最後に
今回、初めて月間目標を書いて投稿してみました。
5月末に振り返りとしてまた記事を書こうと思います。
今回は緩めに設定したので必ず全部達成しようと思います
CKA試験、Ingress Network Policy（命令語）

# Ingress Network Policy

## チートシート
https://kubernetes.io/docs/concepts/services-networking/network-policies/#networkpolicy-resource

```sh
kubectl create namespace customa
kubectl run poc --image=nginx --port=80 --labels=app=poc

vi allow-web-from-customa.yaml
```

```(修正前)allow-web-from-customa.yaml
```

```(修正前1)allow-web-from-customa.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - ipBlock:
            cidr: 172.17.0.0/16
            except:
              - 172.17.1.0/24
        - namespaceSelector:
            matchLabels:
              project: myproject
        - podSelector:
            matchLabels:
              role: frontend
      ports:
        - protocol: TCP
          port: 6379
  egress:
    - to:
        - ipBlock:
            cidr: 10.0.0.0/24
      ports:
        - protocol: TCP
          port: 5978
```


```(修正後)allow-web-from-customa.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-web-from-customa
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: poc # pod label 必要
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              partition: customa # namespace Label 必要
      ports:
        - protocol: TCP
          port: 6379
```

```sh
kubectl apply -f ./allow-web-from-customa.yaml
```
Unity ShaderGraphでGameObjectのRotationに対応した任意軸を固定したビルボードを作る

## 前回の記事
https://qiita.com/archeleeds/items/fe4d487105b0fac7ea92

## 概要
UnityのShaderGraphでGameObjectのRotationに対応した任意のXYZ軸固定のシェーダーを作ります
つまりGameObjectが回転してたら、それを考慮した回転軸になります

## 作り方
前々回表示した部分は省略
適当にVector3(0, 1, 0)と置いていた所を修正

ObjectノードでRotationが取れれば楽なんですが、取れないのでTransformation MatrixノードでModelの行列を引っ張ってきてVector3(0, 1, 0)と掛けます
実際に必要なのは回転ではなく方向なのでこの方法でも問題ないでしょう
平行移動は要らないので3x3だけMatrixに詰め直します

gifではGameObjectを適当に回転させてます
SpriteのUp方向を軸にビルボードしているのがわかるはず

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154377/10ab01c6-d1c6-1cf2-e5f2-5a7480b3ea96.png)
![image.gif](https://i.gyazo.com/e662c299fd9168ef468b30c5dc6a80fd.gif)

## 参考
参考に・・・というか移植が目的だったのでそのままです
ありがとうございます
https://qiita.com/kaneta1992/items/af7793e5450b891c2e27
【VBA Personal】Excelシート上の選択範囲内の図形をグループ化するマクロ

!!編集中のため、現在この記事のコードは参照しないようにしてください

# PERSONALに追加する

下記のコードをVBEのPERSONALに追加してください

※PERSONALについて知らない方は下記の記事を参考
https://vbabeginner.net/how-to-create-a-personal-macro-book/



```vb
Public Sub groupSelectedShapes()

    Application.OnKey "+^{g}", "groupSelectedShapes"

    Dim rngSelection As Range
    Dim selectionWidth As Single
    Dim selectionHeight As Single
    Dim targetShape As Shape
    
On Error GoTo ERR_HANDLER
    Set rngSelection = Selection
    selectionWidth = rngSelection.Left + rngSelection.width
    selectionHeight = rngSelection.Top + rngSelection.height
    
    Dim shapeWidth As Single
    Dim shapeHeight As Single
    Dim shapeCnt As Long
    shapeCnt = 0
    
    For Each targetShape In ActiveSheet.Shapes
        shapeWidth = targetShape.Left + targetShape.width
        shapeHeight = targetShape.Top + targetShape.height
        
        If rngSelection.Left < targetShape.Left And selectionWidth > shapeWidth And _
           rngSelection.Top < targetShape.Top And selectionHeight > shapeHeight Then
           shapeCnt = shapeCnt + 1

           If shapeCnt = 1 Then
               targetShape.Select
            Else
               targetShape.Select Replace:=False
            End If
            
        End If        
    Next
    
    If shapeCnt > 1 Then
        Selection.Group
        Exit Sub
    Else
        Call MsgBox(Prompt:="選択範囲内に2つ以上の図形が存在しません", Buttons:=vbExclamation, Title:="Error")
        Exit Sub
    End If
    
ERR_HANDLER:
    Call MsgBox(Prompt:="想定外エラーです。" & vbCrLf & "グループ化したい図形が入るようにセルを範囲選択し再実行してください。", Buttons:=vbExclamation, Title:="Error")
        
End Sub

```


# ショートカットキーについて

Application.OnKey "+^{g}", "groupSelectedShapes"　のところは好きなショートカットに変えてください。
ショートカットの記述方法は「Application.OnKey」で調べればすぐ出てきますし、
下記の記事コード内のコメントブロックにも記載しています。

https://qiita.com/kan3308/items/443b2c9ec495007f92a9


# 実行時の挙動

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734868/cf2c4bb0-19b4-9cf1-20e1-fc97383d05b0.png)



ショートカットキーからマクロ実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734868/e7e4b99f-1e9c-123f-d7ee-5b19ea278a55.png)



選択範囲内に図形が２つ以上存在しないときはエラーメッセージ表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734868/df0516b4-d370-cef8-dac0-c130c1dca392.png)
Apollo Kotlin のバージョンアップを楽にする


# Dependabot からの PR は、いつも RED になる・・・

私のプロジェクトでは GraphQL Client として [Apollo Kotlin 3.x](https://www.apollographql.com/docs/kotlin/) を使っています。

GraphQL スキーマからクライアントコードを出力してくれるプラグインを使っているんですが、バージョンアップがあると以下のようにプラグインの PR、ランタイムの PR が同時にオープンして、どちらも CI が RED になっている光景を何度か目にしており、改善したいと思っていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97890/8d5087b6-cab0-a100-b803-b382866b16a9.png)

なぜ RED になるかというと、エラーメッセージを見れば一目瞭然。
この 2 つはセットでバージョンアップする必要があります。
Dependabot の PR は一方の version しか書き換えていないので、どちらも同じエラーになっています。
まぁ、[公式のマニュアル](https://www.apollographql.com/docs/kotlin/#getting-started)を工夫もせずバカ正直にコピペしてるのが悪いんですけどね・・・

```:CI のエラーメッセージ(抜粋)
> Task :checkApolloVersions FAILED
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':checkApolloVersions'.
> Apollo: All apollo versions should be the same. Found:
  [3.8.0, 3.8.1]
```

# 変数で共通化する
何の変哲もない、バージョンを変数で宣言して、それを参照するやり方です。
```gradle:build.gradle
buildscript {
  ext {
    apolloVersion = "3.8.0"
  }
}

plugins {
  id 'com.apollographql.apollo3' version "${apolloVersion}"
}

dependencies {
  implementation "com.apollographql.apollo3:apollo-runtime:${apolloVersion}"
}
```

これで Dependabot を再実行すると・・・
PR がひとつになって CI も GREEN になりました。
ちゃんと変数部分に diff が出ています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97890/330cc010-56a1-7c60-ce05-50a5185083c9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97890/a91e1556-649c-b740-f435-6c22d1282a30.png)


# [おまけ] Gradle 8 のバージョンカタログを使ってみる

ちょうど同じ時期に Gradle 7.2 -> 8 へのバージョンアップもやりたくて、新機能を眺めていました。
それによると、「バージョンカタログ」というものが追加されたらしく[^1]、同じことができそうだったので試してみました。

https://gradle.org/whats-new/gradle-8/#version-catalog

[^1]: 正確には Gradle 7 のときから実験的な機能としてあったらしい


[マニュアル](https://docs.gradle.org/8.1.1/userguide/platforms.html#sub:version-catalog) を見ると、バージョンの定義は `settings.gradle` へ書く方法と `gradle/libs.versions.toml` に書く方法があるようです。
今回は後者を採用してみます。

```toml:gradle/libs.versions.toml 
[versions]
# 執筆時点では 3.8.1 が最新だが、dependabot の動作を検証するため意図的に古いバージョンを指定
apollo = "3.8.0"

[libraries]
apollo-runtime = { module = "com.apollographql.apollo3:apollo-runtime", version.ref = "apollo" }

[plugins]
apollo-compiler = { id = "com.apollographql.apollo3", version.ref = "apollo" }
```

```gradle:build.gradle
plugins {
  alias(libs.plugins.apollo.compiler)
}

dependencies {
  implementation(libs.apollo.runtime)
}

apollo {
  // ...
}
```

これで Dependabot を再実行すると・・・
バージョンカタログを認識し、 1 つの PR で GREEN にすることができました。
ちゃんと toml ファイルに diff が出ています。
なかなか頑張ってるな Dependabot。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97890/b264b5b1-db68-c427-8ca2-a29738cd7a54.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97890/a41160de-0879-509e-9716-a5b188c3e23f.png)


# まとめ
Apollo Kotlin のプラグインとランタイムを同時に更新させる方法を確認しました。
buildscript の方法の方が、手っ取り早くて良いかな。

Renovate であれば PR をまとめてくれるので、もっと雑に書いてあっても上手いことしてくれるんでしょうけど・・・
Linux 勉強用Surface go2 の設定WSL 

Linuxの資格(LinuC)の勉強がいつでもできるように、ポータブルなLinuxの実行環境を作ってみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/8a25e3c7-e7bf-9621-9239-4d860ab7b9a1.png)


# 物理的な準備
## 中古のSurface go2を買う
イオシスで買いました。
## キーボードを買う
Amazonで買いました。

# キッティング
## Windows update
初期状態ではWin10なので、Win11になるまでWindows Updateします。

## リモートデスクトップ
https://www.fmworld.net/cs/azbyclub/qanavi/jsp/qacontents.jsp?PID=8311-3510&rid=282

### 接続先(Surface go2)
設定　アカウント　アカウント名：xxxx
設定　リモートデスクトップ　
　オフ→ON
　PC名：aaaa

### 接続元（デスクトップPC）
リモートデスクトップ
PC名：aaa
アカウント名：xxxx

# WSL/Linuxのインストール
https://learn.microsoft.com/ja-jp/windows/wsl/install
上記を参考にします。

Surface go2 > プログラム >  Powershell 
>wsl --install
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/0df9e901-0d5b-ed5a-b55d-61eebb84b7da.png)
できた。

色々パッケージをインストール
Terminal > Ubuntu
sudo apt update && sudo apt upgrade

Surface go 2 上で Ubuntuの勉強環境ができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/4a309047-5355-bf82-4c25-97831f3cc053.png)

おわり
素人がChatGPTを用いてFPGAについて1年間学んだらどうなるのか-その1

最近**FPGA** (Field Programmable Gate Array)というデバイスについて知り、趣味の一環として自身でも使いこなせるようになりたい、ふとそう思った。
しかし、周りにはFPGAについて詳しい人はおらず、いたとしても私はコミュ症である。仲良くなれるはずもない。

#### そこで目を付けたのが、最近はやりのChatGPTである。
ここではFPGAについての素人がChatGPTを用いて
どこまで学ぶことができるのかを検証する。
実施期間は**1年**としているが、すぐやめてしまうかもしれないし、1年以上続けるかもしれない。あくまで個人的な実験である。見ている人は期待しないでください。

ちいかわを見るような優しい目で見てもらえると幸いである。
長く続けられるよう、また1年間の記録のためQitaへの投稿する。

とはいえ1年間続けると考えるとまずはマイルストーンを設定する必要がある。
会社でもよく言われる計画というやつである。こんなことを書いていると業務のようだ。
次の記事ではFPGAを用いてやりたいことと、それに向けたマイルストーン設定について記載する、、、予定である。
PythonでCSVファイルの各先頭のスペースを全て削除する

`skipinitialspace=True`を指定することで先頭の半角スペースだけ削除できます。

```Python
import csv

csv_file = open('sample.csv', 'r', encoding='cp932', errors='', newline='')
f = csv.reader(csv_file, delimiter=',', doublequote=True, lineterminator='\r\n', quotechar="'", skipinitialspace=True)
newfile = open('sample_nospaces.csv', 'w', encoding='cp932')
writer = csv.writer(newfile, doublequote=True, lineterminator='\n')
header = next(f)
writer.writerow(header)
for row in f:
    row = row
    writer.writerow(row)
csv_file.close()
```

```sample.csv
id,NO1,NO2,NO3,NO4,NO5
101,1,1,1,1,1
102, a b ,　a b,1,2 ,1
103, ,,,,
104, , 3,1,1,1
```

```sample_nospaces.csv
id,NO1,NO2,NO3,NO4,NO5
101,1,1,1,1,1
102,a b ,a b,1,2 ,1
103,,,,,
104,,3,1,1,1
```
[Obsidian]Markdown用のCSSを頑張って作ってみた[随時更新]

# はじめに
普段のメモはObsidianを使っています。
Markdownサイコー！なんですけど、HTMLに出力する際にはやはりCSSを適用しておかないと読みづらいので、Obsidian用のCSSを作成しました。

基本的にはWeb上のどこかから拾ってきたやつの寄せ集めです。

この記事は随時更新していく予定です。


# ObsidianでのCSSスニペット設定方法
CSSを作成するついでに、ObsidianでのCSSスニペット設定方法についても併せて記載しておきます。

1. 設定(歯車アイコン)をクリック
1. [オプション]の[外観]を選択
1. [CSSスニペット]-[style]のチェックをONにする
1. [CSSスニペット]の右側にあるフォルダアイコンをクリックし、snippetsフォルダを開く
1. 準備した「style.css」を保存する

# CSSをつくってみた
以下、作ってみたCSSです。
CSSは得意ではないので、フォーマットとかは目をつぶってください。
コメントは気が向いたら追記していこうと思います。

```css:style.css
/* Please visit the URL below for more information: */
/*   https://shd101wyy.github.io/markdown-preview-enhanced/#/customize-css */ 
  h1 {
    /*文字の上下 左右の余白*/
    padding: 0.4em 0.5em;
    /*文字色*/
    color: #494949;
    /*背景色*/
    background: #f4f4f4;
    /*左線*/
    border-left: solid 5px #7db4e6;
    /*下線*/
    border-bottom: solid 3px #d7d7d7;
  }

  h2 {
    position: relative;
    padding: 0.5em;
    background: #7db4e6;
    color: white;
  }

  h2::before {
    position: absolute;
    content: '';
    top: 100%;
    left: 0;
    border: none;
    border-bottom: solid 15px transparent;
    border-right: solid 20px rgb(149, 158, 155);
  }

  h3 {
    color: #494949;
    padding: .5em .75em;
    border-bottom: 2px solid #7db4e6;
  }

  h5 {
    display: inline-block;
    position: relative;
    z-index: 8;
    margin: 0;
    padding: 8px;
    color: #fff;
    font-size: 12px;
    font-weight: 400;
    background-color: #5a6165;
  }

  .div h5 {
    margin-top: -30px;
    padding-top: 56px;

  }

  /* テーブル */
  table {
    border-collapse: collapse;
    border: 1px solid #CCC;
  }
  th, td {
    padding: 5px 10px;
    border: 1px solid #CCC;
  }
  th {
    background: #EEE;
  }

  /* 数字付き箇条書き */
  ol
  {
      counter-reset: section;
      list-style-type: none;
  }
  ol li:before
  {
      counter-increment: section;
      content: counters(section, "-") ". ";
  }
  

  /* https://logicalbeat.jp/blog/3769/ */
  /**
  * codeタグ（コードテキスト）
  */
  code {
    font-family: "Meiryo", Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
  }

  /**
  * preタグ（整形済みテキスト）
  */
  pre {
    font-family: "Meiryo", Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
  }

  /**
  * blockquoteタグ（引用）
  */
  blockquote {
    border-color: #ea5219;
  }

```




# 参考
- [【ドキュメント】Markdownドキュメントのデザインをロジカルビート風にしてみた](https://logicalbeat.jp/blog/3769/)
Unity ShaderGraphで任意のXYZ軸を固定したビルボードを作る

## 前回の記事
https://qiita.com/archeleeds/items/1100c773a1740b7e7de0

## 概要
UnityのShaderGraphで任意のXYZ軸固定のシェーダーを作ります
前回のものより計算量が多め

## 作り方
前回表示した部分は省略
回転に使用する行列だけガラッと置き換えた

まず中段のノードでどの軸を固定にするか決める（今回はYなのでYを1に）
次にカメラからビルボードへのベクトルと固定軸の外積、更にその結果と固定軸をもう一度外積すれば、
UpとRightとForwardが揃うのでそれをMatixとして組み合わせる

前回と違ってメッシュに使っても問題ない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154377/53846b60-58b9-8b58-7ebc-dbb266479fe8.png)
![image.png](https://i.gyazo.com/73b8024a4fbf8923719db0015523cd48.gif)

## 参考
参考になりました。ありがとうございます
- 回転行列のベース
    - https://qiita.com/kaneta1992/items/af7793e5450b891c2e27
vscode-input-sequenceが壊れちゃって困ってる人は今すぐ設定を変えろ

VSCodeで連番生成するのに欠かせない拡張機能が [vscode-input-sequence](https://marketplace.visualstudio.com/items?itemName=tomoki1207.vscode-input-sequence) 。
しかし、今年に入ったくらいからうまく動作しなっちゃった...が、設定変えたら治ったって話。

↓のissueで有志が解決方法を提示してた。

[recently,it is repeated for each character entered #15](https://github.com/tomoki1207/vscode-input-sequence/issues/15)

> I encountered with the same issue. I found the reason is that vs code get an unexpected value for the variable replaceSelection in function function perform(initial, editor, options, undoStop) .
Forcing replaceSelection to be true, I get what I want.

↑のリンク先ではJSON設定が書かれてるけど、GUIから操作したほうが楽。
`Sequence: Replace Selection` にチェック入れるだけ↓。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214979/dfa531b5-ea25-f8a4-d771-7f3e4f7a4594.png)

これで治った❗

助かった。この拡張ないとマジで不便なんだよね。
というか、これを入れてない人ってどうやって作業してるの❓ってレベル。

適当なテストコード用に配列を10個ぐらい定義したいときあるじゃん❓
配列のインデックス(もしくは値)を0~9までチマチマタイプするのめんどくさい。めんどくさくない❓
この拡張を使えば一発で入力できる。
皆さん使おうね❗
お金管理するアプリ作りたいって言ってみた

もちろん、お手伝いします！お金を管理するシステムを作るためには、まずどのような機能が必要かを明確にしましょう。一般的なお金管理システムには、次のような機能が含まれます：

1. 収入の追跡
2. 支出の追跡
3. カテゴリ別の予算設定
4. 残高の確認
5. 貯金目標の設定と追跡

Pythonを使って、これらの機能を持つシンプルなお金管理システムを作成することができます。以下に、最も基本的な機能を持つコード例を示します。

```python
class MoneyManager:
    def __init__(self):
        self.income = {}
        self.expenses = {}

    def add_income(self, source, amount):
        self.income[source] = amount

    def add_expense(self, category, amount):
        self.expenses[category] = amount

    def get_total_income(self):
        return sum(self.income.values())

    def get_total_expenses(self):
        return sum(self.expenses.values())

    def get_balance(self):
        return self.get_total_income() - self.get_total_expenses()

```

このコードは、`MoneyManager`というクラスを定義しています。このクラスには、収入と支出を追加するメソッド、収入と支出の合計を計算するメソッド、残高を計算するメソッドが含まれています。

このクラスを使用して、お金管理システムを作成するには、次のようにインスタンスを作成し、収入と支出を追加します。

```python
my_money = MoneyManager()

my_money.add_income('Salary', 300000)
my_money.add_income('Part-time Job', 50000)

my_money.add_expense('Rent', 100000)
my_money.add_expense('Food', 50000)
my_money.add_expense('Utilities', 20000)

print('Total Income:', my_money.get_total_income())
print('Total Expenses:', my_money.get_total_expenses())
print('Balance:', my_money.get_balance())
```

この例では、収入と支出を追加し、合計収入、合計支出、および残高を表示しています。このコードは単純な例ですが、これを基にして、必要な機能を追加して独自のお金管理システムを作成することができます。

例えば、予算機能や貯金目標追跡機能を追加したり、データをCSVやデータベースに保存したりすることができます。また、視覚化ツールを使用して、支出や収入のグラフを表示することもできます。Pythonにはさまざまなライブラリがありますので、お金管理システムをさらに充実させることができます。例えば、matplotlibやseabornを使ってデータの視覚化を行ったり、pandasを使ってデータ操作を簡単に行ったりすることができます。また、データベースとの連携には、SQLiteやSQLAlchemyを利用することができます。

以下に、pandasとmatplotlibを利用したデータ視覚化の例を示します。

```python
import pandas as pd
import matplotlib.pyplot as plt

class MoneyManager:
    # (以前のコードと同じ)
    # ...

    def generate_expense_report(self):
        expenses_df = pd.DataFrame(list(self.expenses.items()), columns=['Category', 'Amount'])
        expenses_df.set_index('Category', inplace=True)
        expenses_df.plot.pie(y='Amount', legend=None, autopct='%.1f%%', figsize=(6, 6))
        plt.title('Expenses Breakdown')
        plt.ylabel('')
        plt.show()

# インスタンスの作成と収入・支出の追加
# ...

my_money.generate_expense_report()
```

この例では、`generate_expense_report`メソッドを`MoneyManager`クラスに追加しました。このメソッドでは、pandasのデータフレームを使って支出データを整形し、matplotlibで円グラフを表示しています。

このように、Pythonのライブラリを活用することで、お金管理システムをカスタマイズして機能を追加していくことができます。また、ウェブアプリケーションやモバイルアプリケーションとして利用できるように、FlaskやDjangoのようなウェブフレームワークを使って構築することもできます。
【チェックシート】システム開発において、基本・詳細設計書のレビューでよくある指摘観点をまとめる

# はじめに
SAP社のエンタープライズPaaS製品である、SAP Business Technology Platform（BTP） で業務アプリケーション開発をしている@fussasyです。これまで開発プロジェクトを経験する中で、チームメンバーの設計レビューをする機会が多くありました。やはり、レビューでは似たような指摘も発生してしまい、手間に感じている部分もありましたので、まとめてしまいたいと思いました。
当記事ではレビュイーが設計書レビューに向かう前の事前チェック資料、もしくはレビュアーがレビューをするための補足資料として活用していただければと思います。アプリケーション開発する際、品質の向上に繋がれば嬉しく思います。なお、この記事については随時、更新すると思います。

# チェック観点
当資料は、基本設計書（外部設計書）および詳細設計書（内部設計書）の両方で利用できる、汎用的な内容を含んでおりますので、各設計書のフォーマット独自に設定された項目については対象外としています


### 設計書全般に関するチェック事項
機能要件について、内容を把握しレビュアに対して説明できること
非機能要件について、内容を把握しレビュアに対して説明できること
誤字・脱字について全体を見返して確認したこと
変更履歴（設計書ヘッダに記載項がある場合は併せて）に、プロジェクト管理に関する情報の記載漏れがないこと
提供されている記述ルールに従って記述していること
言い切りの形で記述していること（できないこと、しないことを明確にするため）
捉え方が異なる表現方法を使用していないこと（特に、二重否定は使用しない）
5W1Hハッキリと記述していること
設計の際、仕様が不明瞭なものについては、関係者にQAを実施し回答を刈り取っていること
設計の際、関係者にQAを実施し、回答を刈り取ったものについて、証跡を一覧として提示できること
基本設計書について、レビュアに対して要件定義書からの反映箇所を説明できること
詳細設計書について、レビュアに対して基本設計書からの反映箇所を説明できること
使用する言葉は各シートで統一していること（各種テーブル、各種メッセージ、共通モジュール、等)
ペンディングとなっている箇所を明記し一覧化していること
ペンディングとなっている箇所に日付と内容を記載していること
レビュー後に仕様変更が発生している場合、変更管理表に記載されていること
レビュー後に仕様変更が発生している場合、設計書の変更履歴へ管理番号を更新していること（ver.1.00→1.01等）
レビュー後に仕様変更が発生している場合、設計書の変更履歴へ変更内容の概要を記載していること
レビュー後に仕様変更が発生している場合、設計書の変更箇所が分かるように赤字にする、または同行の枠外に「ver.1.01 修正」等の記載をしていること


### 機能・非機能要件に関するチェック事項
以下、要件に関する情報を確認して明確にしており、設計書に記載されていること

背景・目的・役割・処理内容・制約（利用可能時間　等）
画面レイアウト全般（文字、文字数、文字タイプ、項目レイアウト、項目幅、テーブルレイアウト、画像、画像位置、画像幅、ヘッダ情報・フッダ情報　等）
画面遷移時の挙動（同タブ、新タブ、新ウィンドウ）
各ボタン押下時の挙動
各フレームワーク標準機能の利用有無
タブ切り替え時の挙動（タブ順）
カーソル制御の要否
機能の共通化検討
対象データと対象外データの判定条件
業務ロジックの判定条件
集計処理の挙動想定
単一値と範囲値の挙動想定
数値計算処理の挙動想定（0除算が発生しない、マイナス値の許容、オーバーフロー発生）
日付計算処理の方式（営業日・カレンダ日数・JST時刻・UTC時刻　等）
エラー・警告・情報の発生条件（オンライン処理・バッチ処理）
エラー・警告・情報の発生時の挙動（オンライン処理・バッチ処理（処理レコードスキップして続行かどうか等））
エラー・警告・情報の発生時のメッセージ内容（オンライン処理・バッチ処理）
オンライン処理の処理動作（ゼロ件、1件、複数件　等）
オンライン処理の処理件数の想定（最大・平均）
オンライン処理の処理件数の年次（月次）増加想定（最大・平均）
バッチ処理の処理動作（ゼロ件、1件、複数件　等）
バッチ処理の処理件数の想定（最大・平均）
バッチ処理の処理件数の年次（月次）増加想定（最大・平均）
バッチ処理は並列・並行のどちらを許すか
バッチ処理は同期・非同期のどちらを許すか
バッチ処理のコミット要件・ロールバック要件
バッチ処理の処理タイミング
複数バッチ処理の場合、ジョブ構成（番号・名称・実行順・実行時間想定・並列数・多重度　等）
複数バッチ処理の場合、ジョブのリカバリー方法（リランポイント・リカバリー手順　等）
データベース操作のデータ想定（ゼロ件、1件、複数件　等）
データベース操作の制約（時間帯・権限　等）
データベース操作方法（REST API　等）
データベース操作時の排他要件・排他解除要件
データベースに登録した内容の保持期間・削除条件・削除方法
データベースに登録した内容の保持に関する監査要件
ユーザーの認証・認可・権限に関すること
システムのパフォーマンス（レスポンス　等）
アップロード処理（ファイル形式、ファイルレイアウト、ヘッダ有無　等）
ダウンロード処理（ファイル形式、ファイルレイアウト、ヘッダ有無、ファイル名　等）

# おわりに
基本設計書と詳細設計書で分けて書いていたんですが、似たような内容となってしまったので集約しました。受託開発だと設計書を作成する作業はどうしても多いと思うので、参考になれば嬉しいです。
Python2.7でsjisのCSVをutf-8で読み込む方法

Python 2.7を使用して、Shift JIS（SJIS）エンコーディングのCSVファイルをUTF-8で読み込む方法を以下に示します。この例では、`csv`モジュールと`codecs`モジュールを使用しています。

まず、`csv`モジュールと`codecs`モジュールをインポートします。

```python
import csv
import codecs
```

次に、Shift JISエンコーディングのCSVファイルをUTF-8で読み込む関数を定義します。

```python
def read_sjis_csv(file_path):
    with codecs.open(file_path, 'r', 'shift_jis') as file:
        reader = csv.reader(file)
        for row in reader:
            utf8_row = [unicode(cell, 'utf-8') for cell in row]
            print(utf8_row)
```

この関数では、Shift JISエンコーディングのCSVファイルを指定したパスから読み込んでいます。ファイルを開く際に`codecs.open()`を使用し、エンコーディングを`shift_jis`と指定します。その後、`csv.reader()`を使ってCSVファイルの内容を読み込みます。各行をUTF-8に変換して出力しています。

この関数を使って、Shift JISエンコーディングのCSVファイルを読み込むには、次のように呼び出します。

```python
file_path = 'path/to/your/sjis_csv_file.csv'
read_sjis_csv(file_path)
```

この方法で、Python 2.7を使用してShift JISエンコーディングのCSVファイルをUTF-8で読み込むことができます。ただし、Python 2.7はサポートが終了していますので、できるだけPython 3.xに移行することをお勧めします。
Hexabase TypeScript SDKを使ってワークスペースをCRUD操作する

[Hexabase（ヘキサベース）](https://www.hexabase.com/)は企業においても安心して利用できるBaaS（Backend as a Service）を提供しています。多くのBaaSがそうであるように、主にフロントエンド開発者に利用してもらいたいと考えています。そこで現在、TypeScript SDKの開発が進められています。

この記事ではHexabase TypeScript SDKのインストールと、Hexabaseの基盤となるワークスペースを操作する方法を解説します。

## インストール

インストールはnpmやyarnを使って行います。

```
# npmの場合
npm install @hexabase/hexabase-js

# yarnの場合
yarn add @hexabase/hexabase-js
```

## インポート

インポートすると、 `HexabaseClient` というオブジェクトが取得できます。

```jsx
import { HexabaseClient } from "@hexabase/hexabase-js";
```

## 初期化

HexabaseClientを初期化します。

```jsx
const client = new HexabaseClient();
```

### 認証

Hexabaseでは業務利用を想定しているため、利用する際に認証情報が必須になります。最初はメールアドレスとパスワードで認証し、その後はトークンを使ってGraphQLにアクセスします。 `client` を使って処理します。

初回の認証は次のようになります。emailとパスワード、またはトークンが必須です。

```jsx
await client.login({email, password, token});
```

後はこの `client` に対して処理を行います。

## 現在のワークスペースを取得する

ログインした時点でHexabaseClientのcurrentWorkspaceが現在のワークスペースオブジェクトになっています。

```jsx
client.currentWorkspace
```

ワークスペースを切り替える場合には、 `workspace` メソッドを使います。

```jsx
client.workspace(newWorkspaceId);
```

## すべてのワークスペースを取得する

ログインしているユーザーに紐付いているすべてのワークスペースを取得する際には `workspaces` メソッドを使います。

```jsx
const workspaces = await client.workspaces();
```

他にも現在のワークスペースとその他のワークスペースを取得する `workspacesWithCurrent` もあります。

```jsx
const { workspace, workspaces } = await client.workspacesWithCurrent();
```

## ワークスペースを切り替える

作業するワークスペースを変更する場合には `setWorkspace` メソッドを使います。

```jsx
await client.setWorkspace(workspaceId);
```

## ワークスペースを作成する

ワークスペースを作成する場合には `save` メソッドを使います。

```jsx
const workspace = client.workspace();
workspace.name = 'new Workspace';
await workspace.save();
```

## ワークスペースをアーカイブする

ワークスペースは削除ではなく、アーカイブを行います。

```jsx
await workspace.archive();
```

## まとめ

ワークスペースはHexabaseを操作する上での基盤になります。ここからプロジェクト、データストアと階層構造になっています。オブジェクトを使っている限りは意識することはないと思いますが、覚えておくとHexabaseの操作が楽になるはずです。

Hexabase TypeScript SDKを使えば、VueやReactなどと連携したWebアプリを素早く開発できるようになります。2023年04月現在絶賛開発を進めていますので、ぜひ試していただいてフィードバックいただければ嬉しいです！

[hexabase/hexabase-js](https://github.com/hexabase/hexabase-js)