OmniAICreator/Qiita-1.07M huggingface dataset:
MUI v5 の環境構築

ルートディレクトリにて下記をインストール

## MUIとemotionのインストール

```jsx
npm install @mui/material @emotion/react @emotion/styled
```

### emotionとは？

> MUI v5内部で使用されているスタイリングソリューション。

## フォントインストール

デフォルトではRobotoFontが適用

```jsx
npm install @fontsource/roboto
```

## SVGアイコンインストール

```jsx
npm install @mui/icons-material
```

## コンポーネント内でインポートして利用

```jsx
import React from 'react'
import { Button } from '@mui/material'

function Button() {
  return (
    <div>
        <Button>Click Me!！！</Button>
    </div>
    
  )
}

export default Button
```
rex0220 計算式プラグイン テーブルソート TABLE_SORT関数版

[計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73)で、TABLE_SORT関数を使用したテーブルソート・フィルターを行います。

# 概要

TABLE_SORT 関数で、テーブルのソート・フィルターを行います。
テーブル内項目の値で自動的にソート・フィルター処理を行うと編集中の行位置が変わってしまうので、ボタンクリック時にソート・フィルター処理を行います。

テーブル内項目にルックアップ・添付ファイル項目がある場合は、レコード保存後イベントでソートします。
※編集画面表示中にプラグインでテーブル行位置を変えると、ルックアップ・添付ファイル項目に行位置のズレが生じます。

* TABLE_SORT 関数は、計算式プラグイン Ver.76 で追加されます


![2024-03-03_19h09_28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/17ee929d-c6de-457e-568f-c59e213b7e50.png)

# 操作例

ボタンクリックによるテーブルソート・フィルター操作

![2024-03-03_19h33_07.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/19074d66-b16a-5a6f-aed7-f6bb4cdf5a14.gif)

テーブル内項目にルックアップ・添付ファイル項目がある場合は、レコード保存後イベントでソートします。

![2024-03-03_19h37_15.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ef51cbd3-09a6-dc36-ec65-ceaed3b17d30.gif)

# アプリ設定

ボタンを表示するためのスペース項目を追加して、要素IDを設定します。

![2024-03-03_20h00_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ca7def47-2e91-6e26-355c-e83fe39997bf.png)

# 計算式プラグイン設定

テーブルの計算式に TABLE_SORT関数を指定する場合は、「循環参照を許可」をチェックします。

![2024-03-03_20h03_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/515c6505-eb22-08d3-84d2-f525972dfbfa.png)

テーブル内項目にルックアップ・添付ファイル項目がある場合は、レコード保存後イベントを「IF(EV_INFO("mode")="success"&&更新日時」で判定します。
※計算式に更新日時を指定すると、レコード保存後イベントが実行されます。

```.js
OPTION: 循環参照を許可

// header1:($HEADER1) HEADER
DIALOG(ARRAY("日付順にソート","日付順にソートします"),
  FSET(テーブル,
    TABLE_SORT(テーブル,
      TPSORT(日付)
    )
  )
)

// sp1:(sp1) SPACER
BUTTON("数値順にソート",
  FSET(テーブル,
    TABLE_SORT(テーブル,
      TPSORT(数値)
    )
  )
)

// sp2:(sp2) SPACER
BUTTON("数値の逆順にソート",
  FSET(テーブル,
    TABLE_SORT(テーブル,
      TPSORT(数値,0)
    )
  )
)

// sp3:(sp3) SPACER
DIALOG(
  ARRAY("数値未入力を削除","数値が未入力の行を削除します"),
  FSET(テーブル,
    TABLE_SORT(テーブル,
      TPFILTER(数値>0),
    )
  )
)

// テーブル.番号 NUMBER
ROWNO(テーブル)+1

// テーブル2 SUBTABLE (editable)
IF(EV_INFO("mode")="success"&&更新日時,
  TABLE_SORT(テーブル2,
    TPSORT(数値_0)
  )
)
```
JavaScript: base64 decode最適化もどき

色々な実装でbase64文字列の復号速度を検証していきます。特に難しい事はせず、どの組み込み関数やObjectを利用するかの違いが焦点となります。返り値はUint8Arrayとします。
```js
//復号関数群
let u8map=s=>{s=s.replace(/[^A-Za-z\d+/]/g,"");
	var a=62,b=0,c,d=s.length,A=new Uint8Array(123),B=new Uint8Array((d+2>>>2)*3-[0,0,2,1][d&3]);
	for(A[43]=a;A[--a>51?a-4:a>25?a+71:a+65]=a;);
	for(A[47]=63;a<d;B[b++]=c&255)c=A[s.charCodeAt(a++)]<<18|A[s.charCodeAt(a++)]<<12|A[s.charCodeAt(a++)]<<6|A[s.charCodeAt(a++)],B[b++]=c>>16,B[b++]=c>>8&255;
	return B
},hmap=s=>{s=s.replace(/[^A-Za-z\d+/]/g,"").split("");
	for(var a=62,b=0,c,d=s.length,A={"+":62,"/":63},B=new Uint8Array((d+2>>>2)*3-[0,0,2,1][d&3]);A[String.fromCharCode(--a>51?a-4:a>25?a+71:a+65)]=a;);
	for(;a<d;B[b++]=c&255)c=A[s[a++]]<<18|A[s[a++]]<<12|A[s[a++]]<<6|A[s[a++]],B[b++]=c>>16,B[b++]=c>>8&255;
	return B
},index=s=>{s=s.replace(/[^A-Za-z\d+/]/g,"");
	for(var a=62,b=0,c,d=s.length,A="+/",B=new Uint8Array((d+2>>>2)*3-[0,0,2,1][d&3]);a;)A=String.fromCharCode(--a>51?a-4:a>25?a+71:a+65)+A;
	for(s+="AA";a<d;B[b++]=c&255)c=A.indexOf(s[a++])<<18|A.indexOf(s[a++])<<12|A.indexOf(s[a++])<<6|A.indexOf(s[a++]),B[b++]=c>>16,B[b++]=c>>8&255;
	return B
},b2a=s=>{s=btoa(s);
	for(var a=s.length,B=new Uint8Array(a);a;)B[--a]=s.charCodeAt(a);
	return B
},
//復号対象
b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".repeat(1e4),
//検証用変数
round=100,f=a=>a.charCodeAt();
//実践
for(let fn of[u8map,hmap,index,b2a,a=>Uint8Array.from(btoa(a),f)]){
	let a=round,t=new Date;
	for(;a--;)fn(b64);
	console.log(new Date-t)
}
```

結果、最速を誇ったのが`b2a`だ(`btoa` + for loop)! さすが組み込み関数様だぜ!
それに続くのが`u8map`(`[A-Za-z0-9/+]`を`Uint8Array`で数値変換するC言語風の実装)。
栄光の3番手につけたのが`hmap`だ(昔ながらの連想配列を利用したもの)。
不名誉ある4番手は`index`(`indexOf`連発で遅いに決まっている)。
そして`Uint8Array.from`が断然ダントツぶっちぎり圧倒的桁違いにクソ遅い! しかし記述が簡単だから許してあげようぜ!(許さん)
ただし復号しようとするbase64文字列が極端に短い場合や長い場合は結果が変わってくるっぽい。長い程`u8map`が優勢になり、ある時点から最速になる(Google Chromeの場合)
## codegolf
encoder 162 bytes
```html
<input type=file oninput="with(new FileReader)readAsBinaryString(files[0]),onload=b=>a.href=top.URL.createObjectURL(new Blob([btoa(result)]))"><a download id=a>DL
```
decoder 158 bytes
```html
<input type=file oninput="files[0].text().then(b=>a.href=top.URL.createObjectURL(new Blob([Uint8Array.from(atob(b),b=>b.charCodeAt())])))"><a download id=a>DL
```
いずれもFile処理専用
LLMのできることとできないことを整理してみた

# はじめに
昨今話題のLLMですが、従来は不可能だった「人間との自然な対話」や「論理的思考」が可能になった一方で、実務で利用しようとすると、LLMが不得意なことに対して過剰な期待がされて失敗するプロジェクトも多く存在するように感じています。

私は、現在都内の受託分析系のIT企業で機械学習エンジニアとして働いており、ここ1年ぐらいはLLMを使った案件に携わることが多かったため、実際に業務でLLMを扱う立場から、LLMでできることとできないことを整理してみました。

:::note info
この記事は執筆時点でのLLMの限界について筆者の独断で記載しています。LLM周りは日々新しいモデルや技術が出てくるため、この記事の内容もすぐ時代遅れになる可能性があります。
:::

# できること
## 単純作業
端的にいうと、頭を使わなくてもできるような作業は、LLMの得意分野です。
例えば、Webサイトからコピペしてきたような形式が崩れた情報をjsonやcsvのような構造化された形式に変換することは非常に得意です。実際に、レシートや名刺の自動認識のように、OCRした情報を構造化された情報に変換する取り組みは進んでいるように思います。
他にも、与えられた文章に対して肯定的/否定的のような感情を付与するネガポジ分析や、各種ラベルへの分類も行うことができます。

## 単純な知識問題
LLMは学習データに含まれていた情報を知識として利用することができます。例えば「三平方の定理とは」や「ExcelのIF関数の使い方を教えて」といった質問に回答することができ、検索エンジンの一部を代替することが可能です。
なお、LLM単体ではハルシネーション（LLMが虚偽の情報を生成してしまう現象）の問題もありますが、Web検索やRAGを組み合わせることで正確な情報をもとに回答を生成させることも可能になっています。

## 人間の補助
後述しますが、LLMは100%正しい答えを返すことが難しいです。しかし、LLMの結果を人間の補助として利用することで、正しければ採用し、正しくなければ不採用にする（もしくは正しくなくてもそれを参考にすることで人間の思考を補助する）という使い方が可能です。

この代表的な例が、GitHub Copilotに代表されるcopilotツールです。GitHub CopilotはAIを使ってプログラミングのコードの続きを予測してくれるサービスであり、生成した続きのコードは必ず利用されるわけではなく、人間が採用・不採用を判定する仕組みになっています。
現在のLLMの性能の限界として、必ず正しいコードを生成することは不可能という点が挙げられますが、LLMの性能が不足している部分を人間が介入して補完することで価値のあるサービスを実現できています。

# できないこと
## ドメイン知識が必要
ドメイン知識と呼ばれる、特定の専門分野や業務についての知識が必要なタスクについてはLLMは苦手です。
例えば、メールを生成するというタスクを考えた際に、時候の挨拶や敬語表現の生成は可能ですが、日立用語（人の名前を丸括弧で表記する、返答を承るという意味で「拝復」を使うなど。現在も存在しているかは不明）のような社内独自の特別ルールに対応することはできません。
筆者が経験した案件でもこのような暗黙知に苦労するケースが多いです。イメージとしては、転職してきた1日目の社員ができないタスクはLLMもできないと思ってください。

なお、RAGとして企業独自のドキュメントをプロンプトに埋め込むことで、ドメインの知識自体は利用することが可能ですが、ドキュメントの質がかなり大事になる点と、ドキュメントをもとに何らかの判断する過程で暗黙の知識を必要としているケースも存在するため、実現可否は慎重に判断する必要があります。
また、Fine-Tuning（特に現実的な手法であるLoRAの場合）によるドメイン知識の獲得は現時点では難しいという認識です。

## 特定のツールとの連携
LLMの入出力は基本的にはプレーンテキストです。PowerPointのような特定の形式を自動作成してほしいという要望をよく聞きますが、対応することができません。
なお、PowerPointの場合は、Microsoft CopilotというPowerPointを生成するためのツールが存在するため、そちらの利用を推奨しています。

## 100%を求める
LLMは一般のプログラミングのアルゴリズムとは異なり、必ず意図に沿った結果を生成するわけではありません。そのため、高い確度を求められるタスクには不向きであり、必ず〇〇できるシステムを作ってほしいというような場合にはLLMは不適当です。
なお、成功失敗の判定が可能なタスク（例えばプログラミングのコードを生成するタスクを行う場合）であれば、実行できるコードが生成されるまでリトライ処理をするなど、失敗した場合の対策が可能です。

# 総論
LLMはこれまでのAIと比較して、格段にできることが増えたという意味では技術的革新なのは間違いないですし、お遊びツールとしてできる範囲はかなり広いですが、実務に導入することを考えると、かなり使い所を選ぶという感覚です。

（個人的には、LLMは専門家によるモデルの学習を不要にしたという点で、機械学習の民主化に絶大な貢献をしたと考えているので、大金をかけて外部ベンダーに委託してすごいものを作ってもらうというよりも、各社員が自分自身の業務の自動化からスモールスタートで始めて行くことが望ましい導入方法なのかなと思っています。）
Cognito API ハンズオン やってみた 202403

# はじめに
以下のハンズオンをやってみました。
[COGNITO API ハンズオン](https://dcj71ciaiav4i.cloudfront.net/591796E0-D127-11EB-A6A5-FB83B2BAF6EE/)
2024年3月現在、UIの変更に伴い手順が異なる箇所あるため、備忘録として残すことに。
今回、 Postman を使って Cognito ユーザプールの API 呼び出しを行います。
諸々の事前準備は完了している前提です。
# 手順 Cognito
以下、手が止まりそうな箇所のメモ。他はハンズオン手順にのっとってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113363/18622e5c-b7de-a7d8-5f02-ef857866d00c.png)

デフォルトの認証UIで良い場合は下記を選択した状態に。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113363/765e2191-0530-13af-1ba8-c54ab0f25be7.png)
※デフォルトの認証UI　↓　こんなやつ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113363/a18e0e21-003c-bb35-5fc3-c77622402e76.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113363/5481d467-5659-a636-f8fb-04e261216cd5.png)

流れでPublicクライアントを作成することになる。Publicクライアントの場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113363/3955fabf-7960-55c7-a8b1-27d36b91bafc.png)

認証フローを選択よりALLOW_USER_PASSWORD_AUTH に変更。一般的なIDとパスワードを入れる認証システムにしたい場合、必要になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113363/e1351bf7-d128-9aa0-567b-7e6ed730dcd1.png)

ユーザープールが作成された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113363/37815848-d1c0-4862-90f5-4a6027e23069.png)

ユーザープール選択 ⇒「アプリケーションの統合」⇒「アプリケーションの作成」
ConfidentialClientを作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113363/fce74105-4795-3d32-1adf-f4fcac0f00cf.png)

認証フロー　けす
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113363/bb84d1b9-eea0-7374-f215-b4b107b1ff60.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113363/f3ec8286-83d5-ab3f-1184-92020910030d.png)

ふえた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113363/d5c1c3cb-66cf-ddfd-1aab-287df48793bb.png)

これでよし。

# 手順 API Gateway
CORS 対応はここからよしなに
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113363/b3a8dde8-b6a8-deab-3014-a6ac8383f243.png)

# 3. COGNITO IDENTITY PROVIDER API
ここはPostmanの場合、だいたいハンズオンとUI一緒
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113363/edec19e1-f97f-93ea-fccc-374886998374.png)

# 4. AUTH API の AUTHORIZATION CODE GRANT の呼び出し
だいたいハンズオンとUI一緒。認可コードの発行からスタート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113363/d7f92329-2524-7928-bcae-2d580ce7aac5.png)

終わったら後片付け忘れずに。

# おわりに
基本的な認可、認証のフローが腹落ちしました。

# 参考
[【連載】世界一わかりみの深いOAuth入門 〜 その1:OAuthってなに？ 〜](https://tech-lab.sios.jp/archives/25470)
【vue.js】v-forで連想配列のインデックス番号を取得する方法

## 課題
vue.js(v3)で連想配列を扱うが場面あり、データの数を連番で出力したくなった。
## 前提
例えばこういう連想配列があったとして、
```javascript:hoge.vue
let obj ={
    'key1':val1, //1番目
    'key2':val2, //2番目
    'key3':val3 //3番目
}
```
これらをテーブル形式で出力したいのでvue.jsのv-forで以下のように書いた。
```javascript:hoge.vue
<table>
    <tr v-for="(Arrays,index) in obj">
        <tbody>
            <tr>
                <td>{{ index }}</td> // key1,2,3が出力
                <td>{{ Arrays }}</td> // val1,2,3が出力
            </tr>
        </tbody>
    </tr>
</table>
```
ここにthを追加してデータの数を連番で出力したくなった。
```javascript:hoge.vue
<table>
    <tr v-for="(Arrays,index) in obj">
        <tbody>
            <tr>
                <th>データの数を連番で出力したい</th> // 1,2,3として出力したい
                <td>{{ index }}</td> // key1,2,3が出力
                <td>{{ Arrays }}</td> // val1,2,3が出力
            </tr>
        </tbody>
    </tr>
</table>
```
しかし連想配列は通常の配列（一次元配列）と違ってインデックスにキー（文字列）が使用されているので、数字として取れない。

## 解決策
v-forの第三引数に **count（名前は何でもOK）** を追加することで解決しました。
```javascript:hoge.vue
<table>
    <tr v-for="(Arrays,index,count) in obj">
        <tbody>
            <tr>
                <th>{{ count+1 }}</th> // 連番1,2,3が出力
                <td>{{ index }}</td> // key1,2,3が出力
                <td>{{ Arrays }}</td> // val1,2,3が出力
            </tr>
        </tbody>
    </tr>
</table>
```
これで連想配列内のデータのインデックス番号を取得することが出来ました。
ちなみにインデックス番号は0始まりなのでth内では「count+1」としています。

## ありがとうv-for
異なる配列から連想配列を作成した後に今回の課題に直面したので、v-forの便利さに感動しました。
## 参考
[v-for をオブジェクトに適用する リストレンダリング | Vue.js](https://ja.vuejs.org/guide/essentials/list#v-for-with-an-object)
Return Values - CS50’s Introduction to Programming with Python

CS50’s Introduction to Programming with PythonのShortsよりReturn Valuesの内容を記載したいと思います。動画で勉強しながら、復習になど使っていただけたら嬉しいです。

まだ、下記の記事を読んでいない方は、先にそちらを読んだ方が、わかりやすいと思います。
[Functions - CS50’s Introduction to Programming with Python](https://qiita.com/natsuki_natsuki/items/2357ea32d2e099500405)

動画へは下記リンクよりアクセスできます。動画を見ながらまたは、復習として、この記事をご活用ください。
[Return Values - CS50P Shorts
](https://www.youtube.com/watch?v=Jt1p_qQYeUU)

まず、[Visual Studio Code for CS50](https://cs50.dev/)にアクセスして、GitHubアカウントでログインします。

Terminalで
```bash:Terminal
code greeting.py
```
を実行して、greeting.pyのファイルを作成します。

greet functionを定義します。

```python:greeting.py
def greet(input):
	if "hello" in input:
		print("hello, there")
	else:
		print("I'm not sure what you mean")
```

定義したgreet functionを呼び出します。今回は、argumentも入力します。入力しがargumentは、inputにわたされて、functionが実行されます。argumentに"hello"が含まれていれば、"hello, there"と、そうでなければ"I'm not sure what you mean"と返されます。

```python:greeting.py
def greet(input):
	if "hello" in input:
		print("hello, there")
	else:
		print("I'm not sure what you mean")
greet("hello, computer")
```
```bash:Terminal
python greeting.py
```
を実行すると
"hello, there"と返ってきます。

今度は、returnされるようにします。
先ほどのコードのprint functionをreturnに変更します。

```python:greeting.py
def greet(input):
	if "hello" in input:
		return "hello, there"
	else:
		return "I'm not sure what you mean"

greet("hello, computer")
```
ここで、先ほどのように
greeting.pyを実行してもなにも返ってきません。returnで返されたものは、どこかに保存してそれをprintしないと実際に返ってきたものを見ることはできません。

```python:greeting.py
def greet(input):
	if "hello" in input:
		return "hello, there"
	else:
		return "I'm not sure what you mean"

greeting = greet("hello, computer")
print(greeting)
```

greetingにgteet functionに返ってきた値を代入して、print functionで書き出します。

今度は、python greeting.pyを実行するとhello, thereと出力されます。
print(greeting)をprint("Hm, " + greeting)やprint(greeting + " Carter")に変更して実行してみます。

returnを使うとside effectとしてすぐに何かが出力されるのではなく、他のところで、再利用したり、値を渡したりすることができます。
画像を２値化する【道具としての OpenCV 画像認識】

# 本記事でできること
画像を明るさの情報をもとに2値化します。

元画像
![Screenshot from 2024-03-03 19-19-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37698/e3d4042a-df1d-d1ec-5b1e-d4dbc6056090.png)

２値化画像（閾値：180）
![Screenshot from 2024-03-03 19-20-53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37698/1e54fb39-7ee0-b77a-c9d0-a1b559ce54c8.png)

# 想定シーン
## ロボットをビジュアルフィードバック制御する
カメラを使ったロボットアームの制御方法を、ビジュアルフィードバック制御といいます。ここでは、ビジュアルフィードバック制御を使った自動化システムを開発する際に必要となる画像認識プログラムをまとめています。

## 画像を２値化する
画像処理の中でも、２値化はもっともよく使うアルゴリズムのひとつです。ここでは、画像内の明るさに基づいて領域を分割する２値化のプログラムを掲載します。

# 実行環境
- OS：Ubuntu 22.04 LTS
- 言語：C++
- クルーボ：v5.1.0

## クルーボについて
ロボットアプリケーション開発には、株式会社チトセロボティクスのロボット制御ソフトウェア「クルーボ」を使用します。本記事のプログラムは、クルーボがインストールされた制御コンピュータ上で動作します。

- クルーボの製品サイト：https://chitose-robotics.com/product

## プログラム抜粋
```c++
cv::Mat binary(const cv::Mat& image, const int threthold) {
    cv::Mat image_gray = convert_grayscale(image);
    cv::Mat binary_image;
    if (threthold == 0) {
        threshold(image_gray, binary_image, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
    } else {
        threshold(image_gray, binary_image, threthold, 255, cv::THRESH_BINARY);
    }
    return binary_image;
}
```

２値化の閾値（threthold）を0にした場合には、大津の２値化が適用されます。大津の２値化はアルゴリズムによって、閾値を自動設定します。


大津の２値化を適用した場合
![Screenshot from 2024-03-03 19-19-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37698/23cdf5e4-ccd3-2f5f-f233-390be62c1c9f.png)

## 全体プログラム
```c++
#include <iostream>
#include <opencv2/opencv.hpp>

cv::Mat load_image(const std::string file_path) {
    cv::Mat loaded_image = cv::imread(file_path, 1);
    if (loaded_image.empty()) {
        throw std::runtime_error("画像を正常に読み込めませんでした。");
    }
    return loaded_image;
}

cv::Mat convert_grayscale(const cv::Mat& image) {
    const int grayscale_channel_num = 1;
    if (image.channels() == grayscale_channel_num) {
        return image.clone();
    }
    cv::Mat gray_image;
    cvtColor(image, gray_image, cv::COLOR_BGR2GRAY);
    return gray_image;
}

cv::Mat binary(const cv::Mat& image, const int threthold) {
    cv::Mat image_gray = convert_grayscale(image);
    cv::Mat binary_image;
    if (threthold == 0) {
        threshold(image_gray, binary_image, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
    } else {
        threshold(image_gray, binary_image, threthold, 255, cv::THRESH_BINARY);
    }
    return binary_image;
}

int main(void) {
    std::string file_path = "../data/green_sample.jpg";
    const cv::Mat loaded_image = load_image(file_path);

    const int threthold = 180;
    const cv::Mat binary_image = binary(loaded_image, threthold);

    cv::imshow("window", binary_image);
    cv::waitKey(0);
}
```

## おわりに
人手作業をロボットアームで自動化するために、カメラを使ったロボット制御＝ビジュアルフィードバック制御が大切です。
ロボット制御用の画像認識でも中身のひとつひとつはシンプルなので、要素に分解して解説していきたいと思います。
Rhino8でPythonのライブラリを使う際のメモ

# はじめに
Rhino8からはPythonのライブラリがつかえるようになりました

https://www.rhino3d.com/jp/features/developer/scripting/

さっそく色々インポートしてみたのですが意外と苦労してしまったという記録を残します
# numpy
まずは超定番のnumpyをインポートしてみる
### サンプル通りにやってみる
サンプル通りだとこれで読み込めるはず
```diff_python
# r: numpy
import numpy as np
```
だがこんなエラーが出てしまうことがある。こまった・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/028ef228-1113-01dd-71fa-d759d870c472.png)
### Xでアドバイスをいただきました！
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">はじめまして、突然失礼します。<br>私も同じ現象が起きましたがこちらで解決できました。<a href="https://t.co/lz6suoZT5R">https://t.co/lz6suoZT5R</a></p>&mdash; まつした (@spade_ken) <a href="https://twitter.com/spade_ken/status/1764218489529839894?ref_src=twsrc%5Etfw">March 3, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

### インポートできたコード
教えていただいた情報を参考に2行目を追加したら・・・
```diff_python
# r: numpy
# venv: site-packages
import numpy as np
```

インポートできた！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/8decde07-f0d3-304d-aa7e-12bd05fe54e6.png)

# pandas
こちらも超定番のpandasをインポートしてみる

```diff_python
# r: pandas
import pandas as pd
```

だがこんなエラーが出てしまう。またまたこまった・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/1a192193-a9f6-76f9-3d64-467917c324c3.png)

### こちらもXでアドバイスをいただきました！
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">こんにちは。pandasに関しては、locateが何処かと言うのに影響を受けるという報告が上がっているようです。これでしょうか？<a href="https://t.co/iIqQTu58ou">https://t.co/iIqQTu58ou</a></p>&mdash; Masaki Tagami / 田上　雅樹 (@curry247_) <a href="https://twitter.com/curry247_/status/1764205306274566551?ref_src=twsrc%5Etfw">March 3, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

コードを修正して実行
```diff_python
# r: pandas
import locale
locale.setlocale(locale.LC_ALL,'en_US')

import pandas as pd
```

だが違うエラーが出てしまう。またまたこまった・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/33846302-3e12-897c-4914-8b91006d90f4.png)

### Rhino8を管理者として実行してみる
フォルダの権限的なエラーメッセージが出ていたのでRhino8を管理者権限で実行してみた。するとさっきと違うエラーが出た。けどこれはnumpyのときに見たやつだ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/23c5a98b-ee8d-b0cf-77a0-70aca79b3add.png)



### インポートできたコード
numpyのときの解決策を掛け合わせてみる
```diff_python
# r: pandas
# venv: site-packages
import locale
locale.setlocale(locale.LC_ALL,'en_US')

import pandas as pd
```
インポートできた！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/3881ef4c-6c27-0cbc-2a93-ebcc845bdc23.png)

# まとめ
上手くいかないときは `# venv: site-packages`を追加するか管理者として実行で解決できる可能性があるのでお試しください
まつしたさん、田上さんアドバイスありがとうございました！
asdfでWSL+UbuntuにRubyをインストール

# はじめに

プログラミング言語管理ツールのasdfを使って、WSL UbuntuにGoをインストールします。

# 前提環境

https://qiita.com/perilla/items/69bc6f89001dbceb0cde

https://qiita.com/perilla/items/ef73cf57ade24bc94f19

#asdf更新

```sh:Ubuntu
asdf update
```

# Rubyの存在確認

```sh:Ubuntu
asdf plugin list all | grep -e ruby
# ruby                          https://github.com/asdf-vm/asdf-ruby.git
```

https://github.com/asdf-vm/asdf-ruby.git

# asdfにRubyを追加

```sh:Ubuntu
asdf plugin add ruby
```

# 依存パッケージをインストール

[GithubのREADME](https://github.com/asdf-vm/asdf-ruby)に従い依存パッケージをインストールします。（「[Ubuntu/Debian/Mint](https://github.com/rbenv/ruby-build/wiki#suggested-build-environment)」項を確認のこと）

```sh:Ubuntu
sudo apt install autoconf patch build-essential rustc libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libgmp-dev libncurses5-dev libffi-dev libgdbm6 libgdbm-dev libdb-dev uuid-dev
```

# 最新版Rubyをインストール

```sh:Ubuntu
asdf install ruby latest

# asdf: Warn: You have configured asdf to preserve downloaded files (with always_keep_download=yes or --keep-download). But
# asdf: Warn: the current plugin (ruby) does not support that. Downloaded files will not be preserved.

# https://github.com/asdf-vm/asdf-ruby/issues/384
```

警告が出ましたが、気に留めておきひとまず進める。

# 最新版Rubyをグローバルに設定

```sh:Ubuntu
asdf global ruby latest
```

# Rubyバージョン確認

```sh:Ubuntu
asdf current ruby
# ruby            3.3.0           /home/[user]/.tool-versions

ruby -v
# ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux]

gem -v
# 3.5.3
```
PHPUnitでテスト件数がずれる。

## PHPUnitでテスト件数がずれる。
LaravelにてPHPUnitでテストコードを実行したところ、実際の件数とコンソールに出力される件数がずれる事象が発生

#### 原因
テストデータのキーが重複していたこと

```
/**
*テストデータ提供メソッド
**/
public function provider(): array {
  return [
    '正常系' => [1, 2, 3],
    '正常系' => [1.1, 2.2., 3.3]
  ];
```
↑テストデータのキーが正常系で重複しているので１件とカウントされる。

```
/**
*テストデータ提供メソッド
**/
public function provider(): array {
  return [
    '正常系_int' => [1, 2, 3],
    '正常系_double' => [1.1, 2.2., 3.3]
  ];
```
↑上記なら想定通り2件とカウントされる。
Mac（M1）のnodeバージョンアップ

## 背景
nodeのバージョンをあげずに放置していたらv16系だったので、バージョンをあげることにしました。
その際のまとめです。

## 現在のバージョン確認

### Homebrew

```
$ brew -v
```

### nodebrew

```
$ nodebrew -v
```

### Node.js

```
$ node -v
```

### npm

```
$ npm -v
```

## バージョンのアップデート

### Homebrew

```
$ brew update
```

終わったらちゃんと上がっているか先ほどのコマンドでバージョン確認。

### nodebrew

```
$ brew upgrade nodebrew
```

自分の場合はここでエラーが出ました。

```
Error: Failure while executing; `/usr/bin/env cp -pR /private/tmp/d20240303-30797-co2iaz/nodebrew/. /usr/local/Cellar/nodebrew` exited with 1
```

一旦nodebrewをアンインストールしようと思ったのですが、それもエラーとなったので次の通りに削除しました。

```
$ sudo rm -rf /usr/local/Cellar/nodebrew/1.1.0
```

無事削除完了。再度Nodebrewをインストールします。

```
$ curl -L git.io/nodebrew | perl - setup
```

## Node.jsの特定のバージョンのインストール
```
$ nodebrew install-binary vX.X.X
```

Nodebrewを使用して、指定されたバージョンのNode.jsをインストールします。


## Node.jsのバージョンを切り替える

```
$ nodebrew use vX.X.X
```

Nodebrewを使用して、特定のバージョンのNode.jsを使用します。
これで再度`node -v`でバージョン確認。

...あれ、変わってない。
どうやらPATHが通ってなかったようなので設定しました。

## PATHの設定
```
$ echo 'export PATH="$HOME/.nodebrew/current/bin:$PATH"' >> ~/.zshrc
```
PATHにNodebrewのインストールディレクトリを追加することで、
NodebrewでインストールされたNode.jsのバージョンを直接実行できるようにします。

## 変更の反映
```
$ source ~/.zshrc
```

.zshrcファイルの変更を反映させるために、シェルを再読み込みします。

無事nodeのバージョンが上がっていることを確認。
めでたしめでたし👏
Functions - CS50’s Introduction to Programming with Python

CS50’s Introduction to Programming with Python のShortsよりFunctionsの内容を記載したいと思います。動画で勉強しながら、復習になど使っていただけたら嬉しいです。

まだ下記の記事を読んでいない方は、先にこちらを読んでからの方がわかりやすいかもしれません。
[VSCodeのTerminalの使い方とCommand LineをHavard CS50の動画で学ぶ](https://qiita.com/natsuki_natsuki/items/c7a4c3b55fc85bf02f19)

動画へは下記リンクよりアクセスできます。動画を見ながらまたは、復習として、この記事をご活用ください。
[Functions - CS50P Shorts](https://www.youtube.com/watch?v=lGS6O47debI)

まず、[Visual Studio Code for CS50](https://cs50.dev/)にアクセスして、GitHubアカウントでログインします。
## Pythonファイルの作成
Terminalで
```bash:Terminal
code hello.py
```
実行して、ファイルを作成します。

## functionとargumentを書く
今度は、今作成したhello.pyのファイルに
```python:hello.py
print("Hello, world!")
print("This is CS50P.")
```
と入力します。
functionは、function名と()よりできています。
上記だとprintがfunction名です。()の中には、argumentを記入します。上記だと"Hello, world!"と”This is CS50P."がargumentです。

## Pythonファイルを実行する
```bash:Terminal
python hello.py
```
を実行するとpythonファイルが実行されます。

## functionを定義する(define)
defを使うとオリジナルのfunctionを作ることができます。
```python:hello.py
def main():
    print("Hello, world!")
    print("This is CS50P.")
```
とするとmainというfunctionができます。
ここで、
```bash:Terminal
python hello.py
```
を実行してもなにも出力されません。
functionを定義しただけだと出力されないので呼び出す必要があります。

## functionを呼び出す(call)
```python:hello.py
def main():
    print("Hello, world!")
    print("This is CS50P.")

main()
```
main()とかいて呼び出します(call)
ここで、
```bash:Terminal
python hello.py
```
を実行すると、今度は、正常に出力されます。

次に読むのにオススメの記事
[Return Values - CS50’s Introduction to Programming with Python](https://qiita.com/natsuki_natsuki/items/213c475ef089d8b2611f)
Fラン文系、IT歴3ヶ月の自分が約56時間でAWS　SAAを合格した勉強法

## Fラン文系、IT歴3ヶ月の自分が約56時間でAWS SAAを合格した勉強法

 現在受託開発でエンジニアをしている者です。今回はタイトルにある通りAWS SAAに合格することができたので体験談を書きます。![twitter_GEcXsJsa8AAEU-Z.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3672923/26dad20f-39b5-f68e-9efb-1961a12aa634.jpeg)

 # 本記事の結論

 1.過去問　演習1〜4 （答えを見ながら1周）
2.教科書を読み込む
　約6時間かかりました。ざっくりでいいと思います。
3.過去問　演習1〜4
　合格の72%が出るまで同じ演習を繰り返す。解説を読み込んで理解に徹します。Udemyの解説を読んでも分からないサービスを適宜教科書で調べました。


# 使用教材
- [Udemy 【SAA-C03版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）](https://www.udemy.com/course/aws-knan/?couponCode=KEEPLEARNING)：約45時間
- AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)：約11時間


# **大前提** 意識すべき事
![c15bdc45ad7c-20220903.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3672923/5dc74b55-190f-d81c-1690-25b2c1b9a600.png)
　皆様からすれば当たり前の事かもしれませんが、私は以前試験勉強をする際教科書を一周を読むことから始めておりました。ですが、それでは本番でどのような形式で出題されるのかがよく分からずインプットしていることになります。ゴールから逆算していくことは非常に大切であることを[独学大全](https://www.amazon.co.jp/%E7%8B%AC%E5%AD%A6%E5%A4%A7%E5%85%A8-%E7%B5%B6%E5%AF%BE%E3%81%AB%E3%80%8C%E5%AD%A6%E3%81%B6%E3%81%93%E3%81%A8%E3%80%8D%E3%82%92%E3%81%82%E3%81%8D%E3%82%89%E3%82%81%E3%81%9F%E3%81%8F%E3%81%AA%E3%81%84%E4%BA%BA%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE55%E3%81%AE%E6%8A%80%E6%B3%95-%E8%AA%AD%E6%9B%B8%E7%8C%BF/dp/4478108536/ref=asc_df_4478108536/?tag=jpgo-22&linkCode=df0&hvadid=342357386112&hvpos=&hvnetw=g&hvrand=13842135596371165504&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009280&hvtargid=pla-932157601621&psc=1&mcid=beaaaca3fbf5343c8388886a4bcc24e2&th=1&psc=1)で学びました。まずは答えを見ていいので自ら体験してみると効率的です。


 # 学習手順
1.過去問　演習1〜4 （答えを見ながら1周）
2.教科書を読み込む
　約6時間かかりました。ざっくりでいいと思います。
3.過去問　演習1〜4
　合格の72%が出るまで同じ演習を繰り返す。解説を読み込んで理解に徹します。Udemyの解説を読んでも分からないサービスを適宜教科書で調べました。


 # 意識したことと反省点
 - インフラの知識はもちろんないので、紙にお絵描きしてイメージで覚えていました。
 - 公式HPにて模擬試験を受けられるらしい。演習問題と実際の試験では出題の仕方が少し変わっていたので（そりゃそう）、実際の模擬試験を受けて本番慣れをしておいた方が良いと感じました。
 - 本番試験ではコスト最適化の問題に苦労した。

 以上です。できるだけ情報量が増えないよう端的にお伝えしました。
 この記事が誰かの役に立つことがあれば筆者も嬉しいです。
画像の明るさを調整する【道具としての OpenCV 画像認識】

# 本記事でできること
![Screenshot from 2024-03-03 18-17-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37698/b4749d2a-b624-00e4-855f-3a1fef0ed661.png)

画像は、左上から横に、明るさバイアス
-100, -75, -50,
-25, 0, 25,
50, 75, 100
に変更したもの。（0は元画像と同じ）

# 想定シーン
## ロボットをビジュアルフィードバック制御する
カメラを使ったロボットアームの制御方法を、ビジュアルフィードバック制御といいます。ここでは、ビジュアルフィードバック制御を使った自動化システムを開発する際に必要となる画像認識プログラムをまとめています。

## 画像の明るさを調整する
ロボットをビジュアルフィードバック制御する際にはカメラ画像からの情報が欠かせません。ロボットシステム設置環境によっては、照明光量が少なかったり、直射照明によってハレーション（白飛び）が発生してしまう場合があります。このとき、画像の明るさを調節するためのプログラムを掲載します。


# 実行環境
- OS：Ubuntu 22.04 LTS
- 言語：C++
- クルーボ：v5.1.0

## クルーボについて
ロボットアプリケーション開発には、株式会社チトセロボティクスのロボット制御ソフトウェア「クルーボ」を使用します。本記事のプログラムは、クルーボがインストールされた制御コンピュータ上で動作します。

- クルーボの製品サイト：https://chitose-robotics.com/product

## プログラム抜粋
```c++
/* 明るさバイアス（推奨範囲：-100.0~100.0） */
cv::Mat adjust_brightness(const cv::Mat& image, const float brightness_bias) {
    cv::Mat colored_image = convert_colorimage(image);
    cv::Mat brightness_adjusted_image = colored_image + cv::Scalar(brightness_bias, brightness_bias, brightness_bias);
    return brightness_adjusted_image;
}
```

## 全体プログラム
```c++
#include <iostream>
#include <opencv2/opencv.hpp>

cv::Mat load_image(const std::string file_path) {
    cv::Mat loaded_image = cv::imread(file_path, 1);
    if (loaded_image.empty()) {
        throw std::runtime_error("画像を正常に読み込めませんでした。");
    }
    return loaded_image;
}

cv::Mat convert_colorimage(const cv::Mat& image) {
    const int colorimage_channel_num = 3;
    if (image.channels() == colorimage_channel_num) {
        return image.clone();
    }
    cv::Mat color_image;
    cvtColor(image, color_image, cv::COLOR_GRAY2BGR);
    return color_image;
}

/* 明るさバイアス（推奨範囲：-100.0~100.0） */
cv::Mat adjust_brightness(const cv::Mat& image, const float brightness_bias) {
    cv::Mat colored_image = convert_colorimage(image);
    cv::Mat brightness_adjusted_image = colored_image + cv::Scalar(brightness_bias, brightness_bias, brightness_bias);
    return brightness_adjusted_image;
}

int main(void) {
    std::string file_path = "../data/fuji.jpg";
    const cv::Mat loaded_image = load_image(file_path);

    /* 明るさバイアス（推奨範囲：-100.0~100.0） */
    const float brightness_bias = -25.f;
    const cv::Mat adjusted_image = adjust_brightness(loaded_image, brightness_bias);

    cv::imshow("window", adjusted_image);
    cv::waitKey(0);
}
```

## おわりに
人手作業をロボットアームで自動化するために、カメラを使ったロボット制御＝ビジュアルフィードバック制御が大切です。
ロボット制御用の画像認識でも中身のひとつひとつはシンプルなので、要素に分解して解説していきたいと思います。
NVIDIA With RTXを 4080/4090 で実行した際のテスト文

# Chat with RTX の動作確認です。
テスト用データなので

\```java
とかやってないです。まんま \``` で閲覧しておいてください。

YouTube 動画の URL です。
https://youtu.be/iverju3xeWk

- [x] 12.Chat with RTX の動作テスト
  - [x] java → Python
  - [x] ラムダ式について
        java のラムダ式の使い方の概要を教えてください。
        Please give me an overview of how to use lambda expressions in java.
  - [x] What is a realm?
        https://docs.oracle.com/javaee/5/tutorial/doc/bnbxj.html#bnbxm
  - [x] Ansible Playbookの概要を教えてください。
        Please give me an overview of Ansible playbooks.
  - [x] AWS の CloudFormation の概要を教えてください。
        Please give me an overview of AWS CloudFormation.
  - [x] VMware PowerCLI で仮想マシンを表示させるコマンドを教えてください。
        Please tell me the command to display virtual machines using VMware's PowerCLI.
  - [x] Microsoft PowerShell を linux 環境にセットアップする手順を教えてください。
        Do you know the steps to set up Microsoft PowerShell on Linux?
  - [x] ゲーム「Valheim」の概要を教えてください。
        Please give us an overview of the game "Valheim".
  - [x] ゲーム「タイタンフォール２」の概要を教えてください。
        Please give us an overview of the game "Titan Fall2".

## テスト例題 java → Python
Please change java to Python.
```
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello Java!");
    }
}
```

Jasmine

Please change java to Jasmine.
```
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello Java!");
    }
}
```
以上すっ(´・ω・`)
docker runでファイル生成したものがローカルにマウントされない

# はじめに

docker runですこし抜けていたことがあったので書いておきます

# 問題

docker runでTypeScriptのファイルを実行します
その中ではCSVを生成して出力するのですが、なぜかそのファイルがローカルに現れませんでした

本来はディレクトリ配下にあるoutputディレクトリに出力されるはずでした

```
docker run -v $(pwd)/environments/script:/script -w /script docker-registry.uzabase.com/proxy-cache/denoland/deno:latest deno run -A generateCSV.ts
```

# 解決方法

script直下にあったoutputディレクトリもマウントする必要がありました

```
docker run -v $(pwd)/environments/script:/script -v $(pwd)/script/output:/tmp -w /script docker-registry.uzabase.com/proxy-cache/denoland/deno:latest deno run -A generateCSV.ts
```

scriptをマウントしていたのでその下にあるoutputもマウントしているため、ここに生成したものはただしくローカルにも生成されると思ったのですが、明示的に書く必要がありました

# おわりに

すぐにきづけたのでよかったです
laravel select マルチ　保存方法 多対多テーブル利用


            <select class="form-control select2" multiple="" name="items[]" >
             @foreach ($itemss as $item)
                <option value="{{ $item->id }}">{{ $item->name }}</option>
             @endforeach
            </select>

            --Model--
            TableA
            TableA_TableB
            TableB
            --Controller-
            
            foreach($request->items as $itemId) {
                $table_AB = new TableA_TableB();
                $table_AB->$table_a_id = $table_a->id;
                $table_AB->table_b_id = $itemId;
                $table_AB->save();
            }
AzureAD(EntraID)参加したPCで、Chromeブラウザ初回起動時のトップページが指定したものにならないトラブルの解消方法

うちと同じようなことをしなければならないこともあると思うので
記録として残したく書かせていただきます。

## はじめに
この記事は以下のような方のための記事です。

・WindowsのPCがAzureAD(EntraID)に参加している
・Intuneなどのポリシー設定権限が**一切ない**
・そのため、共有PCのChromeブラウザトップページをレジストリで~~無理やり~~設定している
・新規ユーザーログイン時、Chromeのトップページが**初回起動時のみ**なぜか反映されない


## 設定方法
AzureADの場合でも通常のChrome用ADポリシーと同様に
HKLM\Software\Policies\Google\Chrome\RestoreOnStartupURLs
などのレジストリを設定すれば2回目起動以降のトップページは設定されます。

ただし、これだけでは2024年3月現在、初回起動時のみトップページが認識されず、
頻繁に利用者の変わる環境復元共有PCなどでは致命的使いづらさになるため、
以下の処理を行います。

C:\Users\Default\AppData\Local\Google\Chrome\User Data
フォルダ配下に、以下の記述の「Local State」ファイル（拡張子無し）を配置します。
（もしかしたらもう少し記述を削れるかもしれません）
```JSON:Local State
{
    "browser": {
        "first_run_finished": true
    },
    "management": {
        "platform": {
            "azure_active_directory": 8,
            "enterprise_mdm_win": 0
        }
    }
}
```
将来的な悪影響などについては**一切わかりません**ので、
環境復元下でブラウザのアップデートを止めているなど、
管理しているPCでご利用ください。

## おわりに
こんな仕事ばっかりしてます。
問題無ければまた何か書きたいです。
UE5 デカール距離カリングの実装(Implementing decal distance culling)

# 概要
デカールをカメラの距離によってカリングされるようにエンジン改造をしていきます。
実装した環境はUE5.1になります。
すでに「Fade Screen Size」という画面サイズでカリングする機能がありますが、
個別に設定するのは面倒＆使いづらいので一括の距離でカリングされるようにします。

# 実装

最初はカリング距離を調整できるようにコマンドを作成します。
```C++:DecalRenderingShared.cpp 24行
static TAutoConsoleVariable<float> CVarDistanceCulling(
	TEXT("r.Decal.DistanceCulling"),
	5000.0f,
	TEXT("Culls decals by distance.")
);
```

次は下記のコードのように書きます。
まずは、カメラの位置座標とデカールの位置座標の差分を求めます。
そのまま平方根で距離を求めたいのですが「DistancePosition」と「DistanceCulling」両方を二乗すればいいので、二乗して割り算を行い0～1のフェード値を取得します。
そのままだとだんだん消えていくのですが、最後の方に急激に消えて欲しいので、
イージング関数の一つ「easeInQuint」を導入しています(Fade * Fade * Fade * Fadeの部分)。
最後に0～1を1～0にするように反転処理を行います。
「CalculateDecalFadeAlpha」は必要ないので削除します。
```C++:DecalRenderingShared.cpp 327行
if (bIsPerspectiveProjection && Data.Proxy.FadeScreenSize != 0.0f)
{
	//Data.FadeAlpha = CalculateDecalFadeAlpha(Data.Proxy.FadeScreenSize, ComponentToWorldMatrix, View, FadeMultipli
    
	float DistanceCulling = CVarDistanceCulling.GetValueOnRenderThread();
	FVector DistancePosition = View.ViewMatrices.GetViewOrigin() - ComponentToWorldMatrix.GetOrigin();
	float Fade = FMath::Clamp(DistancePosition.SizeSquared() / FMath::Square(DistanceCulling), 0.0f, 1.0f);
	Fade = Fade * Fade * Fade * Fade;
	Data.FadeAlpha = 1 - Fade;
}
```
「Data.FadeAlpha」を0にすると描画されませんので結果的にカリングされます。

# 結果
![DecalFadeEaseInQuint.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156053/484bb69e-32b0-9f81-f754-ca06fe96ca78.gif)

# まとめ
デカールを距離でカリングすることで、GPU、CPUの最適化が行い安くなりました。

# 参考
https://easings.net/ja#easeInQuint
【SES企業への転職】メリット4つデメリット4つあげてみた

## SES（システム・エンジニアリング・サービス）とは？

SES（システム・エンジニアリング・サービス）は、エンジニアの技術力を貸し出すビジネスモデルの一つで、委託契約の一種です。SES企業に所属するエンジニアは、自社とは正社員として雇用され、SES契約に基づいて顧客のプロジェクトに参画します。一方、顧客と結ぶ契約は準委任契約と呼ばれます。

SES企業は、エンジニアの月の単価（レンタル料金）を顧客と先に決め、その単価内でエンジニアの給料が支払われます。このビジネスモデルにより、エンジニアの案件が継続している限り、会社は赤字になることがありません。

ただし、エンジニアの現場が決まらない場合は、会社が自己資金から給料を支払わなければなりません。SESでは、エンジニアへの還元率が高いことが重視されますが、これは単価に対するエンジニアへの支払いの割合を指します。

## SESのメリットとデメリット

### メリット

1. **未経験からでも転職しやすい**: 
SES企業は未経験者を積極的に採用する傾向があります。これは、案件ごとに求められるスキルスタックがことなるため、必ずしも即戦力である必要がないことが理由です。そのため、未経験からのエントリーも歓迎されることがあります。
　
2. **様々な業界経験を積める**: 
SES企業は様々な業界やプロジェクトに参画する機会があります。これにより、エンジニアは幅広い経験を積むことができます。例えば、製造業や金融業界など、異なる業種のプロジェクトに参画することで、業界特有の知識や技術を習得することができます。
　
3. **スキルアップの機会が多い**: 
SES企業では、教育制度やスキルアップ体制、研修カリキュラムを整備し、未経験からの早期スキルアップを支援している企業があります。具体的には専属講師によるIT基礎研修や社内ポータルサイトによる研修動画の公開、eラーニング研修などが主流となっています。
　
4. **対人スキルの向上が見込める**: 
SES企業では、クライアントとのコミュニケーションが頻繁に行われます。そのため、エンジニアはコミュニケーション能力を高める機会が多くあります。また、プロジェクトメンバーやクライアントとの協力関係を築くことで、チームワークやリーダーシップスキルも向上させることができます。

### デメリット

1. **働き方に矛盾が生じやすい**: 
SES契約と雇用契約の間には矛盾が生じることがあります。例えば、有給休暇の消化や退職のタイミングが契約と合わない場合、調整が必要となります。また、SES契約では月間稼働時間が定められているため、有給休暇を取得しても稼働時間を確保する必要があります。（GWやお盆時期に発生しやすい）
　
2. **待機期間は給料減少のリスクあり**: 
SES企業では、参画案件が決まらない待機期間中は休業扱いとし、給料が減少する場合があります。これは、SES契約がプロジェクトごとに成立するため、案件が決まらないと収入が得られないからです。しかし、待機期間中でも給与を100％支給するSES企業も存在します。例えば、待機しているエンジニアの割合が低いSES企業では、
他のエンジニアの売上で待機期間中の給与を賄うことができるため、給与の減額が行われない傾向があります。給与の減額は合法的な手段であるもの、待機期間中の経済的な負担を考えると、給与が100%保証された企業を選ぶのが賢明です。
　
3. **上流工程経験を積みづらい**: 
SES企業では、自社開発やSIerに比べて上流工程の案件が少ない傾向があります。すでに固まった要件に沿っての構築やテスト、運用フェーズからの参画が一般的です。ただし、常駐期間が長い、または経験豊富なエンジニアである場合は、クライアントから要件定義からの案件参画を求められるケースがあり、SESだからと言って必ずしも上流工程を経験できないということはないです。
　
4. **人間関係の希薄さ**: 
SES企業では、本社との人間関係が希薄な場合があります。プロジェクトごとに異なる現場で作業するため、本社とのコミュニケーション機会が限られることがあります。そのため、会社への帰属意識を持ちにくい傾向があります。

## まとめ
SESは、エンジニアが自身の技術力を活かして様々なプロジェクトに参加し、スキルアップを図ることができるビジネスモデルです。メリットとデメリットを理解し、自身のキャリアプランや目標に合わせて適切な選択をすることが重要です。

---

この記事ではSESの基本的な概念、メリット、デメリットについて解説しました。SESでのキャリアを考える際の参考にしていただければ幸いです。
psqlのメタコマンド一覧

メタコマンドは、SQLコマンドとは異なり、改行で終わりが判断される。

| メタコマンド        | 説明                                                                         |
|-------------------|------------------------------------------------------------------------------|
| \q（\quit）         | psqlを終了する                                                                 |
| \l（\list）         | データベースの一覧を表示する。psql -lと同じ効果                                |
| \d パターン          | 指定したパターンに名前が一致するテーブル、インデックス、ビュー、シーケンスの構成情報を表示する。パターンには、ワイルドカード（* や ?）が使える。 |
| \d                  | テーブル、ビュー、シーケンスの一覧を表示する                                     |
| \du                | データベースユーザの一覧を表示する                                               |
| \dn                | スキーマの一覧を表示する                                                         |
| \dt                | テーブルの一覧を表示する                                                           |
| \di                | インデックスの一覧を表示する                                                     |
| \dv                | ビューの一覧を表示する                                                             |
| \ds                | シーケンスの一覧を表示する                                                         |
| \dS                | システムカタログの一覧を表示する                                                   |
| \df                | 関数の一覧を表示する                                                               |
| \dp（\z）           | テーブル、ビュー、シーケンスの一覧と、それらに設定されているテーブル単位の権限を表示する |
| \copy              | PostgreSQLとpsqlの間でテーブルデータをコピーする                                   |
| \password [ユーザ名] | 指定したデータベースユーザ（デフォルトは現在のユーザ）のパスワードを変更する         |
| \c（\connect）データベース名 | 既存の接続を切断し、指定したデータベースに新規接続する                             |
| \x                  | 結果の表示形式を拡張モードに変更する                                                |
| \?                  | メタコマンドの一覧を表示する                                                       |
| \h [SQLコマンド]（\help） | 指定したSQLコマンドのヘルプ情報を表示する。SQLコマンドが未指定の場合、SQLコマンドの一覧を表示する |
初めてのPHP #1



昨日勉強した内容のアウトプット目的です。昨日paizaのスキルチェックテストをプレイして2時間くらいかけて正解しました。


`fgets`は複数の意味のある変数？　分解？してやる必要あり上記画像では`$ai`で
`$ai`を出力すると配列だったので`explode`関数を用い値を返しました
```php
$unti = explode("," , $ai) //←　"," これが第一引数（だいいちひきすう）　配列を何で区分するかということ
```
`$ai`の部分が分解する対象　そういう感じ　しらんけど。

問が　配列の合計値が`$imput_line`以下の場合OK、そうでない場合はNGと出力せよだったので
以降はif構文を使い条件を指定

```php
if($uniti[0] + $unti[1] + $unit[2] > $inmut_line)
{ echo "NG" ; }

else{ echo "OK" ; }  // となる感じの問題。
```

鬼門はfgetsのニュアンスを理解できていなかったことだったかも。

補足としてfor構文もおさらいしとく

```php
for($i=0;$i<count(nums);$i++) 
echo $nums[$i]*table 
```

そんな感じ。 これからはPHPも趣味がてらちょっとずつやっていきたい。
jetpack composeでキーボード入力完了時に特定の処理を行う

# はじめに
今回はjetpack composeでキーボード入力完了時に特定の処理を行うを紹介していきます
### 本文
TextFieldの引数に対して下記の引数を追加するのみです。
アイコンを変えたい場合は`keybodardOption`の`IMEOption`を設定するのみです
```kotlin
keyboardActions = KeyboardActions {
/// 行いたい処理
}
```
### 最後に
どなたかのお役に立てれば幸いです
Next.js(JSフレームワーク)で`satisfies`(TS新機能)が使用できなかった件

## 問題概要

Next.jsプロジェクトにおいて、[TypeScript4.9追加された`satisfies`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html)を使用したい場面がありました。しかし、TypeScriptのバージョンを5.xに上げても開発サーバー(`next dev`)で以下のようなエラーが発生してしまいました。

```sh
Error: 
  x Expected a semicolon
    ,----
 14 | const tag = { type: 'Post', id: 'LIST' } satisfies T;
    :                                              ^^^^^^^^^
    `----
```

※ ただしVSCode上でエラーは表示されていません。

何故、最新のTypeScriptをインストールしているにもかかわらず新機能を利用できないのでしょうか。その原因と対策を探ることにします。

### 実行環境

- Next.js 12.3.4
- TypeScript 5.1.6

## 原因と解決策

結論から言うと、Next.js 14.x 等にアップグレードすることで使用できるようになりました。特に設定がない限り[Next.jsは内部的にJavaScriptおよびTypeScriptコードを変換するためにSWCを使用](https://nextjs.org/docs/architecture/nextjs-compiler)しており、サポートされるTypeScript機能はこれに依存するためです。

ただ、SWCのドキュメントによれば、[最新のTypeScriptのバージョンまでサポートしている](https://swc.rs/docs/migrating-from-tsc#typescript-version)という記載がありましたが、SWCのバージョンによる違いに関しては特に記載がありません。また、[Next.jsの依存関係](https://github.com/vercel/next.js/blob/v12.3.4/package.json#L72-L74)を[辿って](https://github.com/swc-project/swc/blob/v1.2.203/package.json#L131)も正確なTypeScriptのバージョンは不明でした。

### Babelの場合

※ Babelを使用している場合は以下で対応された模様。

https://github.com/vercel/next.js/commit/db214214d6d26cebd8b0004558019c8b667292c2


## `package.json`との相違

Next.jsを使用したプロジェクトの依存関係として最新のTypeScriptがインストールされ、IDE上エラーが出ていないのはどのような状況と言えるでしょうか。これはコンパイル(TS→JS)と型解析の役割の違いに起因します。

プロジェクトの型はインストールされたTypeScriptによってチェックされるためIDE上では問題ないと判断される一方、SWCではそれを尊重せずコンパイルするため結果に相違が生じてしまっていました。

逆にTypeScriptのバージョンが古くIDEでエラーを表示している場合でも、コンパイラー側で解析することができれば、(以下のように型を無視して)ビルドが可能となります。

```ts:next.config.js
const nextConfig = {
  eslint: { ignoreDuringBuilds: true },
  typescript: { ignoreBuildErrors: true },
};
```

## 結論

IDE上の表示とビルド結果の一貫性を確保するにはNext.jsが使用するコンパイラーとTypeScriptの両方に注意する必要があります。しかし正確なバージョンの推定は困難でした。

## 備考

何故か検証した中で[RTK Queryにおける`providesTags`の値を生成する関数](https://redux-toolkit.js.org/rtk-query/usage/automated-refetching#abstracting-common-providesinvalidates-usage)内では`satisfies`が使用可能でした。(何が他と異なるのか不明)

```ts:postApi.ts
getPosts: builder.query({
  // `providesList()`内では`satisfies`が使用可能
  providesTags: () => providesList(undefined, 'Post'),
  ...
}),
```
TerraformでIaCを始める

# はじめに

Google Cloud上でTerraformを少しだけ触ったのでメモです。

やったことは下記の4つです。

1. VPCをつくる
1. subnetをつくる
1. Compute Engineのインスタンスを建てる
1. ssh接続できるようにする

# Terraformを利用できるようにする

Google Cloud上では何もしなくてもCloud ShellからTerraformが利用できます。

```bash:Cloud Shellを開くとそのままTerraformが利用できる 2024.02.18
$ terraform --version
Terraform v1.7.2
on linux_amd64

Your version of Terraform is out of date! The latest version
is 1.7.3. You can update by downloading from https://www.terraform.io/downloads.html
```

# Terraformのソースを作成する

とても親切なチュートリアルがあったので、ほぼそのまま利用させてもらいます。

https://cloud.google.com/docs/terraform/get-started-with-terraform

```terraform:server-on-google-cloud/main.tf
provider "google" {
}
resource "google_compute_network" "vpc_network" {
  name                    = "my-custom-mode-network"
  auto_create_subnetworks = false
  mtu                     = 1460
}

resource "google_compute_subnetwork" "default" {
  name          = "my-custom-subnet"
  ip_cidr_range = "10.0.1.0/24"
  region        = "us-west1"
  network       = google_compute_network.vpc_network.id
}
# Create a single Compute Engine instance
resource "google_compute_instance" "default" {
  name         = "flask-vm"
  machine_type = "f1-micro"
  zone         = "us-west1-a"
  tags         = ["ssh"]

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-12"
    }
  }

  # Install Flask
  metadata_startup_script = "sudo apt-get update; sudo apt-get install -yq build-essential python3-pip rsync; pip install flask"

  network_interface {
    subnetwork = google_compute_subnetwork.default.id

    access_config {
      # Include this section to give the VM an external IP address
    }
  }
}
# [START vpc_flask_quickstart_ssh_fw]
resource "google_compute_firewall" "ssh" {
  name = "allow-ssh"
  allow {
    ports    = ["22"]
    protocol = "tcp"
  }
  direction     = "INGRESS"
  network       = google_compute_network.vpc_network.id
  priority      = 1000
  source_ranges = ["0.0.0.0/0"]
  target_tags   = ["ssh"]
}
# [END vpc_flask_quickstart_ssh_fw]
```

# Terraform実行

実行する前に Cloud Shell に上記のソースコードを持っていきます。Githubに置いたのでそこからcloneしました。

```bash:
git clone https://github.com/talomina/server-on-google-cloud
cd server-on-google-cloud/
```

## terraform init で初期化

Cloud Shell上でmain.tfのあるフォルダで初期化を行います。
```bash:init
terraform init
```

## terraform plan で構築する環境の確認

```bash:plan
terraform plan
```

もしコードにおかしいところがあれば、ここでエラーが表示されます。

## terraform apply で構築

```bash:apply
terraform apply
```

すると下記のように効かれるので、yesと入力します。

```
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes
```

## terraform destroy で撤収

これだけで作った環境を全て撤収することができるというのがIaCの醍醐味だと思います。

```bash:destroy
terraform destroy
```

# おわりに

Google Cloudはコンソール画面から操作する時に「同様のコード」としてTerraformでやった場合のソースコードを出してくれます。これはExcelで「操作の記録」としてマクロを作成してくれるあれと似ていると、個人的には思いました。

IaCはすごい。

# 参考文献

https://cloud.google.com/docs/terraform/get-started-with-terraform?hl=ja

https://github.com/terraform-google-modules/terraform-docs-samples/blob/main/storage/flask_google_cloud_quickstart/main.tf
Github基礎知識

# GitとGithub

### Gitはバージョン管理システム

- Gitは、プログラムなどを記述したソースファイルを管理するための「分散型バージョン管理システム」のこと。
- 複数人で開発を行う際に、**ファイルの変更履歴をすべて反映させ、簡単に管理できる**のがGitの最大の特徴といえる。
- Gitの具体的な機能は、下記のとおり
  - ファイルの変更履歴を管理
  - 過去のバージョンに戻せる
  - さまざまなファイルを管理できる
  - チームで作業を共有できる
- Gitを使えば、「ある1つのファイルを2人で同時に編集してしまったために、先に編集した人の変更内容が消えてしまった」ということや「編集前の状態を記録するため毎回コピーしなければならない」ということがなくなる。

### GitHubはWebサービス

- Gitが「ファイルの変更履歴を管理するバージョン管理システム」であるのに対し、GitHubは「Gitの作業をチームメンバー間でやりとりできるWebサービス」を指す。
- GitHubは、大きく**自分のパソコン内に存在する｢ローカルリポジトリ｣** で作業を行い **Githubに存在する｢リモートリポジトリ｣** で管理を行う。
- GitHubを使った開発は、ローカルでファイルを作成・更新し、リモートリポジトリにアップデートする、という流れで行っていく。

## 今回使用したコマンド

```sh
# 新規リポジトリのデフォルトブランチ名をmainに変更
git config --global init.defaultBranch main

# ユーザー名とメールアドレス
# Gitは誰が変更したのかが重要な為、この設定が必須
git config --global user.name "ユーザー名"
git config --global user.email "メールアドレス"
```

```sh
git clone https://??? # クローンするリポジトリのURL
cd #作業するディレクトリに移動
git checkout -b `作成するブランチ名`
touch `作成するファイル名`
git add `ステージングするファイル` # この操作がされていないファイルはcommitされない
git commit -m "コミットする内容"
git push origin `プッシュするブランチ名`
```
- 各コマンドで何が起こっているかのイメージ図
![gitadd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3686853/dfb3ce40-235f-e839-0f29-629b9bcad5e9.png)
![gitcommand.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3686853/882897c0-e52c-d0ea-8dd4-a599ce6f1819.png)

### ステージングはなぜ必要か？

- Gitには「ステージング領域」または「インデックス」と呼ばれるコミットを完了する前にフォーマットして確認できる中間領域がある。
- ステージングとはコミットしたいファイルを指定する作業を指す。これにより誤って修正途中やコミットしたくないファイルをコミットするのを防ぐことが出来る。
  
参考

- [Git、GitHubを教える時に使いたい資料まとめ](https://qiita.com/yuyakato/items/41751848add5dfd5289c) #Qiita
- [GitHubの使い方を画像つきで徹底解説・初心者でもすぐ使える！](https://www.sejuku.net/blog/73468)
- [図解！ Gitのブランチ・ツリーをちゃんと読む](https://qiita.com/jesus_isao/items/2a0495c973a4c911c2cc) #Qiita 
- [サル以下の存在がまとめた「Git用語」図解](https://qiita.com/hamachi4708/items/6517b0964c6ed1685ecf)
やっと苦手だった基本情報を合格し逃れることができたので経験談を語る

# 感動
5度目？の正直でやっと基本情報技術者試験に合格しました。
2023年4月から始まったCBT方式の試験は勿論、午後試験でCOBOLのある年とPythonが導入された頃と色々な試験内容を経験してきました。もっとちゃんと勉強してればこんなことにならなかったと思うのですが何故ここまでかかったのか振り返ってみます。

# 自分の受験歴史
0\. 完全未経験でSES企業に入社し、半年以内にITパスポート取得
1、2週間程度過去問解きまくりなんとか合格できました。

1\. ITパスポート受験後
ITパス合格し毎月の給料が上がったのをいいことに、基本情報も取得して給料を増やそうと目論み始めました。
年は忘れましたがCOBOLは選択肢に入っていた頃です。
ほぼノー勉で何しにきたのか絶望状態で昼食をとり午後試験もほぼ無理でした。

2\. リベンジ受験
今回も遅刻せず会場に着いた自分を褒め、合否前にもう無理だと悟る。

3\. 再リベンジ受験
勉強したつもりで受験したものの午前試験でOUT。午後試験は表計算かPythonを選択した気がします。一旦冷静になり暫く業務へ集中するため、基本情報から遠ざかりました。

~転職を挟む~

4\. 久しぶりの再々リベンジ
開発経験も積めるようになり、落ち着いてきたので改めて受験しました。
科目Bをセキュリティから解いた方がいいという情報を信じたが、時間をかけすぎてしまいアルゴリズムに時間をかけられずあと１問くらい足りず不合格となりました。

5\. 1ヶ月後クリスマスイブにリベンジ
科目Aが苦手な問題ばかりで不安でしたが、科目Bは問１から順番に解き、時間が足らない事もなくようやっと無事に2023年12月24日**合格**しました。

# 何故今回合格できたか
何回も受験したからもあるかもしれませんが、それ以外だと3つ要素があったかなと考えています。
### 午後試験(科目B)が簡単になった
まずこれですね。以前は何種類かありそこから自分で選択するので要領の悪い自分は3回目の受験の時も全て無駄に勉強していました。その結果あまり時間かけられず結果を出せませんでした。アルゴリズム問題も文が短くなりとっかかりやすくなりました。

### 1~3回目は受験料会社負担だった
これはありがたい制度だったのですが、落ちてもいいやという気持ちが勝っていたのも事実です。
時間があれば勉強しようというマインドだと結果的に勉強しないんですよね。ある程度緊張感ある環境の方が自分はやる気出すんだなと思います。

### 開発業務を通して教材の説明がスッと入ってきた
4〜５回目受験の頃には転職を機にようやく開発業務へ携わるようになりました。イメージができるようになった事で理解も深まりました。例えば今まで「ポートスキャン」という言葉を見てもすぐ忘れていたと思いますが、業務で関わる部分なのでスッと入ったし勉強している意味が少しあるようでちょっと感動しました。

# 勉強方法
1-3回目は「キタミ式の参考書」と「出るとこだけ！」を使っていました。
4-5回目は色々変わっていそうなのもあって参考書を買い直し、「柏木先生の基本情報技術者教室」と「予想問題集」にしました。

1\. 柏木先生の参考書を軽く１周読む

2\. 時間が許す限り皆さんご存じの<a href="https://www.fe-siken.com/fekakomon.php">過去問道場</a>を繰り返し理解を深める

3\. 2と並行的に予想問題集を2~3周解く

4\. IPA公式のサンプル問題を軽くする

5\. 移動時間などは<a href="https://www.youtube.com/@kihonzyouhou">【基本情報技術者試験YouTuber】すーさん</a>の動画を見る。


:::note info
後からわかりましたが、過去の午後試験ほど難しいものは科目Bに出なかったのでアルゴリズムはIPA公式のあるサンプル問題のレベルで充分でした。なので今後もCBT方式前のアルゴリズム問題を解くのは不要だと思ってます。
:::

# 最後に
自分みたいに過去の基本情報に苦戦していた方もリベンジするなら今です！
合格率も上がっているみたいなのでやはりレベルは落ちていると思います。とはいえ範囲が広いのは変わらないので対策しないと痛い目をみます。
また、勉強が苦手な人は自分のようにまず何とかして開発経験を積んでから受験するのも一つの手です。理解度が全然違いますので。
ただ年齢的に基本情報で浮かれていてはお恥ずかしい&前の会社の先輩が基本情報の後すぐに応用情報受けた方が良いとのアドバイスあったので無理ゲーな感じですが応用も取得する気で学習しています。
(合格して会社から一時お祝い金貰えるので、今まで参考書買った分など含めて資産的にプラマイ０に落ち着きそうで良かった🫠)