OmniAICreator/Qiita-1.07M huggingface dataset:
【備忘録】ラスパイ上にSQLサーバーを立てて別PCからアクセスできるようにする　-作業目安20分-

# 概要
ラズパイにSQLサーバーを立ててローカルネットワーク上の別PCからwebアクセス出来るようにする。

◇参考リンク
Raspberry PiをSQLサーバーにして、Python3からMySQLのデータを検索して表示させるまで
https://qiita.com/p3ishnm2/items/078d8d7a47ee3b7abc31
# インストールするパッケージ一覧
- mariadb ：データベースシステム
- Apatch2 ：webサーバーソフトウェア 
- php ：スクリプト言語　
- phpMyAdmin ：webアプリケーション 

# 実施内容
0.既存パッケージを更新する
1.ラズベリーパイ上にデータベースを構築する
2.構築したデータベースをwebページから操作可能にする
3.ネットワーク上の別PCからアクセス可能にする

## 0.既存パッケージの更新
パッケージをインストールする前に既存パッケージの更新をしておきましょう。
```
$sudo apt-get -y update
$sudo apt-get -y upgrade
```

## 1.ラズベリーパイ上にデータベースを構築する
データベースシステムmariadbをインストールする。
```
$ sudo apt update
$ sudo apt install -y mariadb-server
```
mariaDBを起動し、接続する。
```
$ sudo systemctl start mariadb
$ sudo mariadb
```



別PCからアクセス可能な新規ユーザーを作成する。
※コマンド内のユーザ名とパスワード部分は任意のものに書き換えて下さい。
```
create user 'ユーザ名'@'%' identified by 'パスワード';
```
## 2.構築したデータベースをwebページから操作可能にする
下記パッケージ3つをインストールする。
- webサーバーソフトウェア Apatch2
- スクリプト言語　php
- webアプリケーション phpMyAdmin
```
$ sudo apt install apache2
$ sudo apt install php
$ sudo apt install phpmyadmin
```
phpmyadminをインストール中、下記のように設定するwebサーバを選択する画面が表示されるのでapache2をスペースで選択してEnter。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3745465/98ec3b74-3dbf-e7b7-18b4-b4029966ef1e.png)

続いてこちらは＜はい＞を選択してEnter
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3745465/c5ba9359-f6ce-ac05-0ef0-c6c757cf3223.png)

インストール完了するとラズパイ上のwebブラウザから下記のリンクにアクセスができるようになっているはず。(1で作成したアカウントを使ってログインも可能。)

http://localhost/phpmyadmin/
※ログインできない場合はlocalhost部分を127.0.0.1に書き換える。
http://127.0.0.1/phpmyadmin/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3745465/cbb8f698-849c-3a1e-dc73-34d51c1625ea.png)

## 3.ネットワーク上のPCからのアクセスも可能にする
デフォルト状態だと、外部PCからのアクセスができない。
(bind-addressという項目によってローカルホスト上(127.0.0.1)、つまりラズパイ上からのみしかアクセスできない設定になっている)

下記のコマンドで設定ファイルを開く
```
$ sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
```
bind-addressをコメントアウトするとすべてのIPアドレスから接続ができるようになる。
```
#bind-address     =127.0.0.1
```
bind-address項目を追加すれば、特定のIPアドレスからのみ接続できるようにも設定可能。
```
bind-address     =127.0.0.1
bind-address     =[アクセス許可したいIPアドレス]
```

これでSQL webサーバーの構築が完了。
別PCのブラウザより下記のアドレスにアクセスできるはず。
※[ラズパイのIPアドレス部分]は書き換えること。

http://[ラズパイのIPアドレス]/phpmyadmin
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3745465/ff77809b-d833-e991-2267-5a825e3581c3.png)

# メモ
## １.sudo matribdbコマンドエラー
sudo matribdb コマンドでデータベースに接続しようとした時、"ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)"というエラーが出た。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3745465/f4bb921b-3fdb-5c5b-8d25-ea43a91b4740.png)

matribdbのサービスを起動させていないと発生するエラーのようです。
”1.ラズベリーパイ上にデータベースを構築する”に記述の通り、sudo systemctl start mariadbコマンドでmatribdbを起動させてから接続すること。

## 2.myphpadmin上でのエラー
本記事完了後、テーブル作成→表示する所でエラー発生しました。
調べるのに手こずったので備忘録新規作成しました。
```Warning in ./libraries/sql.lib.php#613
count(): Parameter must be an array or an object that implements Countable
```
https://qiita.com/watermelon_saisai/items/9400bafa72792c35e894
makeを使ってSlackのステータスが自動で更新されるようにした話

## はじめに
 「自分が学校にいるときに自動でSlackのステータスを更新するツール，欲しい！！！！！」と思ったので，作りました．ただし，ノーコード開発です．私はバックエンド言語がまだ書けないので，なるべく早く実装するというのを優先し今回は既存のツールに頼ることにしました．~~初めて自力でアプリっぽいものが作れてウキウキなので以下に記録を残します.~~ **完全に方法を間違っていました．せっかく書いたものを消すのが惜しいので残しますが，以下の記事は参考にしないでください.**


## 0. やったこと
[make](https://www.make.com/en)（旧Integromat）というノーコードツールを使用して，GoogleマップとSlackを連携しました．

## 1. Googleマップ側の設定
アカウント登録を終えたら"organizationページ"から右上の➕ボタンを押して新しいシナリオ(makeで言うアプリみたいなもの)を作ります．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3520486/59bb0b12-d88a-9d42-e353-3daabbc371c7.png)

Googleマップを選択し, 位置情報が欲しいので次のページでは"Get a Location"を選びます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3520486/45ff3a6d-19f7-63d2-8423-7b09de5de856.png)

続いて位置情報の指定．住所と緯度経度が選べますが今回は後者を選びました．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3520486/87353f3b-d57e-1e09-f3dd-7b62657ce75e.png)
また，この時にAPIの登録も求められます．
### [Google Maps Platform](https://mapsplatform.google.com/intl/ja/)について
　自分の位置情報を取得するにあたりGoogle Maps APIを利用しました．1 か月あたり 28,500 回まで無料で地図が読み込めるのですが，今回は無料で十分そうです．
 
## 2. Slack側の設定
Googleマップの設定が終わったので同様にSlackの方もやっていきます．"Add anothor module"から"Slack"，続いて"Set a Status"を選びます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3520486/544a5300-5064-0cf8-5b13-2c713e4c753d.png)
このようにステータスを設定できます．~~"status expiration"にどう入力すればいいのかわからなかったため，とりあえず自分が大学を卒業する20XX年の3月31日を指定しました．~~ "status expiration"は必要なかったです．

## 3. その他の設定
実行時間の間隔を選びます．makeでは15分以上を設定でき，特定の曜日なども選択できます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3520486/beed23be-2d41-d93c-39b9-654d639df2a0.png)

必須箇所を全部埋めたので．いざ実行ボタンを押します．

![スクショ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3520486/cd25c7bd-de50-19aa-29be-0762da4658e2.png)
できました！！！！喜びの舞

## おわりに
試行錯誤したものたち...
- [IFTTT](https://ifttt.com/explore)
Slackのステータスを変えるトリガーが有料になってたので諦めました．
- [zapier](https://zapier.com/app/dashboard)
Googleマップとお友達じゃありませんでした(連携先にありませんでした)．
- [GAS](https://workspace.google.co.jp/intl/ja/products/apps-script/)
諦めました．

makeはナビゲーションが親切で分かりやすいのが良さだと思いました．
ローコード開発は便利で楽しいですね．

--
**2024/04/04追記**
Googleマップ側の設定で正確な緯度経度を入れたはずなのにどこに行っても「大学にいます」と表示されます．単にGPSの精度が悪いのか，どこか入力を間違えているのか･･･．同じ経験のある方いらっしゃいましたら，是非教えて下さい！涙
dockerでffmpegを使って動画ファイルの圧縮や動画形式変換を行う

# やりたいこと
dockerコンテナ上でffmpegを使って、動画ファイルの圧縮や動画形式の変換を行う方法をまとめます。
# Dockerfile
```
FROM ubuntu:20.04

RUN apt-get update && apt-get install -y \
      wget \
      xz-utils

WORKDIR /tmp

RUN wget https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-amd64-static.tar.xz \
      && tar xvf ./ffmpeg-git-amd64-static.tar.xz \
      && cp ./ffmpeg*amd64-static/ffmpeg /usr/local/bin/

CMD /bin/bash
```

# Dockerイメージのビルド
```
$ ls ./ffmpeg-docker/
Dockerfile
$ docker build -t ffmpeg:latest ./ffmpeg-docker/
Sending build context to Docker daemon  2.048kB
Step 1/5 : FROM ubuntu:20.04
(略)
Successfully tagged ffmpeg:latest
```
私の環境ではdockerのバージョンはDocker version 20.10.18, build b40c2f6でした。
# Dockerコンテナの起動
処理したい動画の入っているディレクトリをコンテナ側にマウントします。
```
$ docker run --rm -ti -v {ホスト側マウント元ディレクトリ}:{コンテナ側マウント先ディレクトリ} ffmpeg:latest /bin/bash
```
# 動画の圧縮・変換
私のiPhone 15 proで撮影した.MOVの動画ファイルをmp4に変換、また圧縮を行ってみます。
```
$ ffmpeg -i input.MOV -crf 23 output.mp4
（略）
[libx264 @ 0x7d40b80] ref B L0: 85.7% 11.1%  3.1%
[libx264 @ 0x7d40b80] ref B L1: 95.1%  4.9%
[libx264 @ 0x7d40b80] kb/s:1888.54
[aac @ 0x9179d40] Qavg: 405.099
$ ls -lh input.MOV | awk '{print $5}'
22M
$ls -lh output.mp4 | awk '{print $5}'
4.5M
```
22MBの動画ファイルが4.5MBになり、問題なく再生できました。crfの数値を上げると動画の品質が下がり、ファイルサイズが小さくなります。

# 参考記事
- https://qiita.com/nikola-f/items/798547356dcc47239702
- https://www.johnvansickle.com/ffmpeg/faq/
- https://syobochim.hatenablog.com/entry/2021/01/07/004600
【TypeScript】オブジェクトのプロパティをオプショナルにする

`Partial<T>`を使用するとオブジェクトのプロパティをオプショナルにできます。

```ts
type User = {
  id: number
  name: string
}
 
type OptionalUser = Parthial<User>
// {
//   id?: number | undefined;
//   name?: string | undefined;
// }

```
laravel データベースから情報を取得するときの違い（DBファサード・モデル）

## 概要

laravelでDBから情報を取得したいときの方法は、DBファサードを使う方法とモデルを使う方法がある。それぞれどのような違うがあるのか簡単にまとめてみる。
本記事で取り上げる意外にもおそらく差分は存在するが思いつくものだけをメモ的にざっくりまとめてみようと思う。

## 前提

便宜上「インスタンス」という言葉を多用するが、インスタンスそのものが何であるかは今回は重要ではない。実際とは若干異なるかもしれないが「データの集合を入れておく箱」と思っていただいて問題ない。

## DBファサード

### 記載例

ユーザーテーブルの全情報を取得したい場合、下記の様に記載する。下記をtinkerで実際に実行してみる。

```php
use Illuminate\Support\Facades\DB;

$user = DB::table('users')->where('id', 1)->first();

var_dump($user);
```

`$user`の変数には、プロパティにユーザーのレコード情報を格納した`stdClass`というクラスのインスタンスが格納される。

## モデル

### 記載例

ユーザーテーブルのidが1のユーザー情報を取得したい場合、下記の様に記載する。下記をtinkerで実際に実行してみる。

```php
use App\Models\User;

$user = User::find(1);

var_dump($user);
```

`$user`の変数には、プロパティにユーザーのレコード情報を格納した`User`というモデルクラスのインスタンスが格納される。

## ざっくりまとめ

二種類の取得方法で大きな違いは、「レコード情報郡が入っている箱（インスタンス）」である。
下記の様にインスタンスに違いがある

- DBファサード → stdClassのインスタンス
- モデル → Userモデルクラスのインスタンス

この二種類のインスタンスがどのくらい差があるかというと、無印良品の「シンプルな筆箱」と小学生御用達の「多機能筆箱」くらい差がある。
ちなみに「DBファサード → stdClassのインスタンス」が無印良品の「シンプルな筆箱」で「モデル → Userモデルクラスのインスタンス」が「多機能筆箱」である。

「シンプルな筆箱」は鉛筆を入れておく以外の機能を持たない。
逆に「多機能筆箱」は鉛筆削りがあったり、鉛筆ホルダーがあったり、何かと便利な機能が入っている。

ただし、「筆記用具を入れておける・取り出して使える」という部分はどちらの筆箱でも共通している。これはlaravelのデータ取得にも言えることで、極論をいうとこの共通のできることを満たしたいならどっちを使っても良い。

しかし、どちらの筆箱にも適材適所は存在するようにデータ取得でも得手不得手は存在する。

利点を簡単にまとめる。　下記以外にももちろんたくさんある。

- DBファサード
    - ただ単に指定テーブルのレコード情報だけが手っ取り早くほしい。
    - 実行するSQLを引数で渡したい。
- モデル
    - 関連テーブルのレコード情報もほしい。（※別途、モデルクラス内部にリレーションメソッドの定義は必要）
    - 取得したレコード情報をモデルクラスで定義されているメソッド使って加工したい。

## 「laravelでレコード情報を取得する」と言ったら基本モデルを使う（気がする）

ここまで長々と説明してきたが、基本的にlaravelでレコード情報を取得する場合はモデルクラスを使うと思って良いのではないだろうか。
DBファサードは「モデルクラスでは実現できない複雑なSQLを実行する」ときや「モデルのインスタンスを作るほどでも無いテストコード」など、使用箇所は限定されている気がする。

DBのI/Oにモデルを使うとここでは書ききれないほどの利点がある。（キャスト、一括insertのキー許可、データ型、、、などなど）
若干使いこなせるまではストレスが有るかもしれないが、後々楽になってくるのでモデルを使うほうがよいと感じる。

## 参考文献

https://qiita.com/miriwo/items/c6d604c64dbc6ff68545
会社員がIT知識ゼロからIOSエンジニア本気で目指してみた。

# 自己紹介
1　20歳
2　会社員（設備管理）（2024/4/1現在）退職2024/10/31
3　ながさき在住



# きっかけ
「今の会社自分に合ってないな・・・」
「MacBook持ってるし、元々ITエンジニア興味あったから本格的に転職しよう‼️」
そう決めた数日後には、iosアプリ開発のスクールに申し込んでました。笑



# 目標
経験を積んだらリモートワークがしたい
会社に貢献しつつ自分のアプリもたくさんの人に使われるように頑張る
Railsのcollection_check_boxesのカスタマイズ

Railsの`collection_check_boxes`メソッドは、複数選択が可能なフォームを簡単に生成できる非常に便利なヘルパーメソッドです。デフォルトの表示ではモデルの特定の属性（例えば名前やID）のみを表示させることが多いですが、カスタマイズすることで他の情報も表示可能です。本記事では、`collection_check_boxes`メソッドにブロックを渡すことで、より詳細な情報を含めたカスタマイズを行う方法を紹介します。

### 基本的な使用法

`collection_check_boxes`メソッドの基本的な使用法は以下の通りです。

```erb
<%= form.collection_check_boxes :attribute_name, collection, :value_method, :text_method %>
```

- `:attribute_name` - フォームが操作する属性名。
- `collection` - チェックボックスとして表示するオブジェクトのコレクション。
- `:value_method` - コレクション内の各オブジェクトから値を取得するためのメソッド。
- `:text_method` - コレクション内の各オブジェクトから表示テキストを取得するためのメソッド。

### カスタマイズ例

例えば、`Service`モデルがあり、各サービスには名前(`name`)と所要時間(`duration`)が設定されているとします。フォームでは、サービスの名前と所要時間を一緒に表示させたい場合があります。これを実現するには、`collection_check_boxes`メソッドにブロックを渡し、カスタマイズします。

```erb
<div class="field">
  <%= form.label :service_ids %>
  <%= form.collection_check_boxes :service_ids, @company.services, :id, :name do |b| %>
    <%= b.check_box %>
    <%= b.label do %>
      <%= "#{b.text} - #{b.object.duration} minutes" %>
    <% end %>
  <% end %>
</div>
```

このコードでは、`collection_check_boxes`にブロックを渡しています。ブロック変数`b`は、コレクションの現在の要素に対応する`CheckBoxBuilder`オブジェクトです。`b.object`を使用して現在の`Service`オブジェクトにアクセスし、その`duration`属性を取得しています。`b.text`は、`collection_check_boxes`の第4引数で指定された`name`メソッドの結果、つまりサービスの名前を返します。

### 補足説明

- `.object`メソッド: `collection_check_boxes`で現在処理しているオブジェクト（この例では`Service`インスタンス）にアクセスします。
- `.text`メソッド: `collection_check_boxes`の第4引数に指定した属性（この例では`:name`）の値を取得します。

この方法を使用することで、単にサービスの名前を表示するだけでなく、所要時間などの追加情報を含めることができます。これにより、フォームを使用するユーザーにとってより多くの情報を提供し、より良いユーザーエクスペリエンスを実現することが可能になります。
【ポケモン】旅パのタイプ相性チェックツールの作成＆公開

# はじめに
3年前にポケモンBDSPが発売されたタイミングでとあるツールを作成しました。
旅パで使うタイプを設定すると、足りていないポケモンのタイプを教えてくれるものです。

GitHubにあるので好きにご覧ください。

https://github.com/sugimochi97/type_comp_app/tree/master

# データの取得
まず、ポケモンのタイプ相性表を取得します。

データ数としては少ないので自分で作ってもよいのですが、当時の自分はスクレイピングして取得したようです。
長年お世話になってきた徹底攻略様よりお借りしています。

https://yakkun.com/data/aisyou.htm

実際のスクレイピングに使用したコードは以下です。

https://github.com/sugimochi97/type_comp_app/blob/master/scraping.py

# アプリとして実装

相性判定部分に関しては既にある相性表から読み取り、●がついているかどうかで判断しています。
関数で、効果抜群にできないタイプと不足タイプを検出し、それを返す形です。
途中で`set`を使っているのは被っている要素を排除するためですね（多分）。

```python
import streamlit as st
import pandas as pd

df_type_comp = pd.read_csv('type_comp.csv')
df_type_single = pd.read_csv('type_comp_single.csv')
type_dict = dict(zip(df_type_comp.columns, df_type_single.columns))

def check_comp(attack_type, defence_type):
    comp = df_type_comp[defence_type][attack_type]
    print('相性', comp)

def party_type_check(party_type_list):
    types = list(df_type_comp.columns)
    for pt in party_type_list:
        targets = list(df_type_comp.loc[df_type_comp.loc[pt]=='●'].index)
        for target in targets:
            if target in types:
                types.remove(target)
    lacks =  []
    for t in types:
        lacks.extend(df_type_comp[df_type_comp.loc[:, t] == '●'].index)
    lacks = list(set(lacks))
    for pt in party_type_list:
        if pt in lacks:
            lacks = lacks.remove(pt)
    print('効果抜群にできないタイプ→', types)
    print('不足タイプ→', lacks)
    return types, lacks

st.write('# パーティーに含まれるタイプを選択してください。')
select_types = st.multiselect('選択↓', df_type_comp.index)
types, lacks = party_type_check(select_types)
st.markdown("# 効果抜群にできないタイプ")
st.write(' / '.join(types))
st.markdown("# 不足しているタイプ")
st.write(' / '.join(lacks))
types = [type_dict[key] for key in types]
lacks = [type_dict[key] for key in lacks]
st.markdown("# 参考用タイプ相性表")
st.dataframe(df_type_single[types].loc[lacks])
```

# UI

マルチセレクトで簡単にタイプ登録をします。
そして、した二つのタイプ一覧が変化する形ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/33347094-10f2-a8f2-d249-d25661cf6b8f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/125cdadc-f540-9779-cbf9-a0c62f573d6c.png)

また、下に参考用タイプ相性表が出てきます。
これを基に追加するタイプなどを選んでいく流れになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/69569381-619a-c1ab-1035-393cf72e20ca.png)
カメラマップテクスチャを生成AIで補完してみる

:::note
エイプリルフールのお祭り騒ぎに乗っかったテストで
現状では業務には使用してない方式です
:::

アニメ等のテクスチャマッピングの方式に カメラの方向からテクスチャマッピングする
カメラマップやプロジェクションマッピングと言われる方式があります。

ラフな３Dモデルを作成してから作画をすることが多いため
レイアウトがきっちり定まって　下絵や詳細なモデリングの手間は省力化できる一方
カメラから遮蔽された部分に回り込むような動きには弱いです

今回は3D下絵で描いてみた　この絵から生成を試してみたいと思います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/a1d668da-4987-8df4-21d2-45da409385f3.png)
## 処理用画像の用意
カメラマップ画像をUVテクスチャにベイクすることで生成AI処理できる状態にするので
UV展開をします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/266f787e-e5eb-f67b-ef10-8796f71ee32c.png)
できるだけ　テクスチャ自体が面の正面像になるような展開をしています

次に描いた画像をカメラマップで投影してベイクします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/8250747e-39e9-fc6e-93cf-33a5657a2560.png)
この辺りは　他で解説している拙作の[カメラプロジェクションアドオン](https://qiita.com/yukimituki11/items/8d709bbaf2966bf7c38c)の操作で　今回の主題から外れるので割愛します
また[カメラに映る範囲・影になる部分を区別するシェーダー](https://qiita.com/yukimituki11/items/eb6b69bcc09b754aa16d)で作ったカメラからの遮蔽部分やAO画像もベイクしておきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/8e016ce8-94dd-99d8-ec4f-b15b57b5558f.png)
ベイクデータを処理して最終的にこんな感じの画像を作成しました
![24040106.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/c6c6acf7-2b6a-73b0-ca5f-39b48bd07645.png)
薄い色で表示されている部分は　アルファで半透明になっていて　生成AIでデータの作成を試行した部分です

## StableDiffusionでのインペイント
画像処理は Zip版Blender上でStableDiffusionを動かすDream Texturesアドオンを動かし
stable-diffusion-2-inpaintingのモデルを使用しています

![24040107.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/130a514a-253d-b1a4-78d3-b47a6e2d3401.png)
アルファを　Mask Sourceとして指定しています
Noise Stremgthを60-90等いくつかの設定を変動させて何枚か生成してみました

背景部分も同様にインペイントで背後部分をインペイントしました
![24040108.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/a74c4a0b-ef6e-76aa-2b16-0b87f8490d0d.png)
今回の成果はこんな感じです
![24040101.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/0ff6e1d4-568e-dbb8-88a1-8ebddea75bae.gif)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/e7e04045-1de9-cb40-79bb-a3b47e13cf66.png)
いくらか途中のミスもありますし　なんとかできた程度の品質ですが
一応は描いていなかった部分の生成はできました
一連の手順を自動化すれば　もしかしたら使い道があるかもしれないですね

とりあえず　今回の試作はここまでです。
オブジェクトの一つだけ抜き出したい　自分用メモ


オブジェクト配列の欲しい一つだけ抜き出したいメーン

ほいさ、こんな感じ

  ```js
  const hogeList = [
    {
      name: "saburo",
      number: "3",
    },
    {
      name: "ziro",
      number: "2",
    },
    {
      name: "taro",
      number: "1",
    },
  ]


  const newArray = hogeList.filter(value => {
    return value.name === "taro"
  })

  console.log(newArray)
  ```

しかも新しい配列として用意できる

もちのろんで変数も渡して比較できる
多分もっと色々できる（見てる感じいっぱい条件つけていろんなことしてる）

  なのでメモ投稿


  追記
  今回の大切な知識、実務で使いそうなこと
  ・オブジェクトのkeyを指定し、それに対して検索ができること
  ・検索結果は一つのレコード？まとまりで取れること
pandasのapplyよりもnumpyのwhereを使おう

# 目的

```csv:sample.csv
mean,std
-69.33333333333333,0
-61.785714285714285,4.516284468102667
-50.6875,2.4418230894149553
-61.5,0
-60.95,5.862234170833182
...
```

サンプルのような 2000 行の CSV ファイルを読みこみ、std が 0 の場合は 1 にする

# 実装方法

以上の処理を行う時、多くの方は以下のような処理を書くのではないでしょうか？

```python:main.py
import pandas as pd

sample_df = pd.read_csv("sample.csv")

sample_df["std"] = sample_df["std"].apply(lambda x: 1 if x == 0 else x)

```

以上の方法でも全然問題はないのですが、`numpy.where`を使うことでより高速に処理することができます

# numpy の where とは

numpy 配列において特定の条件を満たす要素に対して特定の値を返すメソッドです

pandas.apply は各行に対して一行づつ処理をかけているのですが、それと違って numpy.where はベクトル化された演算、つまり各行に並列して処理をかけます

そのため、pandas.apply よりも高速に処理を行えると言うわけです

```python
np.where(condition, x, y)
```

condition : 条件
x : true の時に返される値
y : false の時に返される値

# 実行速度の比較

```python:pandas.py
import time

import pandas as pd

star_time = time.time()

sample_df = pd.read_csv("sample.csv")

sample_df["std"] = sample_df["std"].apply(lambda x: 1 if x == 0 else x)

print(time.time() - star_time) # 0.0034990310668945312

```

```python:numpy.py
import time

import numpy as np
import pandas as pd

star_time = time.time()

sample_df = pd.read_csv("sample.csv")

sample_df["std"] = np.where(sample_df["std"] == 0, 1, sample_df["std"])

print(time.time() - star_time) # 0.0016324520111083984

```

実際に検証してみると pandas.apply よりも numpy.where の方が約三倍程度高速であるとわかります
Javaで文字列が一致しているか確認する時はequalsを使う

## はじめに
もうタイトルだけで言いたい事は言ってしまった感があります。
私は業務でほとんどJavaしか使ってこなかったので当然のことだと思っていましたが、他の言語を勉強していく内に以外と`equals`を使わないことが分かってきました。
Javaの子ども（だと勝手に思っている）**Kotlin**ですら`==`で比較できる。

::: note info
Kotlinでも`equals`は使えます。
:::
ということでこの件を浅く掘り下げます。

## Stringはプリミティブ型ではない
Stringは1文字目が大文字である事からもわかるように**クラス**となります。
`int`や`boolean`といったプリミティブ型ではありません。
ではなぜ以下のような宣言ができるのか。

```java
String text = "abc";
int num = 123;
```
これはStringだけの特殊な仕様により、コンパイラが自動的にStringオブジェクトを生成しているためです。
つまり、`String text = "abc";`の宣言は以下と _概念的には_ 同等になります。
```java
String text = new String("abc");
```
## 文字列の比較で`==`を使うとどうなるか
クラスは参照型なので`==`を使うと同じ参照を見ているかを返します。
しかし下記のコードを実行すると想定と少し異なる結果になります。
```java
String text1 = "abc";
String text2 = "abc";

System.out.println(text1 == text2); // true
System.out.println(text1.equals(text2)); // true
```
`==`で比較した方も`true`が返ってきました。
これは同じ文字列の値をもつStringオブジェクトが再利用される文字列インターンという特性のためです。
`text1`と`text2`は文言が同じため、Stringオブジェクトが再利用され同じ場所を参照します。
そのため`==`で比較しても`true`となるわけです。

ちなみに、Stringクラスのintern()というメソッドが文字列インターンと関連しているよです。
- [String (Java SE 21 & JDK 21)](https://docs.oracle.com/javase/jp/21/docs/api/java.base/java/lang/String.html#intern())

以下のように後から文字列の操作を行うと`==`では比較できなくなります。
Stringクラスは**不変**（イミュータブル）であるため、サンプルのように文字列の結合を行うと、新しいオブジェクトが生成されて、その内容が`text1`と`text2`に設定されるためです。
```java
String text1 = "abc";
String text2 = "abc";
text1 += "def";
text2 += "def";

System.out.println(text1 == text2); // false
System.out.println(text1.equals(text2)); // true
```
## まとめ
Java以外の言語を触った後にJavaを使うと、文字列が一致しているかで`==`を使ってしまう人がいるかもしません。
開発環境で正しい設定をしていればそのような場合に警告が表示されると思いますが、Javaで文字列を比較するときはequalsを使うという事を頭の片隅にでも覚えておいてください。
TwitterをWebページに埋め込む

1. Twitterのリンクを取る
アカウントのタイムラインが欲しい時は``https://twitter.com/アカウント名(@なし)``
2. https://publish.twitter.com 
3. 1でコピーしたリンクを下記の空欄に張り付ける．
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759397/5bbf4fca-4de1-4010-9b1b-fb29b7ff45b4.png)

4. TimeLineかButtomかなどの細かな設定を行う．
5. 生成されたcodeをコピーしてHTMLファイルに張り付けると完成．
Doma2を使ってみる(その2)

# Doma2を使ってみる(その2)

## セットアップ
### 環境
- 言語
  - Kotlin 1.9.22
- フレームワーク
  - SpringBoot 3.2.3
- buildツール
  - Gradle 8.5
- IDE
  - Intellij

### Intellij用プラグイン
#### [Doma Support](https://plugins.jetbrains.com/plugin/7615-doma-support)
IntelliJ上で、Domaを使った開発を少しだけ便利にすることができるプラグイン
- DAO関連で主にSQLファイルの作成と移動などが簡単になる
[README](https://github.com/siosio/DomaSupport/blob/master/README.md)

### Gradle
#### build.gradle.kts

```build.gradle.kts
plugins {
	// KotlinでSpring Boot開発を行うためのプラグイン
	// https://spring.io/guides/tutorials/spring-boot-kotlin/
	id("org.springframework.boot") version "3.2.3"
	id("io.spring.dependency-management") version "1.1.4"
	kotlin("jvm") version "1.9.22"
	kotlin("plugin.spring") version "1.9.22"

	// doma利用のためのプラグイン
	id("org.domaframework.doma.compile") version "2.0.0"
	kotlin("kapt") version "1.9.22"
}

repositories {
	mavenCentral()
}

dependencies {
	implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
	implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
	implementation("org.springframework.boot:spring-boot-starter-web")
	implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
	implementation("org.jetbrains.kotlin:kotlin-re[build.gradle.kts](..%2FDownloads%2Fdemo%203%2Fbuild.gradle.kts)flect")
	implementation("jakarta.validation:jakarta.validation-api")
	implementation("org.springframework.boot:spring-boot-starter-validation")
	testImplementation("org.springframework.boot:spring-boot-starter-test")
	runtimeOnly("com.h2database:h2")
	
	// doma
	implementation("org.seasar.doma.boot:doma-spring-boot-starter:1.7.0")
	implementation("org.seasar.doma:doma-kotlin:2.56.0")
	kapt("org.seasar.doma:doma-processor:2.56.0")
}
```
springbootとKotlinとDomaの条件で利用する場合、必要な設定が上記のようになります。
springbootでKotlinを使う場合に必要なものなどは、[こちら](https://spring.io/guides/tutorials/spring-boot-kotlin/)を参照するまたは、
Spring Initializrでプロジェクトを作成すると、必要な設定が自動で追加される。

##### ポイント1
[org.domaframework.doma.compileプラグイン](https://github.com/domaframework/doma-compile-plugin)を使うことで、Domaのコンパイル時の処理を行うことができる。
これによって、Domaの設定ファイルなどをアノテーションプロセッサが読み取ることができる。

##### ポイント2
DomaをKotlinで使用する場合はJavaとは設定が異なります。
- doma-kotlin
- doma-processor  

[README](https://github.com/domaframework/doma/blob/master/README.md)

##### ポイント3
[org.seasar.doma.boot:doma-spring-boot-starter](https://mvnrepository.com/artifact/org.seasar.doma.boot/doma-spring-boot-starter/1.7.0)
springbootとDomaを組み合わせるためのスターター

中身は以下
- spring-boot-starter-data-jdbc
- spring-boot-starter
- doma-spring-boot-autoconfigure
initializrで作成したプロジェクトだった場合、すでに依存関係に追加されているため、必要なのはdoma-spring-boot-autoconfigureだけ。
あと、doma-spring-boot-starterの最新バージョンが2024年4月現在、1.7.0でspringbootのバージョンが2.7.6なので古いものをみているので、これ単体で使うと古いバージョンになる。
[GitHub](https://github.com/domaframework/doma-spring-boot/tree/master)

機能は以下
- Domaの設定とSpring Bootの設定の統合：Spring Bootの設定ファイル（application.propertiesやapplication.yml）を使用してDomaの設定を行うことができます。
- DomaのDaoクラスの自動スキャン：Spring Bootのコンポーネントスキャン機能を利用して、DomaのDaoクラスを自動的に認識し、DIコンテナに登録します。
- トランザクション管理の統合：Springのトランザクション管理機能とDomaのトランザクション管理機能を統合し、一貫したトランザクション管理を行うことができます。
MapのnullチェックにはMapUtils.isEmpty()を使おう！

# はじめに
こんにちは！なっしーです！

前回に引き続き、Java（Apache、Spring環境）のtipsを紹介しようと思います！

前回はこちら↓

https://qiita.com/nashi-nashi/items/1d66e5d8dc5ffd8142a8

# 想定読者層
前回と同じく若手向けの記事です。
Javaでの業務ロジックや個人開発などでコードを書き始めた人を想定しています。

# 忙しい人向け結論
- MapのnullチェックにはMapUtilsのメソッド（isEmpty()）を使おう！
- MapUtilsはApache版とSpring版があるけど機能は一緒だよ！

# 本編
今回紹介するMapUtils.isEmpty()はApache版とSpring版がありますが、どちらも一緒の機能なので解説だけします！

皆さんはMap型のnullチェックはどう書いてますか？
私はこのメソッドを知るまで、Mapのnullチェックはこんな感じで書いてました。
```Java
Map<String, Object> hoge = new HashMap<>();

if (hoge == null || hoge.isEmpty()) {
    // hogeは空なのでtrue
}
```

上記をMapUtils.isEmpty()で書き換えるとこうなります↓
```Java
Map<String, Object> hoge = new HashMap<>();

if (MapUtils.isEmpty(hoge)) {
    // hogeは空なのでtrue
}
```

もしMapUtils.isEmpty()をstaticでimportしていた場合はもっと短くなりますね。
```Java
import static org.apache.commons.collections4.MapUtils.isEmpty;

// 中略

Map<String, Object> hoge = new HashMap<>();

if (isEmpty(hoge)) {
    // hogeは空なのでtrue
}
```

実はMapUtils.isEmpty()の実装を見にいくと、`hoge == null || hoge.isEmpty()`と同じことをしていることがわかります。
わざわざ毎回`hoge == null || hoge.isEmpty()`と書くより、先人たちが用意してくれたMapUtils.isEmpty()を使った方が楽で間違いもなさそうです。

# 逆にMapUtils.isNotEmpty()もある
MapUtilsにはMapUtils.isEmpty()だけでなく、MapUtils.is**Not**Empty()もあります。
こちらは値が入っていることを判定できます。便利ですね。

# MapUtilsには他にも便利なメソッドが！
MapUtilsにはisEmpty()、isNotEmpty()だけでなく、他にも便利なMap操作用のメソッドがたくさん存在します。
詳しくは公式ドキュメントをチェックしてみてください！

Apache版MapUtils

https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/MapUtils.html

Spring版MapUtils

https://docs.spring.io/spring-data/rest/docs/current/api/org/springframework/data/rest/core/util/MapUtils.html
poetryのpackage-mode=falseを設定して依存関係だけ管理する

## まえおき

[poetry](https://python-poetry.org)は元々パッケージのバージョン管理に便利な機能が多く、publishコマンドとかわかりやすいですね。

しかしプロジェクトの管理に使用するだけならこれらのメタデータは不要になり、publish等もできない方が良くなります。

## ver 1.8

バージョン1.8から`package-mode`という設定が追加され、パッケージの情報を抜きに依存関係を管理できるようになりました。

現時点では自動でパッケージの情報を削除できないので、設定ファイルを手動で変更する必要があります。

## 削除できる項目

**全てです！**

具体的には、`poetry init`コマンドで追加される`[tools.poetry]`は必要なくなります。


極端な例ですが、以下のようになります。

```toml: pyproject.toml
[tool.poetry]
package-mode = false

[tool.poetry.dependencies]
python = "^3.8"
cleo = ">=2.0.0"
```
参考：[poetry#8650](https://github.com/python-poetry/poetry/pull/8650)

## おわりに

とはいえ、必須でなくなっただけで、`name`や`version`は引き続き設定できます。

また、`poetry install --no-root`を設定せずとも環境に自身をインストールしなくなるという点もあるので、パッケージでない場合は設定すると良さそうです。

## 参考サイト

- [公式ドキュメント](https://python-poetry.org/docs/pyproject/#package-mode)
- [リリースノート](https://github.com/python-poetry/poetry/releases/tag/1.8.0)
macのPATHを更新しても、VSCode内のターミナルで更新したPATHが反映されない際の対処法

### 環境
VSCode v1.87.2
macOS Sonoma 14.3.1

## 問題の原因
.zshrcファイル内にPATHを追加していないのが原因。

## 解決方法
VSCodeのターミナル呼び出し時は、.zshrcに記述されているPATHを読み込むのでそのファイルも更新すれば良い。
ターミナルを開き下記コマンドを入力。
```
vim /.zshrc
```
そうすると.zshrcファイルが開くので、vimの操作方法に従って下記をファイル一番下に追記する。

```
export PATH="$PATH:(追加したいPATH)"
```

:wqで保存を忘れずに！
あとはVSCode再起動で完了！！
RHEL8でコンテナの自動起動を設定する


# はじめに
AWSのRHEL 8イメージでPodmanを使ったときに「VMを立ち上げたら一緒にコンテナが立ち上がる」を実現したかったのですが、少し調べる必要があったのでここに残しておきます。


# 環境
Red Hat Enterprise Linux 8.9
Podman 4.6.1

ユーザ名が`ec2-user`の場合の例です。

# コンテナの自動起動を設定する

任意のコンテナを起動します。ここでは`hello`という名前で起動しています。
```bash
$ podman run -it -d --name hello ubuntu bash
```

コンテナ名を指定して、ユニットファイルを`hello-container.service`という名前で作成しています。名前は任意です。このときコンテナのStatusはRunningでもStoppedでもOKです。
```bash
$ podman generate systemd --name hello > ~/.config/systemd/user/hello-container.service
```

ユーザのユニットファイルをsystemdに反映し、サービスに登録します。
```bash
$ systemctl --user daemon-reload
```

サービスを有効化し登録します。
```bash
$ systemctl --user enable hello-container.service
Created symlink /home/ec2-user/.config/systemd/user/default.target.wants/hello-container.service → /home/ec2-user/.config/systemd/user/hello-container.service.
```

サービス追加されたことを確認します。
```bash
$ systemctl --user list-dependencies
default.target
● hello-container.service
● └─basic.target
●   ├─paths.target
●   ├─sockets.target
●   │ └─dbus.socket
●   └─timers.target
●     └─grub-boot-success.timer
```

以上です。これで次回から起動時に指定のコンテナが起動します。


# ユーザのセッションが切れてもコンテナを起動したままにする

設定によってはユーザのセッションが切れたときにユーザプロセスが落ちるようになっていることがあります。
そんな時は以下のコマンド。

```bash
$ loginctl enable-linger $UID
```
Pythonでコマンドライン上の入力を受け取る方法(ド初心者用)

### 手順

##### モジュールインポート

https://docs.python.org/ja/3/library/sys.html

sysについてはこちらをご覧ください。

今回はsys.argvを使います。

sysを使うためにコードの最初に
import sysを記述しましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1243082/4dedd91c-f288-c894-f9b3-190d5adaf544.png)

### コマンド上でのファイル実行

コマンドライン上で引数を受け取る準備をしましょう。

以下をご覧ください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1243082/9ae057c4-764f-ba85-3521-136368107c17.png)

python3 sample.py input1 input2 input3

とあります。

最初のpython3 宣言は引数にカウントされません

つまり

python3 **[実行したいファイル名(引数1)]**　**[引数2]**　**[引数3]**　**[引数4]** ...

となっているわけですね。

## 引数を受け取る

引数を受け取るには

##### sys.argv[i]

で受け取ります

例としては

``` sample.py
import sys

print(sys.argv[0])
print(sys.argv[1])
print(sys.argv[2])
print(sys.argv[3])
```

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1243082/f1f9c208-f9a1-ab2e-2e22-f760a0f481f5.png)

## つまり、sys.argvを使えば、CLI上での入力をコード側に持ってこれます
(ファイル実行後に入力を受け取りたいときはinput()を使ってください)


#### 備考
pythonの環境構築がめんどくさいときはubuntuをダウンロードすると良いです


以上
GoogleスプレッドシートのQUERY関数を理解する

# これはなに？

GoogleスプレッドシートのQUERY関数（＝Google Visualization API のクエリ言語）をさくっと理解するための記事。
なお、本記事執筆時点（2024/04/01）でのバージョンは0.7のため、後述する「できないこと」は将来的にできるようになるかも。（ならないかも）

公式Docsは下記の通り。

https://support.google.com/docs/answer/3093343

https://developers.google.com/chart/interactive/docs/querylanguage

# 基本的な使い方

下記 `members` シートを用意する。

||A|B|C|
|---|---|---|---|
|1|name|age|memo|
|2|Alice|34||
|3|Bob|21||
|4|Charlie|12|Leader|

このシートに対し、下記関数を発行する。

```
// 関数
=QUERY('members'!A1:B, "SELECT A, B", 1)

// 出力結果
name, age
Alice, 34
Bob, 21
Charlie, 12
```

この実行内容の意味するところは下記の通り。

- 第１引数: `members` シートの`A1` セルから `B` 列の最終行までの範囲をデータソース（≒テーブル）とする
- 第２引数: A列（＝nameカラム）とB列（＝ageカラム）を `SELECT` する
- 第３引数: 1行目をヘッダー行とみなす

## できること

- `SELECT` クエリを発行できる
- `WHERE` や `GROUP BY` 、 `ORDER BY` など、集計時にあると嬉しいものはある程度揃っている
- データソースとして、任意のシートとセル範囲を指定できる

## できないこと
- `SELECT` クエリ以外の発行はできない
    - `INSERT` や `UPDATE` 、 `DELETE` などは使えない
- `SELECT` 時に列名を指定できない
    - AやBといった列名で指定する必要がある
- エイリアス `AS` が利用できない
    - `LABEL` 句で集計結果に出力される列名を編集できるが、クエリ内で使い回すことはできない

# Tips: データソースを2箇所指定する方法

`{'<1つ目のシート名>'!<セル範囲>; '<1つ目のシート名>'!<セル範囲>}` と指定してあげれば良い。

例えば、下記2つのシートをデータソースに指定し、年齢の平均値を集計したい場合。

`members_1` シート

||A|B|C|
|---|---|---|---|
|1|name|age|memo|
|2|Alice|34||
|3|Bob|21||
|4|Charlie|12|Leader|

`members_2` シート

||A|B|C|
|---|---|---|---|
|1|name|age|memo|
|2|太郎|57|お休み中|
|3|次郎|45||
|4|三郎|38|お食事中|

下記のように平均年齢を取得できる。

```
// 関数
=QUERY({'members_1'!A1:B; 'members_2'!A1:B}, "SELECT AVG(Col2) LABEL AVG(Col2) '平均年齢'", 1)

// 出力結果
平均年齢
34.5
```

注意点

- カラム指定方法について、2箇所以上のデータソースを指定した場合、 `A, B` といった形式ではなく `Col1, Col2` とする必要がある
    - 今回の例においては、 `SELECT AVG(B)` ではなく `SELECT AVG(Col2)` としている
- また、 `LABEL AVG(Col2) '平均年齢'` と記載することで、出力結果のカラム名を変更している
    - `LABEL` 句なしの場合、出力結果内のカラム名は `avg age` となる
【React】コードリーディングメモ1

```jsx
import React, { useEffect, useState } from "react";

export function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setCount((prevCount) => prevCount + 1);
    }, 1000);

    return () => {
      clearInterval(timer);
    };
  }, []); // 第二引数が空の配列

  return <div>{count}</div>;
}
```

index.jsx内などでAppが呼ばれたときに

まずuseStateが定義される、countの初期値0

useEffectの第二引数は空配列[]なので初回のレンダリング時にのみ実行される
```jsx
const timer = setInterval( () => {
setCount((prevCount) => prevCount + 1);
}, 1000);
```

定数timerの中に実行したsetIntervalのアドレスを格納する。
このときにtimerを定義してアドレスを格納させておくのはあとでsetIntervalを止める際にsetIntervalを直で実行してしまうと指定できなくなってしまうため。


setIntervalは非同期処理の関数のため、バックグラウンドで実行されるため処理自体は次にそのまま進んでいく。
```jsx
return () => {
      clearInterval(timer);
    };
```
useEffect内に記述されたreturnは最初のレンダリング時には実行されず、useEffectが記述されているコンポーネント、つまりこの場合だとApp()が画面から表示されなくなる（アンマウント）ときにアンマウントの直前にreturnのあとに記述した処理が走るようになっている。（これはもうuseEffectの仕組みだと思われる）

このときreturnで実行する処理は動かし続けているtimerを止めるという処理。ページ変わるしもういらないよねということだと思う。非同期処理なので明示的に止めたり消したりしないとずっと動き続けてしまう。

 ー 流れ ー
ルーティングの遷移などの命令がきてどうやら画面からコンポーネントが消えそう
↓
useEffectのreturnに記述した処理が実行される
↓
画面からコンポーネントが消える

みたいなことっぽい？

バックグラウンド処理のsetIntervalでは
１秒ごとにsetCountを実行してcountを+1し続けているので
1秒ごとにAppコンポーネントが最レンダリングされ続けているという状況。
Stripe txi_から始まる税率オブジェクトを作成する方法

## 概要

Stripeにて`txi_`から始まる税率を設定する方法を簡単にまとめる

## 方法

1. Stripeにブラウザからアクセスする。
1. 下記にアクセスする。
    1. [https://dashboard.stripe.com/test/tax-rates](https://dashboard.stripe.com/test/tax-rates)
1. 税率のタブから新規の税率を追加する。

## 参考文献

https://gist.github.com/fnky/76f533366f75cf75802c8052b577e2a5
【AWS IAM】「信頼関係を用いたマルチアカウントでSwitch Role制御の方法」

## はじめに
マルチアカウントでのAWSアカウントはどのように運用していますか？
以下イメージのようにJumpアカウントを設けて、IAM Userの一元化を行っているケースが多いと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635217/9fa171e3-299e-9664-945d-efac14790191.png)




この構成を取る際に、セキュリティを考慮し、IAM GroupがSwitch出来るRoleを絞るために、IAM GroupにアタッチするPolicyでSwitch先のRoleを絞っていると思います。
しかし、先日組織のセキュリティポリシー上このJumpアカウント側のPolicyをカスタマイズ出来ないケースに遭遇しました。
このポリシーに準拠したうえで、IAM GroupがSwitch出来るRoleを絞るために、IAM Role側の信頼関係を用いて制御しました。
本記事では、このIAM Role側の信頼関係用いたSwitch Role制御の実装方法に関してご紹介させて頂きます。

## 信頼関係を用いた制御
実装イメージとしては以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635217/bf2aaa0e-9d84-b7ad-5823-f78c8b77cb54.png)



ポイントとしては、以下2つです。
* ユーザに役割を示すタグをつける
※IAM Groupにはタグをつけることが出来ないため、IAM Userにタグをつけます。
そのタグをベースに信頼関係にてSwitchさせるかどうかの制御をしています。
* IAM Roleの信頼関係でユーザのタグにより、Roleの引き渡しを制御する

それぞれのポイントに分けて、紹介させて頂きます。

### ユーザにつけるタグ
ユーザには以下のようにタグをつけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635217/1d428f68-f8b7-ecc6-96a2-43b52382d99b.png)


グループ名をKeyとし、役割をValueに入れています。
上記の場合、infraGroupに所属し、開発(dev)、本番(prod)環境に対して、adminという役割を持つ形となります。
IAM Roleの信頼関係に関わってくるのですが、「：」を用いて役割所掌をつなげています。


### IAM Roleの信頼関係
IAM Roleの信頼関係は以下のようになります。
~~~relationship.json
     "Statement": [
      {
       "Action": "sts:AssumeRole",
       "Condition": {
        "StringLike": {
         "aws:PrincipalArn": "arn:aws:iam::jumpアカウント:user/*"
        },
        "ForAnyValue:StringLike": {
         "aws:PrincipalTag/infraGroup": [
          "*dev-admin*"
         ]
        }
       },
       "Effect": "Allow",
       "Principal": { "AWS": "arn:aws:iam::jumpアカウント:root" }
~~~
ここが本構成の最重要ポイントととなります。
IAM Userと関連する部分にフォーカスして紹介させて頂きます。

**"StringLike": {**
Condition句の一部となります。
JumpアカウントのIAM UserからのみこのRoleを引き受けることを許可しています。


**"ForAnyValue:StringLike": {**
Condition句の一部となりです。
IAM UserにinfraGroupタグが設定されており、そのタグ値に「dev-admin」が含まれる場合のみ、このRoleを引き受けることを許可しています。
"\*dev-admin\*"のように「\*」で囲んでいるのは、「prod」等他の環境に対しても権限を持つ場合IAM Userのタグにて「:」でつなげています。
例：「dev-admin:prod-admin」
そのため、前段や後段に「:」がある可能性があるため「\*]で囲っています。

[ForAnyValue:StringLike](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_condition-single-vs-multi-valued-context-keys.html#reference_policies_condition-multi-valued-context-keys)

[aws:PrincipalTag/tag-key](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-principaltag)

## まとめ
今回は、Jumpアカウントを用いたマルチアカウント環境下で、信頼関係を用いてSwitch Roleを制御する方法をご紹介させて頂きました。
素直に考えるとPolicyで制御しちゃえばいいんですが、このやり方の優位性は同じIAM Groupに所属させたうえで、Assume Role先を制御できるので、Groupから一段掘り下げて細かく制御することができる部分にあります。なので、無駄にGroupを乱立させなくてよいというメリットが出てきます。

Jumpアカウントを構成したマルチアカウント環境下で、Switch Roleのご利用をご検討の際は、ご紹介させて頂いた内容を参考にして頂けると幸いです。
※ 本ブログに記載した内容は個人の見解であり、所属する会社、組織とは全く関係ありません。
クリギング⓪：大まかな流れ

## はじめに
クリギングはGPRに似た空間解析手法です。Xでそれなりに関連ポストがある割にはQiitaでの関連記事が10件ほどしかなかったので、いくつかの章に分けてまとめていきたいと思います。

## クリギングとは
クリギングは、地球統計学の分野から進歩した空間解析手法です。鉱山技師のD.Krigeによる、ボーリングデータから鉱物の分布を推定する研究が起源です。推定にあたり共分散関数を用いることや、ベイズ的な手法であることから、しばしばGPR(ガウス課程回帰)と関連付けられることがあります。 MLPシリーズ：ガウス課程と機械学習(名著です。是非読んでみてください。)ではガウス過程の適用として紹介されています。しかし、GPRは数理分野で進歩してかなり有名になった回帰手法であり、クリギングとは別々に進歩していったため圧倒的にGPRの方が有名です。陽がしばらく当たらなかったクリギングですが、昨今のデータサイエンスの発展により、関連論文の数は徐々に増えつつあります。

## クリギングの大まかな流れ
### 等方性、異方性の確認
一次元方向なら良いのですが、二次元や三次元の空間を考えるとき、ある方向による観測値の寄与が、他の方向でも同じである場合は等方性、違う場合は異方性と言います。まだわかりづらいと思うので例を出します。例えば土の分布を考える時、緯度経度でベクトルを考えると、どの方向でも大して条件は変わらないので等方性ということができます。しかし、深さも考えると、ベクトルごとに分布の条件が変わってきます。これが異方性です。このように、目的変数に対して方向ごとの条件が等価であるかそうでないのかを最初に考える必要があります。
### バリオグラム雲、経験バリオグラムの作成
バリオグラム雲とは、各観測値ごとのユーグリッド距離を横軸に、半分散と呼ばれる指標を縦軸に置いたときの散布図です。この散布図から、経験バリオグラムと呼ばれる、各エリアの期待値をプロットした散布図を求めます。
### 理論バリオグラムの選定、共分散関数の設定
先ほどのプロセスで求まった経験バリオグラムから、理論バリオグラムと呼ばれる回帰モデルをいくつか用意して、ハイパーパラメータを求め、それぞれのMSEを求めます。MSEが最小となる理論バリオグラムから、共分散関数を求めることができます。
### クリギングの種類を設定
単純クリギング、普通クリギングや普遍クリギングなど、クリギングには様々な種類があります。目的変数の期待値がわかる時は単純クリギングを用います。普通クリギングは、期待値が空間によらず一定であることがわかるものの、期待値そのものはわからない時に用います。最後に普遍クリギングは、期待値と空間が簡単に回帰できるような関係の時に用いられます。明らかなトレンドがあるのに普通クリギングを行なってしまった場合、理論バリオグラムのハイパーパラメータが大きく変わってしまうので、観測データと空間をよく観察して決定することが重要です。

## さいごに
次回は共分散関数の設定までを記事にしていきたいと思います。

https://qiita.com/watlab/items/3032fddb812045894b87


参考文献
講談社、持橋大地ら、MLPシリーズ：ガウス課程と機械学習
コロナ社、阪田義隆、クリギング入門(こちらも名著です！)
参照渡しと値渡し

## はじめに
参照渡しの理解が曖昧だったため、値渡しと比較しながら整理する。


## 参照渡しと値渡しの違い

二つの違いの前に・・・

### そもそも変数とは

値の格納先に対して付けられた値札のようなもの

値を格納するのはメモリの役割。しかし、コードに意味のない番号を記述するのは見た目的にわかりにくいし、タイプミスの原因にもなる。
そこで、人間がわかりやすいように名前をつけるようにした。それが変数。

### 値による代入

値による代入とは、メモリ上の値を別のアドレスにコピーすること。
代入した変数と代入された変数は別物なため、元の変数が変更されても、代入された変数が影響を受けることはない。

```php:ref_val.php
<?php
$x = 1;
$y = $x;
$x = 5;
print $y  //1
```


### 参照による代入

参照による代入とは、メモリ上のアドレスそのものを引き渡す代入のこと。
元の変数と代入された側の変数が同じ値を見ていて、元の変数に対して加えた変更は代入された側の変数にも及ぶ。

```php:ref_val.php
<?php
$x = 1;
$y = &$x;
$x = 5;
print $y  //5
```
音声認識　Whisper.cppを使ってみた

***
今回は，音声認識 Whisperです．
通常のWhisperと違い，Whisper.cppはCPUで動くという話を耳にしました．
それは動かしてみるしかないでしょ！！
(***whisper.cppの導入にはLinux環境が必要***)

## Whisper.cppを動かす手順
### １．ビルドする

~~~
git clone https://github.com/ggerganov/whisper.cpp.git
cd whisper.cpp
make
~~~

makeを実行すると，様々なオプションが確認できる
- -otxt：テキストファイルとして出力
- -ovtt：vttファイルとして出力
- -m FNAME：使用モデルの選択
- -f FNAME：入力ファイル選択
- -l：言語の選択

などたくさんのオプションが存在する

### ２．使用するモデルをダウンロードする
 ~~~
./models/download-ggml-model.sh ”モデル名”
~~~

### ３．ffmpegのインストール
~~~
snap install ffmpeg
~~~

### ４．ffmpegにより16kHzのWAVファイルに変換する
~~~
ffmpeg -i ”変換したい音声の名前” -ar 16000 -ac 1 -c:a pcm_s16le ”変換後の音声の名”
~~~
Whisperはmp4など他のファイルにも対応していたが、Whisper.cppは16kHzのWAVファイルにのみ対応している

### ５．ダウンロードしたモデルを使用して，文字起こし
~~~
./main -m models/ggml-”使用モデル名” -f ”認識する音声” -l ja -otxt
~~~
モデルは　tiny < base < small < medium < large　の順で性能が良い

## 文字起こし結果
~~~
[00:00:00.000 --> 00:00:04.000]  これを持ちまして公園を終了させていただきます。
[00:00:04.000 --> 00:00:07.000]  どなたさまもお忘れもののございませんよ。
[00:00:07.000 --> 00:00:11.000]  今一度お手回り品を確かめください。
[00:00:11.000 --> 00:00:16.000]  本日はご来場いただきまして誠にありがとうございました。
~~~
モデルはsmallを使用してみましたが，まだ間違いが目立ちますね．
smallの代わりに**mediumやlargeを使用すると間違いは見られなくなりました**．

いやーそれにしても 発音が片言の Japanese English もしっかりと認識するのが whisper のすごさですよね！これからもお世話になります:raised_hands:
M1 Mac + WineでzLog令和版を実行する

## zLogとは

https://zlog.org/zlog_history.html

&emsp;zLogとは、アマチュア無線コンテスト用のロギングソフトです。上記リンク先にある通り、90年代に東京大学アマチュア無線クラブ（JA1ZLO/JA1YWX）の横林氏を中心としたプロジェクトによって開発されたもので、当初はPC9800やDOS/Vで動作し、その後Windows版がリリースされました。2000年代に開発が中断しますが、令和になってからJR8PPG 武藤氏によってコードの改良が行われ、Windows10で動作する「zLog令和版」が2020年にリリースされました。

https://use.zlog.org/

現在、最新版は上記公式ページのほか、Githubでも公開されています。

https://github.com/jr8ppg/zLog/releases

&emsp;Windows用のコンテストロギングソフトとしては他にもCTESTWINやN1MMなどがありますが、当然のことながらMacでは動作しません。

## 筆者について

&emsp;筆者（私）は現在、山形大学大学院理工学研究科博士後期課程に在籍中で、工学部無線研究会（JA7YAB）に所属しています。個人局（JP7VAI）として2019年の開局以来、色々なコンテストに参加してきましたが、昨年度新たに、YABの活動としてコンテストに参加するようになりました。個人でコンテストに参加する分にはロギングはどうにでもなります[^1]が、クラブで参加するとなるとそうはいきません。YABではzLogを使っていますが、PCの台数にも限りがあるため、できることなら自分のPCにzLogを導入し、担当分をロギングしたいと考えました。

[^1]:私はExcelを使っています

## 環境

* MacBook Pro (13-inch, M1, 2020)
* macOS Sonoma 14.4.1
* Homebrew 4.2.15
* Wine 8.0.1 (CrossOverFOSS 23.7.1)
* Winetricks stable 20240105

## 導入方法

&emsp;zLog令和版をM1 Macに導入する方法は、以下リンク先が大変参考になりました。

https://blog.masaru.org/2023/03/zlog-m1-mac-wine-crossover.html

リンク先を読んでいただければわかるのですが、Homebrew経由でWine CrossOver、Winetricksをインストールし、Winetricksを使って日本語フォントに対応させます。その後、DLしてZip解凍したzLog令和版をWineの実行ディレクトリ内に配置するだけです。以下コマンドで実行できます。

```terminal
$ wine64 c:\\zlog\\zlog.exe
```

## どうせならコマンド一発で起動したい

&emsp;毎回コマンド打つのが少し面倒でして（~~導入だけならこの記事いらないんです…~~）。というのも、Windowsでは.exeをダブルクリックするだけで起動できます。同じくらいの手軽さにしたいなと思った筆者は、エイリアスを設定することにしました。

```terminal:.zshrc
# .zshrcなどの設定ファイルに以下の行を追加
$ alias zlog="wine64 c:'\\'zlog'\\'zlog.exe"
```

※シェルファイル内ではバックスラッシュの取り扱いに注意しましょう（1敗）。

これで楽に起動できます。ターミナルを開いたら

```terminal
$ zlog
```

と入力するだけです。

## あとがき

&emsp;無事、自分のPCにzLog令和版を導入できたので、コンテストではフル活用していきたいと思います。
Linuxのブートプロセス：BIOSとUEFI

## BIOS
BIOS（Basic Input/Output System：基本入出力システム）とは、最も基本的な制御プログラムであり、基本入出力を管理します。<br>
コンピュータのファームウェアの一種で、コンピュータのマザーボードに組み込まれているソフトウェアです。<br>
BIOSの主な役割は、コンピュータが電源を入れた時、最初に実行される一連のチェックとプロセスを提供します。
### MBR
BIOSでは、起動デバイスの最初のセクタであるMBRでパーティションを管理します。
### MBRの構成
MBR（Master Boot Record：マスターブートレコード）はハードディスクの最初のセクタ（通常512バイト）に位置しており、以下の構成になっています：<br>
![截屏2024-04-01 21.29.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/941840/2d7853f1-5678-0a52-140f-349dce5ee31c.png)

#### ブートコード（Boot code）
446バイトを占め、オペレーティングシステムを起動するために必要なコードが含まれています。
#### パーティションテーブル（Partition table）
64バイトを占め、ハードディスク上のパーティション情報を記録しています。この領域には、各パーティションエントリが16バイトを使用し、合計4つのエントリで4つのプライマリパーティションに対応しています。
#### ブートシグネチャ（Boot signature）
最後の2バイトを占め、通常0x55AAの値が入っており、これは有効なブートセクタであることを示します。

## UEFI
UEFI（Unified Extensible Firmware Interface）は、コンピュータのファームウェアインターフェースの仕様で、従来のBIOS（Basic Input/Output System）のモダンな代替品として設計されています。<br>
UEFIは、システムの起動とハードウェアの初期化を管理するソフトウェアですが、BIOSよりも多くの機能と拡張性を提供します。


### GPT
GPT（GUID Partition Table）は、MBR（Master Boot Record）方式の分割表の制限を克服するために設計された新しいディスク分割技術です。<br>
GPTは、特に大容量のストレージデバイスに対応するため、UEFI（Unified Extensible Firmware Interface）と共に使われることが多いです。<br>
### GPTの構造

以下はGPT（GUIDパーティションテーブル）のレイアウト構成です：<br>

![截屏2024-04-01 21.44.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/941840/4db53ab2-315c-88fa-b675-99fe98a12a7e.png)

#### 保護MBR（Protective MBR）
最初のセクター（LBA 0）に位置しており、伝統的なMBRを認識するだけのシステムとの後方互換性を維持するためのものです。

#### GPTヘッダ（GPT Header）
2番目のセクター（LBA 1）に位置し、GPTパーティションテーブルを識別するための署名、バージョン情報、サイズ、パーティションテーブルの位置とサイズなどの情報が含まれています。

#### パーティションテーブル（Partition Table）
通常は3番目のセクター（LBA 2）から始まり、複数のパーティションエントリが含まれています。各エントリは通常128バイトで、初期の標準では128のパーティションエントリをサポートするように設計されています。

#### パーティションデータエリア（Partition Data Area）
各パーティションのファイルシステムデータが格納されています。

#### バックアップパーティションテーブル（Backup Partition Table）
ディスクの最後に位置し、パーティションテーブルの完全なバックアップです。

#### バックアップGPTヘッダ（Backup GPT Header）
通常ディスクの最後のセクターに位置し、GPTヘッダのコピーです。
【Transformer越え！？】猫でもわかるMamba解説

## イントロダクション

こんにちは！エンジニアのM.Y.です！！

Mambaについて、超分かりやすく解説させて頂きます！

本記事は「何となく理解する」を目的としており、正確でない表現や説明が含まれています。あくまでも参考情報としてご利用ください。

## Mambaが生まれた経緯

Mambaは2023年12月1日に発表されたネットワークアーキテクチャです。

ネットワークアーキテクチャはコンピューターが人間のように考えたり判断したりできるようにするための、プログラムのようなものです。

現在、ネットワークアーキテクチャで人気なモデルはTransformerで、グーグル翻訳・chatGPT・GitHub Copilot等、様々な場面で使用されています。
Transformerの凄さは皆さん実感しているかと思います。

そんなTransformerの最大の欠点は、計算コストが入力の長さの2乗に比例して増えることです。

例えば、入力文字数が1,000文字で100万回の計算が必要な場合、入力文字数が2,000文字だと計算量は約400万回と4倍に増えてしまいます。

つまり、入力が長くなるにつれ、計算コストが非常に高くなっていきます。

この問題は、長い文書の要約や生成など、計算の際に長い入力が必要タスクにおいて深刻な課題となっています。並列化や階層化といった方法で改善はされますが、根本的な解決にはなっていません。

そんなTransformer最大の欠点を解決するべく生まれたのがMambaです！

## Mambaの特徴

Mambaで最大の特徴は計算コストが入力の長さに比例することです！

Transformerと同じ例で例えると、
入力文字数が1,000文字で100万回の計算が必要な場合、入力の長さが2,000文字だと計算量は約200万回と2倍に抑えることができます。

これによって、長い入力が必要タスクの処理時間ではTransformerに勝っています。

しかし、いくら早くても、求める返答が返ってこなければ意味がないですよね。。。

Mambaは非常に長い文章やデータを処理する際、従来のTransformerより短い時間にもかかわらず、予測性能が優れていることが[論文](https://arxiv.org/pdf/2312.00752.pdf)で示されています。

Mambaが短い時間で高い予測性能を実現できる要因は、必要な部分だけに集中して計算を行う仕組みを採用しているためです。

具体的には、長い文章の中から重要な部分を選び出し、その部分だけを詳しく計算します。
一方、重要でない部分は簡単な計算で済ませています。

また、Mambaはコンピュータのハードウェア(CPU/GPU)に合わせて最適化されたアルゴリズムを使用しており、コンピューターの負荷も抑えて、予測させることが可能です。

## まとめ

Mambaは長い入力の処理に適しており、高速かつ効率的な推論が可能です。

まだ研究段階ですが、将来的に文書要約や動画のキャプション生成など、長文テキストを扱うAIシステムに広く活用されることが期待されています。

Mambaには計算効率や性能面での長所がある一方で、必要な部分を選択する仕組みなどが追加されているため、適切なハイパーパラメータ(学習を制御する設定値)を見けるのが大変といった課題も残されています。

今後の動向に注目ですね！
海外基板会社の比較をしてみた　PCBgogo & ELECROW

今回は、私がよく使う海外の基板会社を比較してみました。

## 料金
100mm☓100mm
の場合はどちらも安い金額で製作できます。
### PCBgogo
サービス期間中は、10枚5ドル
15件以上既に製作している場合は、10枚10ドル

送料は、16ドル
最安の運送業者OCSを使った場合（発送納期も速い）

よって
10ドル(基板費用)+16ドル(送料)+2ドル(クレジット手数料)=28ドル

### ELECROW
10枚1ドル
送料は、11ドル
最安の運送業者OCSを使った場合（発送納期も速い）
1ドル(基板費用)+11ドル(送料)=12ドル

#### 料金はELECROWが安い。

## サービス
### PCBgogo
・基板製作
・メタルマスク製作
・部品実装

### ELECROW
・基板製作
・メタルマスク製作
・部品実装
・3Dプリント

#### ELECROWでは3Dプリントも出来るので筐体作成もできる

## 納期
### PCBgogo
注文日：12/19
製作完了日：12/21
到着日：12/25
到着まで6日

### ELECROW
注文日：3/24
製作完了日：3/30
到着日：4/1
到着まで8日

#### PCBgogoが6日と速い

## 総評
金額的にはELECROWが安いのだが、急いで基板が欲しい時は、
PCBgogoで頼んだ方が良さそうだ。
【PHP入門】コメント・コメントアウトの使い方を解説する方法とコーディングのポイント

## **PHP入門：コメント・コメントアウトの使い方を解説**

PHPプログラミングを始めたばかりの方にとって、コメントの使い方は非常に重要です。この記事では、PHPでのコメントとコメントアウトの正しい使い方を解説します。また、コーディング時に注意すべきポイントも合わせて紹介します。

<a href="https://brain-market.com/u/sun_tomo_0218/a/bxITOykTMgoTZsNWa0JXY">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756609/690f2b5a-5b93-2f4b-a804-121789e5b646.jpeg">
</a>

## コメントの使い方
PHPでは、2種類のコメントがあります。**1行コメント**と**複数行コメント**です。

- 1行コメントは`「//」`を使う
- 複数行コメントは`「/* */」`で囲む

【例】

```php
// これは1行コメントです

/* 
これは
複数行コメントです
*/
```

コメントは、コード内に説明やメモを記述するために使用されます。コメントは実行時に無視され、コードの動作には影響しませんが、他の開発者や自分自身が後でコードを理解しやすくするために役立ちます。

## **コメントアウトの使い方**
コメントアウトは、一時的にコードを無効化するために使います。特にデバッグ時や一部のコードをテストしたい場合に便利です。

【例】
```php
// $name = "John"; // この行はコメントアウトされているため、実行されません
// echo "Hello, $name!";
echo "Hello, world!";
```

## まとめ
PHPでのコメントとコメントアウトは、コードの可読性を高めるために重要です。正しい使い方をマスターし、コーディング時に効果的に活用しましょう。

<a href="https://brain-market.com/u/sun_tomo_0218/a/bxITOykTMgoTZsNWa0JXY">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756609/f8758b9e-3879-8922-ecaf-a95f9227a116.jpeg">
</a>
初めてのチーム開発の感想

## 初めてチーム開発をした感想

初めてチーム開発を行ったので、その感想を書こうと思います。
皆様がチーム開発を行う際の参考になれば幸いです。

「自分たちの役に立つものを開発せよ」というお題でチーム開発をスタートさせました。チーム内で協議した結果「Tmatter(詰まったー)」というアプリを開発することが決まりました。このアプリは、学習記録をデータベースに保存することができ、検索によって素早く過去の学習履歴を取り出すことができます。
また、データベース上にある過去の学習履歴だけでなく、QiitaAPIを用いた情報取得も行い、始めて詰まった箇所でも対応できるアプリを目指しました。

### 担当箇所
自分が担当した個所は、検索画面の作成(HTML,CSS,JavaScript)とQiitaAPIを用いてQiita情報を取得しJavaScriptのDOM操作で表示させました。

検索画面では以下のような画面を作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715802/9e840dcc-677a-bc46-f140-61c7416f713e.png)

検索ボタンと検索結果の表示領域を配置しました。

### 開発で悩んだところは
HTMLのformだけでは必要な情報を詰め込んだGET送信ができなかった(#Rubyなどの選択されたタグが特に...)ため、JavaScriptのaxiosを使ってサーバーにGET送信を送りました。

そこで、CORSエラーというエラーが発生しました。このエラーはウェブブラウザーのセキュリティ制限の一種で異なるオリジン（異なるドメイン、プロトコル、ポート）からのリソースへのアクセスを制限する仕組みです。Rubyでローカルサーバーを立て、GET送信をしていたのですが、送信元と送信先のドメインが異なるためエラーになりました。

ドメインを合わせるためにVS Codeの「Live Server」を使用してGET送信しました。

### チーム開発を実感したところ
実は同じ開発メンバーが先ほどのCORSエラーに陥っており、情報を共有してもらうことで素早く解決できました。自分一人だけではドメインを合わせる方法を探すためにもっと時間を費やしていたと思いますし、開発を投げ出していたかもしれません。

※余談ですが、JavaScriptのaxiosでCORSエラーを回避できるみたいなので別途確認しておきます。

その他にも、
Dockerによる環境構築やGitHubでのコードの共有は個人開発では経験できないことがたくさんありました。例えば、GitHubでブランチを切って開発していたのですが、mainブランチとfeatureブランチの差が大きくなりすぎてしまい、コンフリクトが大量発生しました。
その際もチームメンバーのコードには目を通していなかったため、コードを見たときに目的をすぐに理解できなかったです。GitHubのプルリクエストを許可する段階でしかっりとメンバーのコードを確認して理解して、マージ許可をするべきでした。

### まとめ
チーム開発ではコミュニケーションがとても大切だなと実感しました。各メンバーが各担当の部分のコードを要件通りに作成し結合したら完成ではなく、詳細な部分までの認識合わせが重要なことを学びました。
　また、最終的に作成したアプリも実用までには足りない機能があることを知りました。
 ユーザが満足するアプリを作るためには、CSSで見た目を整えることに特化した人、バックエンドの処理が得意な人、プロジェクト全体をうまく管理する人。様々は人の個性をうまく掛け合わせることで達成できるのではないかと思いました。

 以上です、最後まで読んで頂きありがとうございました。
Google ColaboratoryからTiDB Serverlessに接続する

## はじめに

先日、みんなのPython勉強会でTiDB Serverlessの紹介をする機会がありました。
今までに100回を超えて実施している勉強会で発表させて頂いてありがとうございました！

https://speakerdeck.com/bohnen/minnanopythonmian-qiang-hui-zui-jin-nodbshi-qing-tidb-serverlessnoshao-jie

その中でGoogle ColaboratoryからTiDB Serverlessに接続するNotebookを作成したのですが、公開し忘れていたのでここで公開します。データの分析にはもちろんですが、SQLを勉強したり、バグの再現手順とか書くのにNotebook形式は便利だと思います。是非試してみてください。

Notebookはこちらです

https://gist.github.com/bohnen/847736758c74c62e4d59a9028ad6cc33

## ノートブックの解説

### 事前作業

* TiDB Serverlessクラスタを作成
* TiDB Cloudコンソールの右下の "?" マークから、`Interactive Tutorial` → `S&P 500 Analysis` を選択して、サンプルデータをロード(下図参照)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/36b9031b-d177-c163-261a-7c3dc756ce99.png)

### 必要なライブラリのインストール

他のpythonのmysqlライブラリでもいいと思うのですが、いつも使っているのは`pymysql`です。
NotebookのセルにSQLを書いて実行したいため、[`jupysql`](https://jupysql.ploomber.io/en/latest/quick-start.html#) をインストールしています。
また `jupysql` の初期化がなぜかf文字列ではできなかったので、接続オブジェクトを作成するために `sqlalchemy` もインストールしています。

```python
!pip install pymysql jupysql sqlalchemy --quiet
%load_ext sql
```

### TiDB Serverlessへの接続

Notebookを公開することも考えて、ユーザー名とパスワードはGoogle Colaboratoryのシークレットに保管します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/4e81b9a1-b7a1-7268-d99f-137628e97005.png)

シークレットはノートブックから `userdata` を使ってアクセスできます。

これで接続文字列を作り、`sqlalchemy`のengineオブジェクトを作成し、`%sql` に指定することで、`%sql`や`%%sql` が利用できます。

### セルでのSQLの利用

`%%sql` をセルの最初に書くことで、そのセルでSQLを書くことができます。Gistではシンタックスハイライトされていませんが、Google Colaboratoryではシンタックスハイライトされてキーワードや関数が分かりやすくなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/2012ad4c-85cb-d3f1-ee51-907018a2e9b9.png)

### 結果をpandas DataFrameとして取得

`%sql` を使うと、SELECTの結果をDataFrameとして取得できます。
ただ `%sql`は一行しか書けないので、長いSQLはあらかじめ `%%SQL --save [name]` を使って別名をつけておくと、CTEのように利用できるのでそれを利用しています。