OmniAICreator/Qiita-1.07M huggingface dataset:
Hexabase TypeScript SDKを使ったデモ（認証）

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

この記事ではv2系になって新しくなったHexabase TypeScript SDKのインストールと、認証（メールアドレスとパスワード）の方法を紹介します。

## デモ

以下はデモアプリです。ログインと、ログアウト処理を行っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/83839fbe-9f27-73c6-4d7e-84b7e23096a3.png)

https://stackblitz.com/edit/stackblitz-starters-vaquhb?file=pages%2Fhexabase.ts,.env,pages%2Findex.tsx

## インストール

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

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

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

## インポート

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

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

## 初期化

HexabaseClientを初期化します。

```tsx
// 本番閑居向け
const client = new HexabaseClient();

// 開発環境向け
const client = new HexabaseClient('dev');
```

なお、すでに認証済みだった場合に備えて、2番目の引数にトークンを指定できます。

```tsx
const client = new HexabaseClient('dev', 'YOUR_TOKEN');
```

### 認証

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

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

```tsx
const bol = await client.login({email, password, token});
```

レスポンスは認証成功すれば true 、失敗すれば false が返ってきます。

### ログアウト

ログアウトは `client.logout()` にて行います。

### ログインユーザーの情報

認証すると、 `client.currentUser` にてユーザー情報が取得できます。

```ts
const user = client.currentUser;
```

## 実装例

例としてReactを使った場合は以下のようになります。

```ts
// Input value
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
// Auth
const [status, setStatus] = useState(false);
const [auth, setAuth] = useState(false);
const [user, setUser] = useState<User>(null);
```

ログイン処理は以下のようになります。

```ts
// Login to Hexabase
const login = async (e) => {
	e.preventDefault();
	const bol = await client.login({ email, password });
	setUser(client.currentUser);
	setStatus(bol);
};
```

ログアウト処理です。

```ts
const logout = async (e) => {
	e.preventDefault();
	try {
		await client.logout();
	} catch (e) {
		console.log(e);
	}
    setUser(null);
    setStatus(false);
};
```

## まとめ

SDKを使うことで、Hexabaseの認証は簡単に利用できます。ぜひWebアプリケーション開発に活用してください。

Hexabaseには他にもデータストアやファイルストレージ、スクリプトなどの機能があります。それらの機能も利用してください。
Go言語向けNCMB SDKの使い方（配列の追加・削除操作）

NCMBはモバイル向けのBaaS（mobile Backend as a Service）ですが、サーバー側のデータとNCMB上のデータを連係させたいというニーズは良くあります。

そんなときには各言語向けのSDKがあると便利です。サーバー向けにはRuby、Python、PHP、Java、C#のSDKがあります（すべて公式サポート対象外の、コミュニティSDKという位置づけです）。

新しくGo言語向けのSDK開発をはじめたので、その使い方を紹介します。今回はデータストアの配列フィールドに対する要素追加・削除の処理について解説します。

## ソースコード

ソースコードはGitHubにて公開しています。ライセンスはMIT Licenseになります。

[NCMBMania/ncmb\_go](https://github.com/NCMBMania/ncmb_go)

## インストール

SDKのインストールは下記コマンドで行います。

```bash
go get -u github.com/NCMBMania/ncmb_go
```

## インポート

続けてSDKをインポートします。

```go
import (
    "github.com/NCMBMania/ncmb_go"
)
```

## 初期化

NCMBより取得したアプリケーションキー、クライアントキーを使って初期化します。

```go
ncmb := NCMB.Initialize("YOUR_APPLICATION_KEY", "YOUR_CLIENT_KEY")
```

### データの新規作成

`Item` メソッドで新規データのインスタンスを作ります。引数はクラス名です。

```go
item := ncmb.Item("Hello")
```

### データの適用

アイテムに対して、データをセットします。配列要素は、interfaceの配列として設定してください。 `[]int` などで行うと、追加時などにエラーが発生します。

```go
item.Set("msg1", "Hello").Set("msg2", "World")
item.Set("array", []interface{}{1, 3})
```

キーチェーンにも対応していますが、Go言語は改行が使えないので、多用すると見づらくなりそうです。

### データの保存

保存は `Save` メソッドで行います。保存がうまくいっていれば、 `bol = true` になります。

```go
bol, err := item.Save()
```

## 配列への要素追加

配列の要素追加は `Add` メソッドで行います。指定できるのは一度に一つの要素のみです。配列では設定できないので注意してください。

```go
item.Add("array", 2)
item.Add("array", 3)
item.Add("array", "string")
```

## 配列への要素をユニークで追加

配列をユニークで追加する際には `AddUnique` を使います。これは重複する要素は追加されません。

```go
item.AddUnique("array", "2")
item.AddUnique("array", "2") // 追加対象外
item.AddUnique("array", 3)
item.AddUnique("array", 3) // 追加対象外
```

## 配列の要素削除

配列に含まれる要素を削除する際には `Remove` を使います。これは存在する場合は削除されますが、ない場合には何も処理されません。

```go
item.Remove("array", "3") // なければ何も起きません
item.Remove("array", 2)
```

## 注意点

`Add` や `AddUnique` 、 `Remove` を使うと、そのフィールドの内容が単なる配列ではなくなります。これらのメソッドを使った後には、保存・再取得するまではフィールドの値を取得しない方が良いでしょう。

```go
item.Get("array")
// => [1, 2]
item.Add("array", 3)
item.Get("array")
// => {__op: "Add", objects: [1,2,3])
```

## まとめ

まだ基本的な機能しかありませんが、徐々にバージョンアップしていきます。

Go言語を使ってWebアプリケーションを開発している方は、そのデータ保存先としてNCMBを利用してみてください。

[mBaaSでサーバー開発不要！ \| ニフクラ mobile backend](https://mbaas.nifcloud.com/)
【メモ】SQL 2番目に大きい/小さい値を取得する

SQLを用いて「2番目に大きい値を取得しよ」との問題に一瞬戸惑ったので自分用にメモ。
（問題はLeetCodeより　https://leetcode.com/problems/second-highest-salary/description/?envType=study-plan-v2&envId=top-sql-50）

Q1. 下記のテーブルから2番目に高い給与（salary)を取得し、カラム名はSecondHighestSalaryとせよ。

+----+--------+
| id | salary |
+----+--------+
| 1  | 100    |
| 2  | 200    |
| 3  | 300    |
+----+--------+

2番目に大きい（もしくは小さい）値を取得するのにいくつか方法があったので記します。

* 方法1
```
SELECT MAX(salary) AS SecondHighestSalary
FROM Employee
WHERE salary < (SELECT MAX(SALARY) FROM Employee);
```
* 方法2
```
SELECT 
(SELECT DISTINCT Salary
FROM Employee order by salary desc
limit 1 offset 1)
AS SecondHighestSalary;
```
【積読】RESTのアーキテクチャスタイル前編


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

---

## クライアント・サーバ
Webは、HTTPというプロトコルでクライアントとサーバが通信するクライアント・サーバのアーキテクチャスタイルを採用している。クライアントはサーバにリクエストを送り、サーバはそれに対してレスポンスを返す。

#### 利点
* 処理を分離できる
* クライアントがマルチプラットフォームにできる
* 可用性の向上

クライアント・サーバの利点は、単一のコンピュータ上で全ての処理をするのではなく、クライアントとサーバで分離して処理できること。
これによりクライアントはマルチプラットフォームにすることができる。例えば現在のWebは、PCだけでなく携帯電話やゲーム機からもアクセスが可能。

また、ユーザインターフェースはクライアントが担当するため、サーバはデータストレージとしての機能だけを提供すればよくなる。さらに、複数のサーバを組み合わせて冗長化することで、可用性を上げられる。

## ステートレスサーバ
クライアント・サーバに最初に追加するアーキテクチャはステートレスサーバ。
ここでの**ステートレスとは、クライアントのアプリケーション状態をサーバで管理しないこと**を意味する。

#### 利点
サーバがアプリケーションの状態を持たないことの利点は、サーバ側の実装を簡略化できること。簡略な実装のサーバは、クライアントからのリクエストに応えたあとすぐにサーバの計算機リソースを解放できる。

* クライアント：リクエストごとに全ての情報を送信する
* ステートレスサーバ：クライアントのアプリケーション状態を管理しない

一方で現実にはステートレスではないWebサービスやWeb APIは多く存在する。HTTPをステートフルにする代表格がCookieを使ったセッション管理。

RESTの視点から見ると、Cookieを使ったセッション管理は間違ったHTTPの拡張になる。
（だからと言って、Cookieを使ったフォーム認証をやめるわけにはいかないので、Cookieはステートレスサーバの利点をあえて捨てることを理解した上で使用する。）

## キャッシュ
次のアーキテクチャスタイルがキャッシュ。**キャッシュとは、リソースの鮮度に基づいて、一度取得したリソースをクライアント側で使い回す方式のこと。**

#### 利点
サーバとクライアントの間の通信を減らすことで、ネットワーク帯域の利用や処理時間を縮小し、より効率的に処理できること。（古いキャッシュを利用してしまい、情報の信頼性を下げる可能性もある。）


後編に続く、、
---

参考文献

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

https://gihyo.jp/book/2010/978-4-7741-4204-3
Hyper-Vの仮想スイッチとVLANでドはまり

# はじめに

自宅PCのHyper-V上でネットワークのシミュレータ[eve-ng](https://www.eve-ng.net/)を動かしているのですが、VLAN周りでドはまりしたので、そのメモです。


# やりたかったこと

自宅PCの構成は↓の通り。

![Hyper-V_eve-ng.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580974/68553373-2c8e-9106-4bcb-3974d64913d8.png)



- 自宅PCとAT-x210-9GTはTrunk接続して、Intel PROSetの機能でVLAN接続。OS上ではVLAN11とVLAN251が別のネットワークアダプタとして認識。
- 自宅PC上のHyper-Vでeve-ngが動いている。eve-ngにはVLAN251のネットワークアダプタを割り当て。
- VLAN11とVLAN251間はRTX1200がルーティング。
- 自宅PCのホスト側のVLAN11のインタフェイスから、RTX1200を経由してeve-ngに乗り込みたい。


# 現象

## eve-ngからRTX1200への通信

eve-ngからRTX1200に対してpingを打つと通らない。
各ポイントでパケットキャプチャしてみるとARPの応答がvSwitchあたりで消えてます。

```
                   eve-ng 　     自宅PC       RTX1200
ARP(Broadcast)        -------------------------->
ARP(Response)               ×<-------------------
```

## RTX1200からeve-ngへの通信

RTX1200からeve-ngに対してpingを打っても通らない。
同じく各ポイントでパケットキャプチャしてみると、pingがvSwitchあたりで消えています。
※ARPは先の確認でARPテーブルに入ってました。

```
                   eve-ng 　     自宅PC       RTX1200
ping(Request)                 ×<-------------------
```

## Hyper-VのゲストOS同士の通信

eve-ngと同じvSwitchに接続する別の仮想OSを用意してみてゲストOS間で通信できるか確認してみたところ、問題なくpingが通ります。


## 物理機器同士の通信

RTX1200と同じVLAN251にノートPCを接続して通信できるか確認してみたところ、問題なくpingが通ります。


# 試行錯誤

## ググる
ググること丸一日ｗよくわかりませんでした。
だいたいよくあるのは、Hyper-Vの設定でMACスプーフィング機能をONにしなさいということ。
それは当然やってます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580974/5001e791-7876-e6ca-1cc1-b41c375175af.png)

## Hyper-Vの設定を色々調べる
設定をいろいろ変えまくってみたら、結論これでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580974/264f968c-8800-8a62-bbd5-7e440cefb4b5.png)

ゲストOSのネットワークアダプタの設定でVLANIDを指定する必要があったようです。

すでに、Intel PROSetの設定でホストOSレベルでVLANごとのネットワークアダプタが用意されてて、そのアダプタをHyper-Vの仮想スイッチに割り当てているので、あえてHyper-V上でVLANIDを指定する必要性は認識なかったのですが。。

ま、とりあえず解決したからよし。
JavaScript勉強備忘録

## JavaScript勉強備忘録
友達の開発の内容を理解するためjsの勉強を始めた。

### JavaScriptはどんなプログラミング言語か
・主にWebブラウザの中で動くプログラミング言語。
・WebブラウザだけでなくNode.jsというサーバー側のアプリを作る仕組みでも利用されている。
### プログラミング言語の中での位置付け
・スクリプト言語
・インタプリタ方式

### JavaScriptの歴史
1995年 JavaScriptはNetscape Communicationsのブレンダン・アイク(Brendan Eich)によってLiveScriptという名前で開発される。
1995年12月にJavaScriptとして、Netscape Navigator 2.0で実装された。
1996年にInternet Explorer 3.0登場 Netscape Communicationsはライセンスを付与せずにInternet Explorer 3.0には別のJScriptという言語が搭載
1997年 Internet ExplorerとNetscape Navigatorとの互換性のなさを解消するためにECMAScriptとして標準化
1998年〜1999年標準化を進めていった
2000年 標準化なかなか進まず、セキュリティ面などから評判が下がる。Flashに負ける
2005年　Google Mapなどで使われたAjax通信で見直されるように 
2006年 jQuery誕生
2008年 google chrome誕生　、node.js誕生
2015年 ECMAScript２０１５

### 見慣れず勉強したsyntax
関数式
```javascript
// 関数式
const 変数名 = function() {
    // 関数を呼び出したときの処理
    // ...
    return 関数の返り値;
};
```
Arrow Function
```javascript
// Arrow Functionを使った関数定義
const 変数名 = () => {
    // 関数を呼び出したときの処理
    // ...
    return 関数の返す値;
};
```
関数の仮引数が1つのときは()を省略できる
関数の処理が1つの式である場合に、ブロックとreturn文を省略できる
その式の評価結果をreturnの返り値とする
```javascript
// 仮引数の数と定義
const fnA = () => { /* 仮引数がないとき */ };
const fnB = (x) => { /* 仮引数が1つのみのとき */ };
const fnC = x => { /* 仮引数が1つのみのときは()を省略可能 */ };
const fnD = (x, y) => { /* 仮引数が複数のとき */ };
// 値の返し方
// 次の２つの定義は同じ意味となる
const mulA = x => { return x * x; }; // ブロックの中でreturn
const mulB = x => x * x;            // 1行のみの場合はreturnとブロックを省略できる
```

引用・参考文献
歴史
　https://zenn.dev/antez/books/568dd4d86562a1/viewer/bc8ac9
　https://rightcode.co.jp/blog/it-entertainment/javascript-history
　https://qiita.com/a_rcsin/items/0a3c8c98c8d703c49a22
　https://ja.wikipedia.org/wiki/JavaScript#%E6%AD%B4%E5%8F%B2
syntax
 https://jsprimer.net/
[1.20 Forge,Fabric対応]Minecraft1.20で日本語入力modを導入する

## ※この記事はMinecraftJava1.20のForge,Fabric(windows)を対象にしています。
検証はしていませんがmacOSでも同じようにできると思います。
　
### 1,概要
日本語入力modとして知られている[CocoaInputの1.20対応フォーク](https://github.com/nakanotti/CocoaInput/tree/master)をコンパイルしてみます。
### 2,ダウンロード
https://github.com/nakanotti/CocoaInput/tree/master
こちらのページからダウンロードできます。

ダウンロードしたら適当な場所で展開してください。
### 3,Forge
```~\CocoaInput-master\forge```に移動し、gradlew.batを実行します。
もしくは
```
./gradlew build
```
でも実行できます。少し時間がかかる場合がありますが気長に待ちましょう。
　実行するとコマンドプロンプトが立ち上がりコンパイルが始まります。
　コンパイルが終わると```~\CocoaInput-master\forge\build\libs```
にコンパイルされたmodが生成されます。これを他modと同じようにMinecraftのmodフォルダーに入れると使用できます。
### 4,Fabric
基本的にはForgeの場合と同じ方法でできます。


```~\CocoaInput-master\fabric```
に移動し、gradlew.bat実行します。
もしくは
```
./gradlew build
```
でも実行できます。少し時間がかかる場合がありますが気長に待ちましょう。
　実行するとコマンドプロンプトが立ち上がりコンパイルが始まります。
　コンパイルが終わると``~\CocoaInput-master\fabric\build\libs``にコンパイルされたmodが生成されます。2種類生成されますが```CocoaInput-1.20-fabric-4.0.9.jar```を他modと同じようにMinecraftのmodフォルダーに入れると使用できます。
### 5,コンパイルができない場合
　JDKのバージョンが古い場合コンパイルが失敗することがあります。その場合は新しいJDK(17以上を推奨)をインストールし環境変数に登録します。OracleJDKはこちらからダウンロードできます。
https://www.oracle.com/jp/java/technologies/downloads/
また、確認していませんがopenJDKでもできると思います。
【React】Identiconをデフォルトアバターに使用する

以下のライブラリを使用してIdentionを生成できます。

https://github.com/boringdesigners/boring-avatars

## インストール
以下のコマンドでインストールします。

```
npm install boring-avatars
```

## 使用方法

以下のように記述することで使用できます。

```
import Avatar from "boring-avatars";

<Avatar
  size={128}
  name="User Name"
  variant="marble"
  colors={["#92A1C6", "#146A7C", "#F0AB3D", "#C271B4", "#C20D90"]}
/>;

```

`name`の値によってIdentionが生成されます。

上記の場合には以下のようなアバターになります。

![Avatar for User Name](https://source.boringavatars.com/marble/128/User%20Name?colors=92A1C6,146A7C,F0AB3D,C271B4,C20D90)

また、`variant`には`marble`, `beam`, `pixel`,`sunset`, `ring`, `bauhaus`が使用できそれぞれ以下のようなアバターになります。

- `marble`
![Avatar for User Name（marble)](https://source.boringavatars.com/marble/128/User%20Name?colors=92A1C6,146A7C,F0AB3D,C271B4,C20D90)

- `beam`
![Avatar for User Name(beam)](https://source.boringavatars.com/beam/128/User%20Name?colors=92A1C6,146A7C,F0AB3D,C271B4,C20D90)

- `pixel`
![Avatar for User Name(pixel)](https://source.boringavatars.com/pixel/128/User%20Name?colors=92A1C6,146A7C,F0AB3D,C271B4,C20D90)

- `sunset`
![Avatar for User Name(sunset)](https://source.boringavatars.com/sunset/128/User%20Name?colors=92A1C6,146A7C,F0AB3D,C271B4,C20D90)

- `ring`
![Avatar for User Name(ring)](https://source.boringavatars.com/ring/128/User%20Name?colors=92A1C6,146A7C,F0AB3D,C271B4,C20D90)

- `bauhaus`
![Avatar for User Name(bauhaus)](https://source.boringavatars.com/bauhaus/128/User%20Name?colors=92A1C6,146A7C,F0AB3D,C271B4,C20D90)
Reduxと各種用語の定義

# Reduxと各種用語の定義

## 目次
1. [はじめに](#はじめに)
2. [Reduxの基本要素](#reduxの基本要素)
   - [Store](#store)
   - [Action](#action)
   - [Reducer](#reducer)
3. [Actionの定義とDispatch](#actionの定義とdispatch)
4. [ReducerとPure Function](#reducerとpure-function)
5. [Storeの構造と役割](#storeの構造と役割)
6. [Redux ToolkitとcreateSlice](#redux-toolkitとcreateslice)
7. [Reduxの設計思想](#reduxの設計思想)
8. [非同期処理とMiddleware](#非同期処理とmiddleware)
9. [Payloadとアクションオブジェクト](#payloadとアクションオブジェクト)
10. [まとめ](#まとめ)

## はじめに
Reduxは、JavaScriptアプリケーションでの状態管理を効率的かつ予測可能にするためのライブラリです。本記事ではReduxの主要概念や用語を具体的なコード例と共に詳細に解説します。

## Reduxの基本要素
### Store
Storeはアプリケーションの状態を保持するオブジェクトです。
```javascript
import { createStore } from 'redux';
const store = createStore(reducer);
```

### Action
Actionは、状態をどのように変更するかを定義するオブジェクトで、最低限`type`プロパティを持つ必要があります。
```javascript
const addAction = {
  type: 'ADD_TODO',
  payload: 'Learn Redux'
};
```

### Reducer
Reducerは、現在の状態とディスパッチされたアクションを受け取り、新しい状態を返します。
```javascript
function todoReducer(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [...state, action.payload];
    default:
      return state;
  }
}
```

## Actionの定義とDispatch
Actionはオブジェクトであり、`dispatch`メソッドを使用してStoreに送信されます。
```javascript
store.dispatch(addAction);
```

## ReducerとPure Function
Reducerは純粋関数であり、外部の状態を変更せず、同じ引数で呼び出された場合は常に同じ結果を返します。
```javascript
function reducer(state = initialState, action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [...state, action.payload];
    default:
      return state;
  }
}
```

## Storeの構造と役割
Storeは、アプリケーションの状態、Reducer、およびミドルウェアを保持し、`getState()`で状態にアクセス、`dispatch(action)`でアクションをディスパッチできます。

## Redux ToolkitとcreateSlice
`createSlice`はActionとReducerの作成を効率的に行うことができます。
```javascript
import { createSlice } from '@reduxjs/toolkit';

const todoSlice = createSlice({
  name: 'todos',
  initialState: [],
  reducers: {
    addTodo: (state, action) => {
      state.push(action.payload);
    }
  }
});

export const { addTodo } = todoSlice.actions;
export default todoSlice.reducer;
```

## Reduxの設計思想
Reduxは状態の予測可能性、一元管理、不変性を重視し、これによりデバッグやテストが容易になります。

## 非同期処理とMiddleware
MiddlewareはActionがReducerに到達する前に特定の処理を行うための仕組みです。非同期処理やAPIの呼び出しはMiddlewareを利用して行います。

## Payloadとアクションオブジェクト
Payloadはアクションオブジェクト内でデータを送信するための

プロパティです。
```javascript
const action = {
  type: 'ADD_TODO',
  payload: 'Learn Redux Toolkit'
};
```

## まとめ
Reduxは状態管理のための効果的なツールであり、適切な知識と理解を持つことで、開発の効率性とアプリケーションの品質を向上させることができます。本記事を通じて、Reduxの各要素とその役割、設計思想について理解を深められたことでしょう。
【Power Automate】Microsoft 365 groupsコネクタ「HTTP要求を送信します」：Teamsでチャネル・人にメンションする方法（Microsoft Graph）

# はじめに
最近やっとPower Automation中級者程度なら名乗れるか、と思い始めたくらいの知識です。
記述内容間違っているよ、もっといい方法あるよ、などあれば優しくコメントもらえると嬉しいです。

# 利用シーン
Power AutomateからTeams投稿する際、チャネル・人にそれぞれメンションしたいとき

1. 人のみにメンションしたいとき
    →　「Power Automate　Teams　メンション」と検索するとたくさん記事が出てきます。楽ちん実装
1. チーム・チャネルをメンションしたいとき
    →　プレミアムアクションであるMicrosoft 365 groupsコネクタ「HTTP要求を送信します」アクションを利用

**本記事ではMicrosoft 365 groupsコネクタ「HTTP要求を送信します」アクションを利用して人・チャネル両方にメンションする方法について扱います。**

# プレミアムアクションが必要なのか
色々と調べた結果、2023年9月現在、プレミアムアクションなしに実現することはできないと判断しました（あくまで私見）
以前は「HTTP要求を送信する」アクションを利用することでプレミアムアクションを利用せずにチャネルメンションできていたようです。

https://mofumofupower.hatenablog.com/entry/mention_teams_channel

しかし、23年9月現在、V2となっており色々試してみたもののエラー解消することができませんでした。
<img width="500" alt="screenshot_v2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449563/2acfdb17-a05a-cd4d-3928-934502ee6223.png">

ビクターさん「プレミアムコネクターが唯一の選択肢だぜ」

https://powerusers.microsoft.com/t5/Using-Connectors/Send-an-HTTP-Request-V2-URI-path-is-not-valid-but-works-in-Graph/td-p/2298244

リソース「Teams」が利用不可になったとの記述

https://speakerdeck.com/miyakemito/graph-api-noji-ben-topower-automatedenoli-yong-fang-fa-nituite

もともと抜け道のようなものだったのでV2で対策されたということなのかもしれません。

# 本題
コネクタの探し方、チャネルへのメンション方法は他記事に譲ります。「Power Automate　Teams　チャネル　メンション」で検索。
私が詰まったポイントは<b>「チャネルと人、どちらにもメンションしたいが探しても探してもHTTP要求で人にメンションする方法がわからない」</b>です。

## 初めに試したもの
まずはシンプルに\<at>タグを試しました。
しかし、エラーにはならないがUPNがそのまま表示されるだけでメンションにはなりませんでした。
失敗！
```html:content内の抜粋
<at>【ユーザUPN】</at>さん
```
## 最終的に辿り着いた先
チャネルと同様にmentionsに人も指定する必要がありました。チャネルと若干指定すべき項目が変わるので注意です。
解決！
```json:body部分
{
  "body": {
    "contentType": "html",
    "content": "
        <at id=\"1\">CHANNEL NAME</at><br/>
        <at id=\"0\">USER NAME</at>さん"
  },
  "mentions": [
    {
      "id": 0,
      "mentionText": "USER NAME",
      "mentioned": {
        "user": {
          "displayName": "USER NAME",
          "id": "【ユーザのID】",
          "userIdentityType": "aadUser"
        }
      }
    },
    {
      "id": 1,
      "mentionText": "CHANNEL NAME",
      "mentioned": {
        "conversation": {
          "displayName": "CHANNEL NAME",
          "id": "【チャネルのID】",
          "conversationIdentityType": "channel"
        }
      }
    }
  ]
}
```
# 参考

例 2: \@mentions チャネル メッセージ内のユーザー

https://learn.microsoft.com/ja-jp/graph/api/chatmessage-post?view=graph-rest-1.0&tabs=http

# 最後に
チャネルのメンション方法は検索したらいくらでも出てくるのですが、意外にも人にメンションする方法が全然見つからず沼りました。
チャネルメンションくらいプレミアム使わず実装させてほしい。プレミアム使ってもコーディングしないとダメなのもなんとも…
RNA-Seqデータ解析ツールで使用している技術を紹介します

この記事ではRNA-Seqデータ解析ツールで使用している技術について紹介します。RNA-Seqデータ解析ツールについては、[noteの記事](https://note.com/olvtools/n/n04a799061a21)を参考にしてください。実際の[RNA-Seqデータ解析ツールはこちら](https://olvtools.com/rnaseq/introduction)からアクセスできます。

# RNA-Seqデータ解析の技術
FASTQファイルはfastpを用いて前処理を行っています。前処理済みのデータをもとに遺伝子発現量の定量を行うところでは、通常のマッピング処理を行わないアルゴリズムであるSalmonを用いています。従来のマッピング処理 → リードカウントでは解析に時間がかかるため、Salmonを採用し高速な解析を実現しています。Salmonで得られる結果は転写産物ごとの発現量になりますので、それを遺伝子単位に変換するために tximportを使用しています。ここまでの処理で、FASTQファイルをインプットとして、遺伝子発現量テーブルであるCSVファイル得られます。

遺伝子発現量テーブルをもとに発現変動遺伝子を抽出する処理にはedgeRを用いています。edgeRでは内部でTMM補正という手法を用いてサンプル間のリードカウントの補正を行っています。得られた発現変動遺伝子群において、どのようなGene OntologyやPathwayが有意に多く観測されているかを確認する解析にはclusterProfilerを用いています。PathwayのデータベースとしてはWikiPathwaysを用いています。

- fastp
- Salmon
- tximport 
- edgeR
- colusterProfiler
- WikiPathways

# WEBの技術
フロントエンドの技術としてはTypeScript + Next.jsを用いています。RNA-Seqデータ解析ツール以外のWEBページと一体化しており、SEO対策が必要であったために、Next.jsでSSRを行うようにしています。バックエンドにはPythonのFastAPIを採用しています。バイオ分野でのライブラリがPythonで充実しているため、ちょっとしたバイオ分野のデータの操作を行ううえでPythonのフレームワークを採用しておくと便利であると考えたためです。ただ、現状ではあまりPythonである利点を活かせていないこともあり、別言語のフレームワークでも良かったと感じています。

- TypeScript
- Next.js
- Python
- FastAPI


# インフラの技術
フロントエンドにはVercel、バックエンドにはHerokuを採用しています。RNA-Seqデータ解析の処理は解析ごとに都度ECSを立ち上げています。認証にはAuth0を用いています。
Vercel、Herokuについては将来的にAWSに移行する必要が出てくるかもしれません。

- Vercel
- Heroku
- Auth0
- AWS
- ECS
【Markdown】数字や英語の前後にスペースが入らないようにする簡単な方法


# Introduction

Qiita CLIがリリースされ、従来のGUIからVSCodeでMarkdown形式で記事を書くようになりました。

https://qiita.com/kagami_t/items/0760712d29003841a1fd

しかしMarkdownで書くことで、VSCodeに入れていたPrettierという拡張機能が影響し、数字と英語の前後に半角スペースが入り込んでいました。

本記事ではUbuntu22.04環境で上記の事象を解決します。

**本記事が少しでも読者様の学びに繋がれば幸いです！**
**「いいね」をしていただけると今後の励みになるので、是非お願いします！**

## 環境

Ubuntu22.04

## 実施内容

まずは事象の確認を行います。

![Screenshot from 2023-09-22 22-31-37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3292052/451afcd0-885a-54cc-c93d-30ee07776d84.png)

> 2023 年 8 月
> 個人的には GUI でも

以前からMarkdownでメモを取っているので気にはなりましたが、Prettierのようなコードフォーマッターに余計な設定を入れたくはなかったため放置していました。
メモのような個人用途はまだしも、人様に読んで頂く上で見辛い記事を提供するわけにはいかないため、スペースを取り除く設定を加えました。

最初は以下の記事を参考に設定しましたが、適用されずスペースは残りました。
設定からPrettierのResolve Global ModulesをTrueにする方法です。

https://qiita.com/LifescrewDesign/items/4c5b8f076bdf59538f96

Win10ではResolve Global Modulesでフォーマットできない旨が書かれており、私の環境（Ubuntu22.04）でも同様に動作しませんでした。

別の方法で解決することにし、以下の記事を参考に設定しました。
対処法2であればUbuntu22.04環境でも適用できました。

https://qiita.com/kumapo0313/items/92d1597da5f3752f6584

記事の内容に沿ってPrettierのディレクトリを開きます。
Ubuntuでは以下に格納されています。

```bash
cd ~/.vscode/extensions/esbenp.prettier-vscode-10.1.0/node_modules/prettier/
```

記事が若干古いためprettierのバージョンなど異なりますので、必要に応じて`esbenp.prettier-vscode-10.1.0/`は`esbenp`辺りでタブ補完をするとスムーズです。

index.jsを修正していきます。
私のバージョンでは33413行目が該当箇所なため、vimで行を指定して開きます。

```bash
vim +33143 index.js
```

普通にvimで開いてから、`/function appendNode`で引っ掛けても良いです。

![Screenshot from 2023-09-22 23-00-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3292052/7679ff04-3c1e-ba3b-84e5-bdfa72f4145e.png)

修正前は`value: " "`となっているため、画像の通り`value: ""`としてスペースを消しましょう。

スペースが消せるか保存して確認します。

![Screenshot from 2023-09-22 23-06-40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3292052/1f599584-847b-59c6-9a35-354047d2de21.png)

無事消せました！

### 最後に

最後まで閲覧頂きありがとうございました。
OS問題やバージョン問題がありそうなので、特にUbuntu環境の方は参考にしてみてください！
Qiita CLIの登場もあり、QiitaユーザーでMarkdownを書く機会が増える方もいると思います。
スペースが気になっていた方は、是非本記事や紹介した他の方の記事を見ながらスペース消して快適な執筆生活を送りましょう！

本記事がお役に立てば幸いです！

### 参考URL

https://github.com/prettier/prettier/issues/5938

https://qiita.com/LifescrewDesign/items/4c5b8f076bdf59538f96

https://qiita.com/kumapo0313/items/92d1597da5f3752f6584
【route】GitHub CodespacesでLaravelを使うときの注意点【localhost:8000】

https://github.com/laravel/laravel

`Create codespace`押します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/6f55ee75-ac92-ddea-8d25-4c36c66131d2.png)


ターミナルで以下を実行します。
proxiesを有効にしないと、assetやroute周りがlocalhost:8000になります。

```bash
composer install
sed -i "s/proxies;/proxies = '*';/" app/Http/Middleware/TrustProxies.php
cp .env.example .env
php artisan key:generate
php artisan serve
```

`'*'`を`['127.0.0.1']`にすることも可能です。

### 参考

https://stackoverflow.com/questions/50194923/laravel-and-ngrok-url-domain-is-not-correct-for-routes-and-assets
XcodeのTextFieldでキーボードが表示されない！

今日はなんで起きるかわかりませんが、たまに起きるエラーについて記述します。
Xcode上でコードを記述し、さぁビルドして動作の確認だ！って時に、先ほどまで出ていた入力画面が急に出てこなくなりました。
でもよく見てみると、画面の下に閉じるボタン出ていました。
![スクリーンショット 2023-09-22 22.19.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553935/9ca5e796-8946-48a0-2a80-3f102adf6dc2.png)
なぜ上に上がってこない…？と思いましたが、これはiOSシミュレーターの設定が変わってないいたことが原因でした。（なぜ変わったかはわかりません。有識者の方教えてください）
解決方法としては、シミュレーターを開いた状態で左上の「I/O」を選択し、「Keyboard」を選択します。
その中で「Connect Hardware Keyboard」にチェックが入っていることを確認します。
![スクリーンショット 2023-09-22 22.25.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553935/0ee47368-1664-90e9-bdc8-e4117781d8b6.png)
これをクリックして、チェックを外します。
![スクリーンショット 2023-09-22 22.25.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553935/7cfef214-c050-af07-a34a-355f64f1e5a8.png)
これで無事にTextFieldでキーボードが表示されるようになりました。
「入力画面で何かを行なったままシミュレーターを閉じる」というこうなどをした際に起きている様な気もするので、今後起きた際には原因について調べてみます！
wxPythonのwxListBoxで全選択状態を解除する

軽く検索した限りでは見つからなかったのでメモ(目が節穴なだけかもしれない)。
ついでに全選択ボタンも記載。
ただこちらはもう少しシンプルな方法がないか調べたい。

```python
import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, ID, title):
        wx.Frame.__init__(self, parent, title=title, pos=(100, 100), size=(400, 400))
        self.__create_widget()
        self.__do_layout()
    def __create_widget(self):
        #リストボックス
        self.columnListbox = wx.ListBox(self, wx.ID_ANY, choices=("a","b", "c"), style=wx.LB_EXTENDED | wx.LB_NEEDED_SB)

        #全選択ボタン
        self.columnSelectAllButton = wx.Button(self, wx.ID_ANY, "全て選択")
        #全選択解除ボタン
        self.columnSelectNoneButton = wx.Button(self, wx.ID_ANY, "全て解除")

        #イベント設定
        self.columnSelectAllButton.Bind(wx.EVT_BUTTON, self.OnClickSelectColumnsAllOn)
        self.columnSelectNoneButton.Bind(wx.EVT_BUTTON, self.OnClickSelectColumnsAllOff)

    def __do_layout(self):
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        #リストボックス
        sizer.Add(self.columnListbox, flag=wx.EXPAND)

        #選択状態変更ボタンs
        sizer.Add(self.columnSelectAllButton, flag=wx.EXPAND)
        sizer.Add(self.columnSelectNoneButton, flag=wx.EXPAND)

        self.SetSizer(sizer)

    #### イベント ####

    #全て選択
    def OnClickSelectColumnsAllOn(self, event):
        for c in self.columnListbox.GetItems():
            self.columnListbox.SetStringSelection(c)
        return 0
    #全て選択解除
    def OnClickSelectColumnsAllOff(self, event):
        self.columnListbox.SetSelection(-1)
        return 0

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(parent=None, ID=-1, title="test")
        self.SetTopWindow(frame)
        frame.Show()
        return True

if __name__ == '__main__':
    app = MyApp()
    app.MainLoop()

```
ネットワークセキュリティ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/dfbbdc8d-43b4-222f-6751-9f5e7267025e.png)
１：VPN(Virtual Private Network)
専用線を使った通信では「通信内容の盗聴」や「通信相手のなりすまし」の被害に遭う心配はありません。しかし、運用コストが高くなります。運用コストが安い通信路として、インターネットがありますが、インターネットは公開網ですので通信路の途中で誰が通信内容を盗聴しているかわかりませんし、そもそも接続先が正規のサーバであるかどうかさえも疑わしいことがあります。そこで、コストの安いインターネット上に専用線と同レベルの安全性を持ったネットワークを構築して運用することを考えます。このように、大勢で利用しているネットワーク（インターネット）常に構築する、専用線と同レベルの安全性を持つ自分だけのネットワークをVPNと言います。インターネット上にVPNを構築すると「通信内容の盗聴」や「通信相手のなりすまし」を防ぐことができます。

　VPNでは、暗号技術を用いることによって専用線と同レベルの安全性を持った通信路を構築します。VPNを構築する方式として、２つよく用いられます。
①IPsecVPN：IPの拡張規格であるIPsecを用い、ネットワーク層で構築するVPNである。IPsecは、認証に利用するAH、暗号化や認証に利用するESP、鍵の取り決めを行うIKEの３つのプロトコルで構築されている。一般には、ESPとIKEを組み合わせて利用する。VPNルータを設置し、VPNルータでIPパケットの暗号化、複合を行う。

②SSL（TLSVPN）
　SSL（TLS）通信を利用する、トランスポート層で構築するVPNである。VPN装置やリバースプロキシサーバを設置し、これらの設置で、SSL（TLS）通信の暗号化、復号を行う。VPN装置やリバースプロキシサーバには、SSL（TLS）サーバ証明書を導入する。
RailsのRubyライブラリ自動読み込みについて | なぜrequireしなくても動くのか？

Railsでアプリを開発中、外部APIを叩く処理で[URIライブラリ](https://docs.ruby-lang.org/ja/latest/library/uri.html)を使用する場面がありました。

URIライブラリは[組み込みライブラリ](https://docs.ruby-lang.org/ja/3.1/library/_builtin.html)ではないので、コード内に`require 'uri'`が必ず必要だと思っていたのですが、require無しでも動いたため、その理由について調べたことをまとめます。


## Rubyライブラリの種類

本題に入る前にRubyライブラリの種類について簡単に。


#### ①組み込み標準ライブラリ
- Ruby本体に組み込まれている。
- require を書かなくても使うことができる。
- 例）Array, Hash, String, Integer

#### ②組み込みではない標準ライブラリ（この記事で扱います）
- Ruby本体に付属している。
- インストール不要でコード内でrequireして使う。
- 例）Date, Uri, Net/http, Base64

#### ③gem
- 有志の開発した外部ライブラリ。
- インストールが必要。
- 例）devise, rspec, rails-i18n

冒頭で挙げたURIライブラリは、**②組み込みではない標準ライブラリ**なので、requireが必要そうですが、、

## 結論：Railsが自動で読み込んでくれます
Railsには、クラスやモジュールを初めて参照した際、自動的に読み込んでくれる機能が備わっています。

たとえば、以下のように、`require 'uri'`無しで初めてURIクラスが登場したとします。
```ruby:GoogleApiConnectable.rb
module GoogleApiConnectable
  extend ActiveSupport::Concern

  def get_place_details(place_id)
  uri = URI.parse("https://maps.googleapis.com/maps/api/place/details/json")
```
このとき、自動でuri.rbの検索が走り、`$LOAD_PATH`というRubyの組み込み変数が検索されます。

この`$LOAD_PATH`には、「読み込み対象として検索するディレクトリのコレクション」が格納されています。

`$LOAD_PATH`の中身を`ruby -e 'puts $LOAD_PATH'`で確認すると、私の環境では以下のような結果になります。
```
/opt/homebrew/Cellar/rbenv/1.2.0/rbenv.d/exec/gem-rehash
/Users/yuko/.rbenv/versions/3.1.3/lib/ruby/site_ruby/3.1.0
/Users/yuko/.rbenv/versions/3.1.3/lib/ruby/site_ruby/3.1.0/arm64-darwin22
/Users/yuko/.rbenv/versions/3.1.3/lib/ruby/site_ruby
/Users/yuko/.rbenv/versions/3.1.3/lib/ruby/vendor_ruby/3.1.0
/Users/yuko/.rbenv/versions/3.1.3/lib/ruby/vendor_ruby/3.1.0/arm64-darwin22
/Users/yuko/.rbenv/versions/3.1.3/lib/ruby/vendor_ruby
/Users/yuko/.rbenv/versions/3.1.3/lib/ruby/3.1.0
/Users/yuko/.rbenv/versions/3.1.3/lib/ruby/3.1.0/arm64-darwin22
```

このうち、/Users/yuko/.rbenv/versions/3.1.3/lib/ruby/3.1.0の中にuri.rbが格納されていました。
このほか、date.rb, net/http.rb, base64.rbなども見つかります。

Railsはここからファイルを見つけて実行してくれていたんですね。

*自動読み込みはRailsの機能なので、素のRubyではrequireが必須です。

## おわりに
詳しい仕様については、Railsガイドの[定数の自動読み込みと再読み込み](https://railsguides.jp/autoloading_and_reloading_constants.html)にいろいろと書いてあります。（私はまだ断片的にしか理解できておりません。。）

普段何気なくフレームワークを使ってしまっていますが、こんな処理が走ってるんだ、とひとつ勉強にになりました。

## 参考
http://www.code-magagine.com/?p=6996

https://jumtech.hatenablog.jp/entry/2016/08/20/140720

https://system.blog.uuum.jp/entry/2016/08/10/110000

https://railsguides.jp/autoloading_and_reloading_constants.html
[C#] 関数を簡単に説明

<p> プログラミングを始めたはいいものの、「関数」という概念でつまずいてしまったひとは少なからずいるのではないでしょうか。関数についてわかりやすく解説します。</p>

<p>目次</p>

[そもそも関数とは](#そもそも関数とは)
[なぜ関数が必要なのか](#なぜ関数が必要なのか)
[書き方](#書き方)
# そもそも関数とは
<p>　端的に言えば関数とはいくつかの処理をひとまとめにしたもののことです。実は、これまで使ってきたConsole.WriteLine()なども関数のひとつなのです。このように、C#の機能として元々定義されているものもありますが、自分で定義することもできます。例えば次のコードを見てください。</p>

```C#:Samplefunction.cs
Examplefunction();

void Exampelefunction()
{
    //この中身が処理
    Console.Write("hello,");
    Console.Write("world");
}
```

```:結果
hello,world
```

<p>　このコードでは"hello,"と出力するという処理と"world"と出力する処理をまとめて関数"Examplefunction"と名付けています。そして、Examplefunctionを実行すると"hello,world"と出力されます。</p>

# なぜ関数が必要なのか
<p>　具体的なコードの書き方を説明する前にその意義について考えましょう。</p>

**--１．同じような処理を何度も記述せずに済む**
<p>　関数を使えば複数の処理を一行で記述することができます。そのため、繰り返し呼び出したいときには大きくコードの簡略化に役立ちます。同じような処理を何度も記述していては、コードが冗長になってしまいますし、何よりミスが起きやすくなります。</p>

**--２．修正が簡単**
<p>　１に関連して関数は処理を変更しなくてはならなくなったときや、処理にバグが発見されたときにも活躍します。もし、関数を使っていれば関数を使っていなければ見落としがないようにチェックしながら修正しなければなりません。</p>

**--３．コードを理解しやすくなる**
<p>　複数の処理を簡単にかけるのでひと目見ただけで何をしているのかがわかります。</p>

# 書き方
<p>　それでは実際に使ってみましょう。</p>

```C#:１次関数
int f(int x) //int型のxが引数
{
    return 5 * x + 3; // 与えられた引数xを代入して計算する
}

int num = f(3); // f(x)に3を引数として渡した
Console.Write(num);
```

```:実行結果
18
```

```:関数の定義方法
関数の戻り値の型 関数名(引数の型 引数の名前,引数の型 引数の名前...)
{
    //処理

    return 戻り値; // return文で戻り値を返す
}
```
<p>　この関数は、与えられた引数xを使って</p>

```math
f(x) = 5x+3
```
<p>の結果を返すものです。<br>以下に、用語の解説を示します。</p>

### 戻り値
<p>　関数は、実行した結果を指定された型(今回はint型)で返します。型にvoidと指定するとなんの返り値も返さない関数になります。</p>

### 引数
<p>　関数は実行時に指定された型の値を受け取って処理を実行することができます。今回の例では、int型のxを受け取っています。このとき、xのことを仮引数とf(3)の3を実引数と呼びます。引数はいくつでも設定でき、コンマで区切って書きます。定義の書き方は変数の定義とほぼ同じです。１つ目から順に第一引数、第二引数...といいます。</p>
<p>　また、引数は一つも指定しなくても構いません。ただし、その場合でも呼び出しや定義のカッコは省略できません。</p>

### 関数内の処理とreturn
<p>　関数の引数を表記し終わったら波括弧 {} を書きその中に処理を記入します。この波括弧で囲われた部分をブロックと言います。関数の他にも様々な場面でブロックは使います。</p>
<p>　関数の戻り値はreturn文で返します。returnするものには式だけでなく変数なども指定できます。ただし、指定された戻り値の方と違うものをreturnしようとするとエラーになります。
<br>　また、return文には関数を終わらせる役割があります。</p>

```C#:return文は関数を終わらせる
int add(int x,int y)
{
    Console.WriteLine("returnの前");
    return x + y;
    Console.WriteLine("returnの後"); // return文のあとなので実行されない
}
Console.WriteLine(add(1,3));
```

```:出力
returnの前
4
```

<p></p>
DockerでMySQL構築

## はじめに
掲題の通り、Dockerを使ってMySQLを構築してみました。

### ディレクトリ構成
```
      /mysql
           |
           |-docker-compose.yaml
           |-db
               |-conf.d
               |  |-my.cnf
               |-mysql_data
               |-mysql_init
               |  |-create.sql
```

### 設定ファイル

```yml:docker-compose.yml
version: '3.7'
services:
    db:
        image: mysql:5.7
        ports:
            - "3306:3306"
        volumes:
            # 起動時に実行するSQLを格納
            - ./db/mysql_init:/docker-entrypoint-initdb.d
            # マウントするディレクトリ
            - ./db/mysql_data:/var/lib/mysql
            # 設定ファイルを格納
            - ./db/conf.d:/etc/mysql/conf.d
        environment:
            MYSQL_ROOT_PASSWORD: root
            MYSQL_USER: test
            MYSQL_PASSWORD: test
        command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
```

```conf:my.conf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
explicit-defaults-for-timestamp=1
general-log=1
general-log-file=/var/log/mysql/mysqld.log

[client]
default-character-set=utf8mb4
```

```sql:create.sql
CREATE DATABASE sample;
use sample;

CREATE TABLE employee (
    id INT(11) AUTO_INCREMENT NOT NULL,
    name VARCHAR(64) NOT NULL,
    PRIMARY KEY (id)
);
```

### 起動方法
docker-compose.yamlが格納されているディレクトリ内で```docker-compose up -d```です。
コンテナが起動しているかは```docker-compose ps```で確認できます。
起動したら、docker-compose exec db bashで直接コンテナに入るか、
MySQL Workbench等のクライアントツールを使ってMySQLにログインしてください。
コマンドで入る場合は「mysql -u root -p」で入れます。（今回の設定だとIDもパスワードもrootです。）
【Next.js】備忘録：Warning: React version not specified in eslint-plugin-react settings. ~ 原因と解決法 ~

# はじめに

記事をご覧いただきありがとうございます。
私は個人開発でNext.jsを使用しています。Next.jsのプロジェクトにおいて npm run dev　を実行した際にエラーが発生したのでその原因と対処法について備忘録としてまとめたいと思います。

# 開発環境

* eslint-plugin-react 7.33.2
* VSCode 1.79.2
* React  18.2.0
* Next.js 13.4.19
* TypeScript 5.2.2
* ESLint 8.49.0
* Prettier 3.0.3


# 実際のエラー

はじめにでも記述しましたが npm run devをターミナル上で実行した際に以下のようなエラーが出力されました。

```Linux:ターミナル
Warning: React version not specified in eslint-plugin-react settings. 
See https://github.com/jsx-eslint/eslint-plugin-react#configuration .
```

このエラー文を日本語訳をすると以下のようになります。

> 訳
警告: React バージョンが eslint-plugin-react 設定で指定されていません。 
https://github.com/jsx-eslint/eslint-plugin-react#configuration を参照してください。


# 原因

今回はエラーメッセージ内にもあった公式のGitHubリンクを参考にしました。
原因としてはエラーメッセージのままですがeslint-plugin-reactを使用する際にはReactのVersion指定が必要であったとのことでした。

公式ドキュメント内にある原因部分の記述を和訳にし載せておきます。

> // React version. "detect" automatically picks the version you have installed.
                           // You can also use `16.0`, `16.3`, etc, if you want to override the detected value.
                           // It will default to "latest" and warn if missing, and to "detect" in the future

>和訳
Reactのバージョン。"detect "は自動的にインストールされているバージョンを選択します。検出された値を上書きしたい場合は、`16.0`や`16.3`などを使用することもできます。デフォルトは "latest "で、見つからない場合は警告が表示され、将来的には "detect "になります。



# 解決

公式のドキュメント通り.eslintrc.jsに下記の設定を入れることでエラーメッセージは出てこなくなります。

```JavaScript:.eslintrc.json
    settings: {
        react: {
            version: 'detect',
        },
    },
```

以上のコードだけでは具体的にどこに記述すれば良いのか分かりづらいので.eslintrc.jsonの全体の記述も載せておきます。参考にしてください。

```JavaScript:.eslintrc.json
module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:react/recommended',
  ],
  overrides: [
    {
      env: {
        node: true,
      },
      files: ['.eslintrc.{js,cjs}'],
      parserOptions: {
        sourceType: 'script',
      },
    },
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
  },
  plugins: ['@typescript-eslint', 'react'],
  rules: {},
+   settings: {
+    react: {
+     version: 'detect',
+    },
+  },
}

```


# 終わりに

やっぱり環境構築って難しい、



## 参考記事・URL
https://github.com/jsx-eslint/eslint-plugin-react

https://stackoverflow.com/questions/72780296/warning-react-version-not-specified-in-eslint-plugin-react-settings-while-run
Pythonで複数の画像ファイルにつけたIPTCのキーワードを集計する（IPTCInfo3を使用）

## はじめに

複数の画像ファイルに付けたキーワードの総数や、キーワードごとの使用回数を調べるという処理を、Pythonのpyexiv2で書きました。画像ファイルのIPTC情報からキーワードを抽出して、集計してみた記事です。

https://qiita.com/st10/items/5ae77fd5393365cce42a

PythonでIPTCを扱うモジュールには、pyexiv2の他にIPTCInfo3というモジュールもあります。

https://pypi.org/project/IPTCInfo3/

https://github.com/james-see/iptcinfo3

こちらのモジュールも試してみることにしました。

## 環境

* OS: Windows 11 Home 22H2
* Python: 64ビット版、3.11.4

## モジュールのインストール

```
pip install IPTCInfo3
```

## 複数の画像ファイルにおいて、キーワードごとの出現回数を集計する

pyexiv2で行ったように、基準となるディレクトリ配下のJPEGファイルをすべて読み込み、キーワードごとの出現回数を集計します。

IPTCInfo3を使ったときの注意点は、以下のとおりです。

* ファイルを読み込むたびに型のことで警告を返してくるので、ロガーのログレベルを操作して警告表示を抑制する
    * 必須ではないが、何百、何千件というファイルを読み込んだときには気になる。必要に応じて表示の抑制を行う
* IPTCInfo3は各要素をbytes型で返してくる。よって、適時変換を行いながら処理する

```python
# 複数の画像ファイルのキーワードを集計する
# 複数の画像ファイルに付けられたキーワードごとの個数を調べてみる

import datetime
import collections
from iptcinfo3 import IPTCInfo
from glob import glob
from tqdm import tqdm
from pprint import pprint
import logging

# IPTCInfo3では、ファイルを読み込むたびに以下の警告が表示される
#   WARNING: problems with charset recognition (b'\x1b')
# この警告を抑制するため、ロガーのログレベルを警告より高いエラーにしておく
iptcinfo_logger = logging.getLogger('iptcinfo')
iptcinfo_logger.setLevel(logging.ERROR)

# 基準となるディレクトリ
base_dir = 'baseDir'

# 基準となるディレクトリ配下にあるJPEGファイルを再帰的に読み込む
glob_dir = glob('%s/**/*.jpg' % base_dir, recursive=True)

all_keywords = []

for file_name in tqdm(glob_dir):
    try:
        img = IPTCInfo(file_name)

        # キーワードのリストを取得するが、各要素はbytes型
        keywords = img['keywords']
    except Exception as err:
        # IPTC情報が読めなかったファイル名とエラー内容を表示
        print(f'Error file name: {file_name}')
        print(f'Exception: {err}')
        continue

    # キーワードのリストの各要素をデコードして、改めてリストにする
    decode_keywords = [x.decode('utf-8') for x in keywords]

    # 全部のキーワードを収めるリストに、デコードしたリストを結合する
    all_keywords.extend(decode_keywords)

# collectionsのCounterクラスを用いて、キーワードの出現回数を集計する
coll = collections.Counter(all_keywords)

# 整形して表示する
pprint(coll)

# キーワードの出現回数の結果をファイルに出力する
# キーワード数が多いと画面では見切れてしまうので、必要に応じて
with open(f'aggregate_keywords_iptcinfo3_.txt', 'w', encoding='UTF-8') as f:
    pprint(coll, stream=f)
```

## 集計結果

pyexiv2と同じように集計できました（pyexiv2とは集計対象のディレクトリを変えています）。

```
Counter({'屋外': 1972,
         '日本': 1851,
         '風景': 1753,
         '晴れ': 1644,
         '青空': 1542,
         '空': 1513,
         '青色': 1353,
（中略）
         '冠水': 1,
         '走行注意': 1,
         '冠水警報': 1,
         'LED': 1,
         '警告灯': 1,
         '要注意': 1,
         '洪水': 1,
         '警戒': 1,
         '1棟': 1,
         '複数棟': 1,
         '積雲': 1,
         '1羽': 1,
         '農村': 1})
```
【SwiftUI】iOS16.4以降のsheetを完全に理解する

# はじめに

# 基本実装
本記事で扱うサンプルコードの全コードです。
今後はここから端折っていくので試す方はこちらのコードに追加してください。
```swift
import SwiftUI

struct Sample1View: View {
    @State private var isPresented = false
    var body: some View {
        Button {
            isPresented = true
        } label: {
            Text("表示")
        }
        .sheet(isPresented: $isPresented) {
            Sample2View()
        }
    }
}

struct Sample2View: View {
    @Environment(\.dismiss) private var dismiss
    var body: some View {
        Button {
            dismiss()
        } label: {
            Text("閉じる")
        }
    }
}

```

# 実装
### Sheetを閉じれなくする
```diff_swift
.sheet(isPresented: $isPresented) {
    Sample2View()
+       .interactiveDismissDisabled()
}
```

### Sheetの高さを指定する
```diff_swift
.sheet(isPresented: $isPresented) {
    Sample2View()
+       .presentationDetents([.medium])
}
```

### Sheetの丸角を編集する
```diff_swift
.sheet(isPresented: $isPresented) {
    Sample2View()
+       .presentationCornerRadius(100)
}
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/b3eb7ee1-8c82-7a9f-8de2-2971e9c13fb8.png" width="50%">

### Sheetの背景を編集する
```diff_swift
.sheet(isPresented: $isPresented) {
    Sample2View()
+       .presentationBackground(Material.ultraThinMaterial)
}
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/8e2113a7-5b95-cdf5-0049-89c64ad8dda5.png" width="50%">

### Sheetの上に灰色のバーを表示する
```diff_swift
.sheet(isPresented: $isPresented) {
    Sample2View()
+       .presentationDragIndicator(.visible)
}
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/fd745e54-8a05-3cb2-e8cb-6894da4f43b7.png" width="50%">

### Sheetの表示方法を固定する
標準では以下のようになっています
|端末|縦向き|横向き|
|-|-|-|
|iPhone|`.sheet`|`.fullScreenCover`|

これをカスタマイズできます
以下のようにすることでiPhoneが横画面の際でもSheetで表示されます

```diff_swift
.sheet(isPresented: $isPresented) {
    Sample2View()
        .presentationCompactAdaptation(.sheet)
}
```

縦画面と横画面を分けて指定することもできます。
以下のようにすると標準とは逆になります
```diff_swift
.sheet(isPresented: $isPresented) {
    Sample2View()
        .presentationCompactAdaptation(.sheet)
}
```

### Sheetをドラッグした時の挙動を設定
#### Sheetのリサイズを優先
```diff_swift
.sheet(isPresented: $isPresented) {
    Sample2View()
        .presentationDetents([.medium, .large])
+       .presentationContentInteraction(.resizes)
}
```
#### スクロールを優先
```diff_swift
.sheet(isPresented: $isPresented) {
    Sample2View()
        .presentationDetents([.medium, .large])
+       .presentationContentInteraction(.scrolls)
}
```

# おわり
iOS16とiOS16.4で色々追加されてめっちゃsheetが便利になりました。
Windows11でPyenvをインストールする

# はじめに

Windows11 でPythonの開発環境をセットアップしたので、その備忘録。

# pyenv-win

https://github.com/pyenv-win/pyenv-win

# pyenv インストール

Powershellを開く。（以降全てPowershell上でコマンドを実行する）

カレントディレクトリに`install-pyenv-win.ps1`がダウンロードされた後に、このスクリプトが実行される。

```powershell
Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/pyenv-win/pyenv-win/master/pyenv-win/install-pyenv-win.ps1" -OutFile "./install-pyenv-win.ps1"; &"./install-pyenv-win.ps1"
```

# pyenvのバージョン確認

```powershell
pyenv --version
```

:::note
失敗する場合は、一旦Powershellを起動しなおして再度実行する。
:::

# 指定のPythonインストール

```powershell
pyenv install 3.8.10
```

# 指定のPythonを適用
```powershell
pyenv global 3.8.10
```

# Pythonのバージョン確認

```powershell
python --version
```
バージョンが表示されたらOK。
```powershell
Python 3.8.10
```

# pipでモジュールのインストール

```powershell
pip install fastapi uvicorn aiofiles clickhouse_driver plotly pycryptodome
```

# pycryptodomeの読み込み確認

たまに、上手くモジュールを読み込めないことがあったので念のため実施。

```powershell
python -c "from Crypto.Cipher import AES"
```
何もエラーがでなければOK。


# 補足

Pyenvのパスはインストールスクリプトで登録されるが、万が一再登録したい場合は以下のコマンドで設定できる。

```powershell
[System.Environment]::SetEnvironmentVariable('PYENV',$env:USERPROFILE + "\.pyenv\pyenv-win\","User")
[System.Environment]::SetEnvironmentVariable('path', $HOME + "\.pyenv\pyenv-win\bin;" + $HOME + "\.pyenv\pyenv-win\shims;" + $env:Path,"User")
```
PowerAutomateでExcelの動的な行数を取得する


# はじめに
PowerAutomateを使って、Excelの行数を取得する方法になります

取得したいExcelにテーブルが作成されている前提ですので、
テーブルの作成がされていない場合は事前に作成をするか、
PowerAutomateの「テーブルの作成」アクション等で準備が必要です

# 全体の流れ
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284042/4c070c36-0d11-11ab-0b0f-ef626b2b7023.png">

1. トリガー　(`手動でフローをトリガーします`)
1. 取得したいテーブルを指定します　(`表内に存在する行を一覧表示`)
1. 行数の変数の初期化をします　(`変数を初期化する`)
1. Teamsチャットに出力　(`チャットまたはチャネルにメッセージを投稿する`)

1.のトリガーと4.のTeamsチャットへの出力はお好きなものに変更してください
# 環境
今回は例として以下のようなテーブルを使います
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284042/c15efd9e-425a-8fbf-a8f1-677aec2130b4.png">
# フロー作成
お好きなトリガー設定後のフローの作り方になります
### テーブルの指定
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284042/bd25ebe6-557a-1ecd-cfa9-a6dec834c401.png">

`表内に存在する行を一覧表示`アクションより行数を取得したいExcelのテーブルを指定します
### 行数の変数の初期化
`変数を初期化する`アクションより以下の設定をします

**名前**：``tableRows``
**種類**：``整数``
**値**：```length(body('表内に存在する行を一覧表示')?['value'])```
### 行数をチャットする
`チャットまたはチャネルにメッセージを投稿する`アクションよりお好きなチャットまたはチャネルを指定してください
今回の場合は以下のような設定をしております
**Message**：``変数 tableRows の値は：@{variables('tableRows')}``
### テスト結果
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284042/875b2e06-65fd-c78d-17ac-5980f17c5dba.png">

# 最後に
行数のみを取得したい人はほぼほぼいないと思いますが、
`表内に存在する行を一覧表示`アクションにおいて、フィルタークエリやスキップ数の設定をする際に、
動的なテーブルの行数の取得が必要なため作成しました
Unity URPでRendererFeatureのインスタンスを取得できるようにする改造

# 概要
UnityのURPでRendererにセットしたRendererFeatureのインスタンスを取得するには、無改造ではシングルトンとしてstaticメンバでクラスインスタンスを取得できるようにするぐらいしか手がありませんが、クラスインスタンスが1つで済むとは限りません。

以下のページの様にReflectionを利用してprivateメンバを引っぱりだせば可能ですが、この方法を生理的によしとしない人もいるでしょう。
https://qiita.com/makisin/items/5d66f1ea97f525f0c6d8

そこでURPを改造して **2つ簡単なクラスメソッドを追加** することで、Camera からRendererFeatureのインスタンスにたどり着くまでの方法を紹介します。

# (準備) URPをカスタムできる状態にする
* Unityが終了している状態にしてください
* ProjectFolder/Library/PackageCache から **com.unity.render-pipelines.universal@(バージョン番号)** のフォルダを、ProjectFolder/Packages にコピーします
* **このコピーした方を改造してください**
* 次にUnityでそのプロジェクトを起動するとPackageCacheの同フォルダは消えてしまうので、無改造の状態を残しておきたい場合は、プロジェクトフォルダ外にバックアップしておいてください
* 次にUnityでそのプロジェクトを起動してPackageManagerで見ると UniversalRP が [CUSTOM] に変わっているはずです

# (改造1) カメラに設定したRenderer番号をとってくる機能
* Runtime\UniversalAdditionalCameraData.cs
* SetRenderer の次辺りに追加すると良いでしょう
```
//=========================================================================================
        /// <summary>
        /// カメラにセットされたレンダラー番号を取得する 改造
        /// </summary>
        /// <returns> m_RendererIndex (カメラにセットされたレンダラー番号)</returns>
        public int GetRendererIndex()
        {
            return m_RendererIndex;
        }
//=========================================================================================
```

# (改造2) UniversalRenderPipelineAssetから指定したindexに従ってScriptableRendererDataを返す機能
* Runtime\Data\UniversalRenderPipelineAsset.cs 
* classの最後にでも追加しましょう
```
//=========================================================================================
        /// <summary>
        /// m_RendererDataListをindexで取得できるようにする 改造　
        /// </summary>
        /// <param name="index"></param>
        /// <returns>パイプラインにセットしたScriptableRenderer列のindex番目にあたるScriptableRendererData、indexがオーバーしているときはnullが返る</returns>
        public ScriptableRendererData GetScriptableRendererData(int index)
        {
            if (index < 0 || index >= m_RendererDataList.Length)
            {
                return null;
            }
            return m_RendererDataList[index];
        }
//=========================================================================================
```

# 使い方
* Camera _cameraとしてRendererFeatureを取り出したいRendererが設定されたカメラが引ける状態
 * int _myRendererFeatureIndex として取り出したいRendererFeatureの順番が入っている状態 (レンダラー設計者として何番目かはわかっているはず)

```
//カメラのURP拡張データを取り出す
UniversalAdditionalCameraData cameraData = _camera.GetUniversalAdditionalCameraData();
//改造メソッドでレンダラー番号を取り出す
int rendererIndex = cameraData.GetRendererIndex(); 
  
//プロジェクト設定からパイプラインアセットを取り出す
UniversalRenderPipelineAsset  _renderPipelineAsset = ((UniversalRenderPipelineAsset)GraphicsSettings.renderPipelineAsset);
//カメラから取り出したレンダラー番号から改造メソッドでScriptableRendererDataを取り出す
var scriptableRendererData = _renderPipelineAsset.GetScriptableRendererData(rendererIndex);
//そのレンダラー内のRendererFeature配列を取り出す
var rendererFeatures = scriptableRendererData.rendererFeatures;
//何番目がなんのRendererFeatureかというのはレンダラー設計者は知っているハズ
MyRendererFeature myRendererFeature = (MyRendererFeature)rendererFeatures[_myRendererFeatureIndex];
//インスタンスを取り出せたので制御しよう(仮想コード)
myRendererFeature.SetHoge(true);  //Hogeを有効にする
```
Node.jsでdotenvがいらなくなったっぽいので使ってみる


2023年9月頭にリリースされたNode.js v20.6.0に`built-in .env file support`という記載がありました。

まだフラグが必要ですが、`.env`ファイルをデフォで使えるようになる感じですね。

> https://nodejs.org/en/blog/release/v20.6.0

> 参考: [Using Environment Variables In Node.js 20.6.0](https://browsee.io/blog/using-environment-variables-in-node-js-20-6-0/)

## 従来はdotenvを利用していた

通常環境変数を.envファイルを扱うためにdotenvというライブラリを使うやり方が主流でした。

https://www.npmjs.com/package/dotenv

```bash
$ npm i dotenv
```

```js
require('dotenv').config()
console.log(process.env.HOGEHOGE); //.env内のHOGEHOEGEを取得
```

1行いれるだけだけどちょっと手間感はあった気がします。言われてみてばくらいのやつですが。

## 使ってみる

v20.6.0以降で使えます。

```.env
OBNIZ_ID=123456789
```

```main.js
console.log(process.env.OBNIZ_ID);  //.env内のOBNIZ_IDを取得
```

現状、実行時はフラグが必要です。そのうちフラグなしでもOKになるかも

```bash
$ node --env-file=.env main.js
```

## よもやま: Denoだとデフォで.env対応

Denoだとデフォだと.env対応してるので、Node.jsの方もこの流れ反映はありがたいですね。

https://docs.deno.com/runtime/manual/basics/env_variables