OmniAICreator/Qiita-1.07M huggingface dataset:
SpringBoot SecurityFilterChain

自分用メモ

ロールによるURLの制御

```ruby:SecurityConfig.java
package ***;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class DemoSecurityConfig {
    @Bean
    public InMemoryUserDetailsManager userDetailsManager(){
        UserDetails john = User.builder()
                .username("john")
                .password("{noop}test123")
                .roles("EMPLOYEE")
                .build();

        UserDetails mary = User.builder()
                .username("mary")
                .password("{noop}test123")
                .roles("EMPLOYEE","MANAGER")
                .build();

        UserDetails susan = User.builder()
                .username("susan")
                .password("{noop}test123")
                .roles("EMPLOYEE","MANAGER","ADMIN")
                .build();

        return new InMemoryUserDetailsManager(john,mary,susan);
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
        http.authorizeHttpRequests(configure ->
                configure
                        .requestMatchers(HttpMethod.GET, "/api/employees").hasRole("EMPLOYEE")
                        .requestMatchers(HttpMethod.GET, "/api/employees/**").hasRole("EMPLOYEE")
                        .requestMatchers(HttpMethod.POST, "/api/employees").hasRole("MANAGER")
                        .requestMatchers(HttpMethod.PUT, "/api/employees").hasRole("MANAGER")
                        .requestMatchers(HttpMethod.DELETE, "/api/employees/**").hasRole("ADMIN")
        );
        //use HTTP basic authentication
        http.httpBasic(Customizer.withDefaults());

        //disable CSRF
        //in general. not required for stateless REST APIs that use POST,PUT,DELETE and/or PATCH
        http.csrf(csrf->csrf.disable());

        return http.build();
    }
}
```
【Laravel】外部キー制約を追加したテーブルでシーディングをするとエラーが発生する

## きっかけ
シーディングを行ったら、SQLのエラーが発生した。詳細は以下の通り。
### 作業手順
1. Usersテーブルの`ID`カラムとTweetsテーブルの`user_id`カラムを関連づけるために、Tweetsテーブルの`user_id`カラムに外部キー制約を付ける。
2. UsersテーブルとTweetsテーブルのシーディングを実行する。
(以下のようなデータをTweetsテーブルに格納する。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/505b9694-8c33-7736-9878-6bf97a1bae81.png)

### エラー
```
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails(`example_app`.`tweets`, CONSTRAINT `tweets_user_id_foreign` FOREIGN KEY(`user_id`) REFERENCES `users` (`id`)) (Connection: mysql, SQL: ...
```

## 原因
シーディングを実行する時に`DatabaseSeeder`クラスに以下のように記述していた。
```DatabaseSeeder.php
public function run(): void
    {
        // \App\Models\User::factory(10)->create();
		$this->call([
			TweetsSeeder::class,
			UsersSeeder::class,
		]);
    }
```
※先にTweetsテーブルのデータを作成するように記述していたため、Tweetsテーブルのuser_idカラムに格納できるUsersテーブルのIDがない。というエラーが出ていた。

## 解決策
`TweetsSeeder::class`と`UsersSeeder::class,`の順番を逆にした。
```DatabaseSeeder.php
public function run(): void
    {
        // \App\Models\User::factory(10)->create();
		$this->call([
			UsersSeeder::class,
			TweetsSeeder::class,
		]);
    }
```
無事にシーディングを実行することができた。

## 参考サイト
https://qiita.com/kat0/items/a550355903585ec5fb1b

## 使用した本
https://www.amazon.co.jp/dp/4295202835?tag=yomeru-22&linkCode=ogi&th=1&psc=1

P.130 ログインユーザーの情報を保存する
CodePipelineからGitHubリポジトリを参照する際に「リポジトリが見つからない」場合のトラブルシューティング

## はじめに

CodePipelineからCodeStarを利用しGitHub接続をする検証中に、ハマった点について紹介します。

## 前提

- CodePipelineでは、CodeStarSourceConnection（デベロッパー用ツール > 設定 > 接続）を用いて、各種プロバイダーと接続が可能です。
- 接続設定がされていると、CodePipeline上の「リポジトリ名」「ブランチ名」の指定を元に、ソースコード取得が可能です。
- 今回の記事では、CodeStarSourceConnectionの接続設定自体についての解説は行いません。

参考：[CodeStarSourceConnection for Bitbucket Cloud, GitHub, GitHub Enterprise Server, GitLab.com, and GitLab self-managed actions](https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/action-reference-CodestarConnectionSource.html)

## 発生した事象

- GitHub上にリポジトリやブランチが実在するにも関わらず、CodePipeline上で`FullRepositoryName`が見つけられないと表示される

> [GitHub] No Branch [main] found for FullRepositoryName [yoyoyo-pg/gradle-publish-sample]

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411902/e097e735-a328-f052-5d34-58f97e1e2c33.png)

## 原因

- 以前、GitHub側にインストールしていたAWS Connectorを使いまわしており、今回のパイプラインの対象リポジトリに対するアクセス権限が存在しませんでした。
- こちらの設定に関しては、`GitHubのユーザーページ` > `settings` > `Integrations` > `Applications` から確認可能です。

![github-auth.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411902/0a5155bd-b434-839d-0909-413e4f744bae.png)

## 対処法

- 対象のリポジトリを新たに加え、`save`します。

![select-repo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411902/9759f1e6-f031-5ae0-8f8b-f41d143a8b45.png)

- パイプラインを再実行し、無事GitHubからのソース取得に成功しました！

![cicd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411902/af373688-b309-0c73-45b1-fc73dfe9b237.png)

## ついでに検証

- [CodeStarSourceConnectionについてのドキュメント](https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/action-reference-CodestarConnectionSource.html)に記載がありますが、リポジトリ名に関しては大文字小文字を正しく設定する必要があるようです。
- 今回だと`yoyoyo-pg/gradle-publish-sample`という指定ですが、あえて`YOYOYO-PG/Gradle-Publish-Sample`という指定で記載し、パイプラインを動かしてみました。
- ただし、こちらに関してはエラーとなる事無くソース取得に成功しました。
MetaQuest3でWebカメラの映像を表示する

# 概要
- MetaQuest3のUSBからカメラを接続し、そのカメラ映像を表示できるようにする
- カメラはMetaQuestのType-Cで入力する

# 動作動画
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Quest3で外部カメラの映像を取得した<br><br>以下を参考に<a href="https://t.co/02ucIYqXha">https://t.co/02ucIYqXha</a> <a href="https://t.co/7FFikLwDOH">pic.twitter.com/7FFikLwDOH</a></p>&mdash; 旧支配者たちよのタコ (@vent0908) <a href="https://twitter.com/vent0908/status/1745457101869346958?ref_src=twsrc%5Etfw">January 11, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 仕組み
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436651/8a35c533-8c6d-223b-9909-4c6b4db7fe69.png)

MetaQuest3に接続するカメラはUVC(USB Video Class)カメラを使用します
UVCカメラとは動作するためにドライバーが必要ないカメラのことです。これはオペレーティングシステムによって既に提供されている標準的なドライバーを利用して動作するらしい。


どうやらAndroid端末では、標準のカメラがメインカメラと認識されているらしく、外部接続したカメラを使用するには直接カメラを指定する必要があるようです。
https://source.android.com/docs/core/camera/external-usb-cameras?hl=ja


というわけでUnityでUVCカメラを使用する場合は以下のプラグインを使用します。動かすだけなら同梱のサンプルシーンをMetaQuest3にインストールします
https://github.com/saki4510t/UVC4UnityAndroid?source=post_page-----6bf1087bbf86--------------------------------


以上
今までVScodeのターミナルでfigを使っていたがCursorに乗り換えたらターミナルでfigが使えなくなった

## 概要

タイトルの通り、VScodeのターミナルでfigを使ってコマンド補完してもらっていた。
エディタをCursorに乗り換えたのだが、Cursorのターミナルではなぜかfigによる補完が効かない。しかも`$ fig doctor`コマンドを実行しても問題は発見されない。
この事象がうまく解決できたので簡単にまとめる。

## 解決までの道のり

1. figのウインドウを開き、SettingsからDanger Zoneの「Uninstall Fig」をクリックした。
1. ブラウザに飛ばされ、アンインストールの理由を聞かれる。日本語翻訳して「再インストール」をクリックし、更に理由を選択した。
1. より具体的な理由もフリーテキストで入力し、送信するとfig.dmgが勝手にダウンロードされる。これをダブルクリックで起動し、アプリケーションフォルダにドラッグアンドドロップする。
1. アプリケーションフォルダのfigをクリックして起動した。
1. Cursorの新しいエディタウインドウを開くと無事コマンドが補完される様になった。

figの再インストールは本当に簡単なので不具合があったら躊躇なく試して良さそうだった。（figの設定やログイン状態もそのまま引き継がれていた。）
MindでデータベースSQLServer2022 クエリーしてみる（ステップ1.1）select文渡し

# はじめに
この記事のお題はMindでデータベースSQLServer2022にクエリーしてみる（ステップ1.1）」です。ステップ1.1とはまだ最初のステップで足踏みを意味します。

[CでデータベースSQLServer2022 クエリーしてみる（ステップ1.1）dll化select文渡し](https://qiita.com/mylifewithviolin/items/1e9a2bb4d4936f82993d)という記事で単純なODBC接続、SELECT実行・結果表示、切断の実装をDLLにした状態からSELECT文を引数渡しするようにしていますので、今回はそのエクスポート関数をMindから実行してみます。

## この記事内容の作業環境
Windows11 Pro 22H2
CPU Intel(R) Core(TM) i3-5005U 2.00 GHz
Microsoft Visual Studio Community 2022 Version 17.4.4
Microsoft Visual C++ 2022
Mind Version 8.07 for Windows
SQL Server 16.0.1000.6 Express Edition
SQL Server Management Studio	19.2.56.2

# お題のデータべース
データベース名 日本語プログラミング言語
テーブル構成は[C（ステップ0.0）](https://qiita.com/mylifewithviolin/items/415ec4bf87219935a3c0)をご参照ください。

# お題のソースコード
## C
C側のソースコード、プロジェクト配置構成は[C（ステップ0.5）](https://qiita.com/mylifewithviolin/items/2615070f9b4cca51e531)と[C（ステップ1.1）dll化select文渡し](https://qiita.com/mylifewithviolin/items/1e9a2bb4d4936f82993d)をご参照ください。

## Mind
Mindのソースは下記のとおりです。

### メイン
まずメインです。なるべくシンプルな雰囲気になるようにしています。Mind文字列のNULL終端はいちばんお手軽な方法のやつです。

```mind:mssqlodbc.src
メインとは
	SELECTは　　　文字列定数　「SELECT * FROM 言語名&00&」
	API初期処理しておき

	DB接続し
	SELECTで　SQL実行し
	DB切断し

	API破棄処理すること。
```
「API初期処理」と「API破棄処理」はCのDLLをロードして関数アドレスを取得する処理とDLLをアンロードする処理です。
### API初期処理
```mind:mssqlodbc.src
API初期処理とは　（・　→　・）

　　　　「ODBCライブラリをロードする」を　一行表示し
　　　　ODBCライブラリをロードし　偽？　ならば 「ロード失敗」を　一行表示し　終り
　　　　 つぎに
　　　　「ロード成功」を　一行表示し

　　　　「関数アドレス群を取得」を　一行表示し
　　　　ODBC関数アドレス群を取得し　エラー？　ならば 「取得失敗」を　一行表示し　終り
　　　　 つぎに
　　　　「取得成功」を　一行表示する。
```
### SQL実行
```mind:mssqlodbc.src
SQL実行とは
	execで　アドレス指定でＡＰＩ呼出１する。
```
その他のソースコードは[Mind（ステップ1.0）](https://qiita.com/mylifewithviolin/items/7901da4001cada906663)をご参照ください。

# 実行結果
それでは実行してみます。ほんとに動くのか！？
```
C:\pmind\sample>mssqlodbc.exe
ODBCライブラリをロードする
ロード成功
関数アドレス群を取得
取得成功
SQLAllocEnv --> 0
SQLAllocConnect --> 0
SQLConnect --> 1
SQLAllocStmt --> 0
SUCCESS OPEN
SQLText --> SQLExecDirect --> -1
SQLDisconnect --> 0
SQLFreeConnect --> 0
SQLFreeEnv --> 0
SUCCESS CLOSE
ODBCライブラリを破棄する

C:\pmind\sample>
```
動きませんでした！？:joy:　C側はSELECT文を認識していないようです。

```c:mssqlodbc32.c
#define _EXPORTING

#include "mssqlodbc32.h"

__declspec(dllexport) void exec(wchar_t* select){
    setlocale(LC_ALL, "Japanese_Japan.932");
    printf("SQLText --> %ws\n", select);//☆この時点で文字列が出力されていない
    //照会する
    doSelect(henv, hdbc, hstmt, select);
    return;
}
```
# おわりに
ごめんなさい。タイムアウトです。次回は問題解決を試みます。MindはANSI系のSJISかもしれないのでC側でワイド文字とか使っちゃいけないのかもしれません。
SurfaceのOSリカバリを実施したはなし

## 経緯
Surface pro6の動作が遅いという話をいただき、状況を確認することに。
初見としては、以下の状況が見られた。
１．エクスプローラーを開くのに1分近くかかる。その他の動作ももっさりしている感じ。
２．アップデートを全く実施できておらず、OSもWindows10のままとなっている。
３．セキュリティソフトでサーチをかけるとどうやらウイルス周りも怪しいのではという感じ。

この対応を実施するにあたり最後はOSのリカバリを実施することになった。
他にもこういったトラブルが発生している方に向けて、ここに記録として残すことにした。

## 実施内容
まずは、セキュリティソフトを利用して、ウイルスの駆除を実施。
⇒問題なく完了。

そのあと、各種プログラムやOSのバージョンあアップを実行したのだが、これが全くもってうまくいかない。
なぜかエラーが発生してしまい、プログラムのインストールが思うようにうまく進まない。

そこで、何度か再起動を実行しながらバージョンアップを進めていたのだが、、、

突然以下のような画面でうんともすんとも言わなくなってしまっった。

![f47ba935-93c5-4c72-ae14-14823eec7813.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/798622/66e043ba-9a56-acb9-a06e-911105e3db18.png)

Surfaceのサポートページを確認すると
強制再起動で解決しない場合は、回復ドライブとやらを利用して、Surfaceのリセットを実施する必要があるとのこと。

## 回復ドライブの作成
以下のページを参考に回復ドライブを作成する。
[Surface の USB 回復ドライブの作成と使用](https://support.microsoft.com/ja-jp/surface/surface-%E3%81%AE-usb-%E5%9B%9E%E5%BE%A9%E3%83%89%E3%83%A9%E3%82%A4%E3%83%96%E3%81%AE%E4%BD%9C%E6%88%90%E3%81%A8%E4%BD%BF%E7%94%A8-677852e2-ed34-45cb-40ef-398fc7d62c07)

### ■必要なもの
１．USBドライブ
２．回復対象とは別のPC
基本的には、ページの指示に従って対応すれば問題なく回復用ドライブを作成することが出来る。
注）この作業は、購入した際に実施しておくことが推奨されている作業である。

## 回復ドライブを利用したリカバリ作業
以下のぺージを参考にSurfaceを出荷時に戻すリカバリ作業を実行する。
[回復ドライブを利用してSurfaceを出荷時に戻す](https://support.microsoft.com/ja-jp/surface/surface-%E3%81%AE-usb-%E5%9B%9E%E5%BE%A9%E3%83%89%E3%83%A9%E3%82%A4%E3%83%96%E3%81%AE%E4%BD%9C%E6%88%90%E3%81%A8%E4%BD%BF%E7%94%A8-677852e2-ed34-45cb-40ef-398fc7d62c07#bkmk_reset_surface)

### 必要なもの
１．故障中のSurface本体
２．回復用ドライブ
今回も基本的にはページの指示に従えば問題なくリカバリすることが出来る。
ただし、少し画像的にボタンの場所が見にくかったりするので、そこだけは注意が必要。


## 最後に
今回は、動作が重たいSurfaceのウイルス駆除、バージョンアップ作業、及びPC本体のリカバリ作業を実施した。
この体験から声を大きくして言いたいことは、大きく3つである。

１．バージョンアップはこまめに実施してください。
　　バージョンアップを実施しないとセキュリティのパッチ等が適用されず、
　　ウイルス感染の可能性が高まります。
  　　常にバージョンは最新に上げることを徹底していきたいものです。

２．リカバリ用の準備をしっかりとすること。
　　Surfaceだけなのか他のデバイスでもそうなのかは知識不足で不明だが、
  　　リカバリ用のドライブ作成のために別のPCが必要になるとは思いもしなかった。。。
    　ぜひ、購入時にこういった時の対応準備もしておきたいものだ。

３．バックアップはしっかりとすること。
　　今回、急なリカバリが必要になったため、
　　PC内のデータをバックアップすることが出来なかった。
  　　ぜひ、バックアップもこまめに取得し、必要なデータはPC内だけに置かないように。。


以上、文才がないため、長々と記載してしまったことをお許しください。
誰かのためになりますことをお祈りします。
LLMのトレーニングで必要な手法「分散学習」について紹介します。

LLMのトレーニング（事前学習や継続学習）は膨大なGPUリソースかかりますので、試したこともなく、いつもどうやって行っているのか疑問になっていました。
最近、中国のBaichuan（中国で有名なLLM）の技術レポートを読んだところ、LLMのトレーニング流れについて書かれていましたので、そのプロセスをある程度理解することができました。（このレポートは、おそらく唯一のLLMトレーニングの過程を全て公開したレポートだと思います。一般的には、LLMのトレーニングに関するレポートは精度の紹介にとどまり、詳細なプロセスやコツはほとんど公開されないため、これ読むことで結構勉強になりました。）

まずすべてのLLMは分散学習でトレーニングします。
なぜ分散学習が必要かというと、LLMをトレーニング際に学習するパラメーターの数が少なくとも数十億にも及ぶため、一台のGPUのメモリでは学習できないです。

分散学習には主に2種類の分散方法があります。それは、データ並列（DP: Data Parallelism）とモデル並列（MP: Model Parallelism）です。

## データ並列（DP: Data Parallelism）

データ並列は、すべてのGPU上で同じモデルを実行し、それぞれのGPUで異なるデータセットを使ってモデルをトレーニングする手法です。トレーニング後、各モデルのパラメーターの平均値を計算してパラメーター値を修正します。
計算を担当したGPUはWorkerと呼ばれ、勾配集約を担当したGPUはServerです。Serverは他のWorkerへ勾配を通信しますから。この計算を行うGPUは「Worker」と呼ばれ、勾配を集約するGPUは「Server」と呼ばれます。Serverは他のWorkerに勾配情報を伝達する役割を持ちますが、通信のボトルネックはServerに存在します。通信コストの大きさと負荷がコントロールしにくいために、データ並列は通常、単一のマシンに複数のカードがある場面で使用されます。また、データ並列は一台のGPUでは実行できないサイズのモデルには適用できないため、データ並列のみ使うと最近の大規模LLMのトレーニングはできないです。


## モデル並列（MP: Model Parallelism）

モデル並列は、パイプライン並列（PP:Pipeline Parallelism）とテンソル並列（TP:Tensor Parallelism）に分けられます。パイプライン並列は、モデルをいくつかの段階に分割し、それぞれの段階を複数のGPUに分散させます。一方で、テンソル並列では、モデルの異なる計算部分を複数のGPUに分散させる手法ます。（"段階"と"計算部分"の違いについては私もよくわからなかったです）


これら2種類の分散方法を組み合わせることにより、さまざまなLLMのトレーニングアーキテクチャが構築されています。
一般的なLLMトレーニングアーキテクチャには、Megatron、DeepSpeed（Zero）、Accelerateなどがあります。
最も人気あるのは、Microsoftによって開発されたDeepSpeedです。DeepSpeedはパラメーターを分散させることで、トレーニング時間とメモリ消費を大幅に削減することができます。（ファインチューニングの場合にも使われます）
AccelerateはHuggingFaceが提出した軽量アーキテクチャで、小規模なモデルのトレーニングに向いてます。

これらのアーキテクチャは一緒に使うこともできます、例えばMegatron-DeepSpeedというのはMegatronとDeepSpeedを結合したものです。（baichuanもこのアーキテクチャでトレーニングされてます）

今後もし機会あれば、分散学習でプレトレーニングも試してみたいと思います。


DeepSpeedについて：

https://github.com/microsoft/DeepSpeed

DP:

https://pytorch.org/tutorials/intermediate/ddp_tutorial.html

baichuanのレポート:

https://arxiv.org/abs/2309.10305
CでデータベースSQLServer2022 クエリーしてみる（ステップ1.1）dll化select文渡し

# はじめに
この記事のお題はCでデータベースSQLServer2022にクエリーしてみる（ステップ1.1）」です。ステップ1.1とは最初のステップちょい先を意味します。

[（ステップ0.5）](https://qiita.com/mylifewithviolin/items/2615070f9b4cca51e531)ではODBC接続、SELECT実行・結果表示、切断の実装をDLLにして、コンソールアプリケーションから単純に実行しました。今回はSELEC文をコンソールアプリケーションから渡せるようにします。

## この記事内容の作業環境
Windows11 Pro 22H2
CPU Intel(R) Core(TM) i3-5005U 2.00 GHz
Microsoft Visual Studio Community 2022 Version 17.4.4
Microsoft Visual C++ 2022
SQL Server 16.0.1000.6 Express Edition
SQL Server Management Studio	19.2.56.2

# お題のデータべース
データベース名 日本語プログラミング言語
テーブル構成は[（ステップ0.0）](https://qiita.com/mylifewithviolin/items/415ec4bf87219935a3c0)をご参照ください。

# 配置情報
 ソリューション、プロジェクトの配置については[（ステップ0.5）](https://qiita.com/mylifewithviolin/items/2615070f9b4cca51e531)をご参照ください。
 
# お題のソースコード
learn.microsoft.comの日本語サイトの下記に公開されているソースコードの流用です。どのように改変していったかは（ステップ0.5）以前の記事をご参照ください。

 https://learn.microsoft.com/ja-jp/sql/connect/odbc/cpp-code-example-app-connect-access-sql-db?view=sql-server-ver16


# C状態での変更点
exec関数の引数をワイド文字のポインタにして、内部に文字列のコンソール出力を追加。ロケールはSJISにしました。

```c:mssqlodbc32.c
#define _EXPORTING

#include "mssqlodbc32.h"

__declspec(dllexport) void exec(wchar_t* select){
    setlocale(LC_ALL, "Japanese_Japan.932");
    printf("SQLText --> %ws\n", select);
    //照会する
    doSelect(henv, hdbc, hstmt, select);
    return;
}
```
実行検証用のCのコンソールアプリケーション
```c:consoleApp.c
#include "mssqlodbc32.h"

void main() {
	wchar_t select[] = L"SELECT * FROM 言語名";
	openDb();
	exec(select);
	closeDb();
}
```

Cのdll（ダイナミックリンクライブラリ）のヘッダファイル
```c:mssqlodbc32.h
#pragma once

#ifdef _EXPORTING
#define FUNC_DECLSPEC    __declspec(dllexport)
#else
#define FUNC_DECLSPEC    __declspec(dllimport)
#endif

FUNC_DECLSPEC void openDb();

FUNC_DECLSPEC void exec(wchar_t* select);

FUNC_DECLSPEC void closeDb();
```

 # 実行結果
 それでは実行してみます。

```
SQLAllocEnv --> 0
SQLAllocConnect --> 0
SQLConnect --> 1
SQLAllocStmt --> 0
SUCCESS OPEN
SQLText --> SELECT * FROM 言語名
SQLExecDirect --> 0
| 言語ID        | 言語名                  | 公開年         | よみがな                  |
|           1 |                 Ｍｉｎｄ |        1985 |                 まいんど  |
|           2 |                  ＴＴＳ |        2000 |             てぃーてぃーえす  |
|           3 |                 ひまわり |        2001 |                 ひまわり  |
|           4 |                 ドリトル |        2003 |                 どりとる  |
|           5 |                 なでしこ |        2004 |                 なでしこ  |
|           6 |                 プロデル |        2007 |                 ぷろでる  |
|           7 |     Mind fro Android |        2012 |        まいんどふぉーあんどろいど  |
|           8 |                  スミレ |        2018 |                  すみれ  |
|           9 |                なでしこ３ |        2018 |               なでしこさん  |
|          10 |                 スミレ畑 |        2020 |               すみればたけ  |

SQLDisconnect --> 0
SQLFreeConnect --> 0
SQLFreeEnv --> 0
SUCCESS CLOSE
```
動きました。SELECT文の日本語も正常に引き渡されているようでした。

  # おわりに
C言語でのdll作成の情報は少ないので何かの参考になれば幸いです。また、次回は接続文字列や戻り値を返すように変更して参ります。結果セットを返すようになるのはだいぶ先です。
【CSS】Edgeのパスワード表示ボタンを非表示にする方法

## はじめに
Edgeで`<input type="password">`にパスワードを入力した際に以下のようにパスワード表示ボタンが表示されます。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f323334323434332f62653132323965382d376566382d376639642d323837362d3963333965386333386339332e706e67のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/2ed0cbd8-edef-82a1-2e23-70a4308fb6a4.png)

## 非表示にする方法
以下のようにCSSを記述することでパスワード表示ボタンを非表示にできます。

```css
::-ms-reveal {
  display: none;
}
```

TailwindCSSを使用している場合には以下のようになります。

```html
<input type="password" class="[&::-ms-reveal]:hidden" />
```

![スクリーンショット 2024-01-11 23.01.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/dd4af4f9-aeee-a9cc-50a6-271c20ffcef4.png)
Laravel existsのバリデーションルールで存在しないidをPOSTするとバリデーションエラーではなくSQLのエラーが返る

## 概要

Laravel + PostgreSQLの環境でとあるテーブルのidをつかってexistsのバリデーションをかけた。バリデーションルールにちゃんと引っかかることを確認したくて`999999`という値をidのキーでPOSTした。なぜかバリデーションチェックエラーではなくSQL系のエラーが返された。何が起きたのか簡単にまとめておく。

## 原因

当該テーブルのidカラムのデータ型の値範囲を超えてexistsルールでチェックしていた。

## 返されたSQLエラー

バリデーションエラーで400が帰ってほしいのに下記が返された。

```
SQLSTATE[25P02]: In failed sql transaction: 7 ERROR:  current transaction is aborted, commands ignored until end of transaction block
```

このとき自分はexistsのバリデーションルールがSQLを投げてチェックしていることを完全に失念しており、「なんでありえないIDを投げているのにバリデーションルール通過して、DB書き込み処理まで到達してしまったんだ！！！」というようにプチパニック担っていた。

## 簡単な説明

先に原因で書いたように当該のidカラムのデータ型を超えた値を渡してしまったのでエラーになった。
ようはexistsでルールはもちろん裏でSQLを実行しており、その時に「引数で渡された値がカラムの値格納範囲越えてるからエラーね。」と訴えかけてきていた。

よく見たら当該のidはマイグレーションでtinyIncrementsが指定されていた。
このとき自分は「tinyIncrementsならインクリメントだしUNSIGNEDだから最大値255か〜、ってことはidの値を255渡したときはバリデーションエラーで、256渡したときはこのSQLのエラーが返るんだろうな。それで裏付け取れるわ。」って思ってた。甘かった。知らなかったんです。PostgreSQLがTINYINTとUNSIGNEDが無いことを。当然、256をPOSTしてもSQLのエラーではなくバリデーションエラーが返る。またもパニック。

https://qiita.com/miriwo/items/0a56612a3ef63fd42d41

ちょっと調べたらPostgreSQLはTINYINTとUNSIGNEDが無いこと発覚、laravelは頭が良いのでマイグレーションでtinyIncrementsって指定されててもDBのクライアントを判断してSMALLINTでカラムを作ってくれるらしい。
SMALLINTの最大値である32767をIDとしてPOSTしたらバリデーションエラーになり、32768をIDとしてPOSTしたらSQLのエラーが返ってきたので裏付けが取れた。

Q.E.D

これで今夜はスッキリして眠れそう。
Teams有効活用！予約メッセージを設定する方法！Workatoでは定期実行が可能

# こんな人に参考にしてほしい
- ### いつも同じメッセージを送信してる
###
- ### 定刻メッセージを自動化したい
###
- ### Teamsをもっと活用したい！
###

Teamsの予約メッセージを、設定する方法を紹介します。
「決めた日時」に「入力した文章」が送信されます。

iPaaS製品であるWorkatoも、Teamsのような予約メッセージの送信ができます。Workatoの良い点があるので、合わせて紹介させて頂きます。

# Teamsの予約メッセージを設定する方法

メッセージを送りたいチャットを、選択してから
以下の手順で設定ができます。
 
- 送信ボタンを右クリック
- 日時選択画面が表示 (1週間までが予約可能)
- 文章入力して送信ボタン
- 予約メッセージの設定が完了

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570089/0770b191-77c1-7dc4-71e3-af5ec87927bb.png)

これで「決めた日時」に「入力した文章」が送信されます。
予約メッセージは、1つずつ作成していきます。

なので、例えば **「毎週平日の午前8時にメッセージ送信したい。」**
といった場合は、5日分の設定をする必要があります。
また、1週間以上先は選択できないので、翌日も設定しなくてはいけません。

そこで、Workatoを使用すると、
 **1回の設定で「毎週平日の午前8時にメッセージ送信」** が、できるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570089/edb95f3e-b9ea-e97a-9c64-c8263f12c1d0.png)

Workatoはローコードで開発できるiPaaS製品です。
条件分岐や順次処理を加えることで、
以下のような状況に合わせてカスタマイズができます。
- **複数人へ送信する**
- **非稼働日は送信しない**
- **送り先や曜日で、文章を変える**

今回は「毎週平日の午前8時にメッセージ送信」を行う、Workatoの簡単なレシピを紹介します。

# WorkatoでTeamsメッセージ定期実行
WorkatoとTeamsを、連携させるために **Workbotの設定** をします。
**(設定方法は下部で、別記事を紹介しています。)**

Workatoのレシピには、以下3つを設定します。


**1. 毎週平日の午前8時に起動**
**2. 送りたいチャット(ユーザー)を取得**
**3. メッセージを送信**


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570089/306d461e-79fe-92d0-2ee2-f7010750650a.png)

この3つを設定をするだけで、Workatoでメッセージ定期実行が可能となります。

### 1.毎週平日の午前8時に起動
スケジュールで定期実行を行っています。トリガー条件は「毎週平日の午前8時」なので、各項目を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570089/11463b61-dbc0-451b-8eb3-0d921785e749.png)

### 2.送りたいチャット(ユーザー)を取得
送りたいチャット(ユーザー)を取得するために、Microsoftアカウントのユーザーのログイン名を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570089/8c0bee86-da04-5837-bf75-e64899329274.png)

### 3.メッセージを送信
最後に送る処理です。前工程で取得した、送りたいチャット(ユーザー)の情報を設定して、メッセージを入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570089/59b8f415-1bc9-2aff-2cd7-96404a3bc949.png)

これで **「毎週平日の午前8時にメッセージ送信」** という定期実行が完成です。

TeamsとWorkatoを連携させるには **Workato for Teams** というワークボットを設定する必要があります。

 **Workato for Teams** は簡単に設定することが出来ます。
 別記事で紹介しているので合わせて参考にしてみてください。
[→Workbot for Microsoft Teams の設定から簡単なアクションまで実行してみた](https://qiita.com/ueno_bvt/items/5d8ee9f5278a5c65eb69)

# 終わりに
Workatoはローコードで開発できるiPaaS製品です。ですが、条件分岐や順次処理などの基本的な知識は必要になります。メッセージをカスタマイズできれば、**さらに業務に応じたメッセージを送信することができます。** 
弊社では他にも記事を紹介しているので参考にしてみてください。
[→会社概要と記事一覧はこちら](https://qiita.com/organizations/bstylevt/profile)
【langchain】RAGの目視評価を軽めにしたいときのスクリプト

# 概要
100個以下くらいの想定質問のRAG出力を取得して、目視評価をするためのスクリプトの覚書です。

# 環境
langchainのバージョンは0.0.331です。最近0.1が登場したので、もうじきlegacyになるかもしれません。

v0.1対応のチュートリアルは以下にあります。
https://api.python.langchain.com/en/latest/chains/langchain.chains.retrieval_qa.base.RetrievalQA.html#langchain.chains.retrieval_qa.base.RetrievalQA

# 実装
## VectorStoreRetrieverの作成

```Python
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import FAISS
from langchain.vectorstores.utils import DistanceStrategy

embedding = HuggingFaceEmbeddings(model_name = "oshizo/sbert-jsnli-luke-japanese-base-lite")
vectorstore = FAISS.from_texts(
    ["こんにちは","こんばんは","さようなら"]
    , embedding
)
retriever = vectorstore.as_retriever()
retriever.get_relevant_documents("こんにちは")
```

## RetrievalQA chainの作成

```Python
from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA
import dotenv
dotenv.load_dotenv()

retrievalQA = RetrievalQA.from_llm(llm=ChatOpenAI(model="gpt-4-1106-preview", temperature=0), retriever=retriever, return_source_documents=True)
retrievalQA.invoke("こんにちは")
```

## 出力の実行と保存

```Python
import pandas as pd
output_path = "output.xlsx"
questions = ["こんにちはと意味の近い文章は？","さようならと意味の近い文章は?"]
rows = []
for q in questions:
    res = retrievalQA.invoke(q)
    print(res)
    row = {
        "question": q,
        "result": res["result"]
    }

    for i, doc in enumerate(res["source_documents"]):    
        row[f"source_document_{i}"]=doc.dict()
    rows.append(row)
    pd.DataFrame(rows).to_excel(output_path, index=False)
```
PostgreSQLにTINYINTは存在しない

## 概要

今までLaravel + MySQLを主に使ってきて最近Laravel + PosgreSQLを使っている。どうやらPosgreSQLにTINYINT型が存在しないらしく勝手に衝撃を受けたのでまとめておく。

## PostgreSQLにTINYINTは存在しない

https://www.postgresql.jp/docs/9.0/datatype-numeric.html

上記をみて驚いた。MySQLのようにTINYINTがあると思ってた。最小がSMALLINTで±32767の間の数値が格納可能らしい。
更にいうとUNSIGNED（符号なし）もないらしい。

https://note.com/ririse/n/n52ece3a07739

## PostgraSQL使ってるときにマイグレーションでtinyIntとかを指定したらどうなるの？

SMALLINTに勝手に変換されてカラム定義される。
もちろんいくらマイグレーション側でunsignedTinyIntとか指定しても符号ありのSMALLINTのカラムができる。
なのでマイグレーションだけをみて「unsignedTinyIntだから最大値255だな」とか思わない方がいい。なれないうちはちゃんとDBを見に行ってデータ型を確認したほうがいい。

参考までにMySQLの整数型の値範囲の参考リンクを載せておく。

https://www.javadrive.jp/mysql/type/index1.html#google_vignette
AIchallenge-racingのすゝめ（進め）その２

# はじめに
<!-- 発端や概要を記載 -->
この記事は、[前回](https://qiita.com/Arata-iASL/items/4b03772348dca4f7ef89)からの続きとなっております。

前回は、lookaheadgainとspeedを調整しましたが、第一コーナでコースアウトしてしまう状況は解決できませんでした。スピード制限をすると直線でも遅くなってしまう問題もありました。
今回は、これらを同時に解決する方法を紹介します。
tanaka3さんの記事を参考にしております。
[AI Challeenge 入門ガイド(1)](https://zenn.dev/ttanaka3/articles/3dc507df539985)
# 目次
<!-- タイトルとアンカー名を編集 -->
1. [Mapを編集する](#Mapを編集する)
1. [次回に向けて](#次回に向けて)
1. [参考文献](#参考文献)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# Mapを編集する
今利用するTier4 VectorMapBuilderはtier4のアカウントに登録する必要があるので、[こちら](https://account.tier4.jp/login)に登録しましょう。（無料）

登録ができたら、実際にツールを使わせもらいましょう。
[Vector Map Builder](https://tools.tier4.jp/vector_map_builder_ll2/)

ますは、Fileタブから、"import PCD"と"Import OSM"でマップを読み込みます。
マップは、/aichallenge_submit/aichalllenge_submit_launch/Map
にあります。読み込むと下図のような画面になります。
<br>
![lane選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3673708/195c439b-e5cd-00f1-08eb-bb8d5ace8735.png)

青色のラインが走行レーンとなっております。
レーンにカーソルを合わせると、赤色で表示され、クリックすると黄色で表示されると思います。また、右下のメニューに注目すると、speed limitという項目があります。自動運転中は、この速度を基準に走行します。
　次に、黒色のmap画面右上に注目すると、"Create Centerline"というボタンがあります。そのボタンを押してみると、中央線が表示されます。実は、今まで走行していたラインは、この線を基準にして作られたルートでした。<br>
 ![センターライン表示.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3673708/9d278151-750f-0198-6989-7b231d65a4ff.png)

つまり、私達が直面していた経路問題は、このセンターラインを編集し、理想的なコーナリングラインをつくれば解決できるのです。
　センターラインを拡大していくと、小さな点があると思います。私は、この点を選択し、ひとつひとつずらしていことで、センターラインを調整しました。また、shiftを押しながら、ドラッグで範囲選択、shiftを押しながら、点をクリックすることで複数選択ができます。
下図は、私のつくった経路です。<br>
![Screenshot from 2024-01-11 21-50-40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3673708/f9c04023-5b09-9b17-a2a6-d3d481f02ffd.png)

少し雑ですが、このくらい大雑把でも問題ありません。（私は、無事走行できました）そして、ついでに速度制限を30kmにしておきました。

Mapの編集が完了したら、Fileタブから"export osm"でファイルをダウンロードできますが、ファイル名に注意してください。初期設定で実行されるファイルは、"lanelet2_map.osm"という名前のファイルなので、自分のmapで実行したいときは、元々あったosmファイルの名前を変更しておいた状態で、自分のmapファイルを"lanelet2_map.osm"に変えましょう。
(例)
"lanelet2_map.osm" --> "tmp_lanelet2_map.osm"(元のファイル)
"lanelet2_map.osm"(自分が編集したファイル)

実行する際は、再buildすることを忘れないでください。

Mapファイルの編集だけでも、かなり効果が出ると思います。
自分だけのルートを探してみましょう。

# 次回に向けて
今までは、とにかくパラメータやmapをいじりましたが、その情報はどのように利用されているでしょうか。ここらで、Autowareの構造をみていこうと考えました。<br>
次回は、Autowareを探っていく回にしたいと思います。

# 参考文献
- [AI Challeenge 入門ガイド(1)](https://zenn.dev/ttanaka3/articles/3dc507df539985)
Oracle データポンプの使い方の一例

# 前提
 Windows 10

# ディレクトリ作成する
- OracleDBが入っているサーバ上のディレクトリのみ設定可能
（ネットワークドライブなどは指定不可）
- sysでログインする必要あり
~~~
CREATE OR REPLACE DIRECTORY EXPDB_DIR AS 'C:\DATADUMP';
CREATE OR REPLACE DIRECTORY IMPDB_DIR AS 'C:\DATADUMP';
~~~

# ディレクトリを使用したいユーザーに権限を付与
~~~
GRANT READ,WRITE ON DIRECTORY EXPDB_DIR TO SYSTEM;
~~~

# エクスポートする
~~~
EXPDP SYSTEM/PASS DERECTORY=EXPDB_DIR SCHEMAS=TEST DUMPFILE=TEST.DMP LOGFILE=TEST.LOG
~~~

# インポートする
同じスキーマ名でインポートするときは、
スキーマ（ユーザー）を先に作成しておく必要なし
~~~
IMPDP SYSTEM/PASS DERECTORY=IMPDB_DIR SCHEMAS=TEST DUMPFILE=TEST.DMP LOGFILE=TEST.LOG
~~~
【AWS】【IAM】Resource 要素が空欄であるアクションについて


## はじめに
「最小特権アクセス許可を適用する」ための最もシンプルなやり方としては、
IAM ポリシーの「Resource 句」で対象リソースのArnを指定することだと思います。

ただ、[AWSリファレンス](https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html)内の「リソースタイプ列」が空欄の場合は、
「Resource句」での制御ができるのでしょうか。

本記事では「リソースタイプ列」が空欄となっているアクションに対して、
リソース句での制御可否を確認した記事となります。

## 結論
リソースタイプが空欄のアクションに対しては Resource 要素で全てのリソースを指定する必要があります。
例としてリソースタイプが空欄のアクションである「s3:ListAllMyBuckets」に対しては、
以下のように「"Resource": "\*"」を指定する必要がありました。

```json:IAMポリシー例
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": "s3:ListAllMyBuckets",
      "Resource": "*"
    }
```

## 確認方法
> ■AWS 公式ページ[(Amazon S3 のアクション、リソース、条件キー - Amazon S3 で定義されるアクション)](https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/list_amazons3.html#amazons3-actions-as-permissions)より
[アクション] テーブルの [リソースタイプ] 列は、各アクションがリソースレベルの許可をサポートしているかどうかを示します。この列に値がない場合は、ポリシーステートメントの Resource 要素で、ポリシーが適用されるすべてのリソース (「\*」) を指定する必要があります。

上記の通り、公式ページに明記が存在していました。
また、リソースタイプ列が空欄なアクションをResource 句で制御しようとしましたが、
そのアクションの実行は拒否されました。
アクションがサポートしているリソースタイプの指定方法ではないため、
許可されない模様です。
　※許可されない＝拒否ではなく、Allow 設定とならず暗黙的な拒否となる
　※暗黙的な拒否については後述

## Resource 要素が空欄/記載有アクションを1つのポリシーに設定する方法

Resource 句で制御可能な形式が多種存在しているアクションは、
対応している Resource 句ごとにStatement を複数指定する必要があります。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:ListAllMyBuckets", "s3:GetBucketLocation"],
      "Resource": "arn:aws:s3:::*"
    },
    {
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::BUCKET-NAME",
      "Condition": {
        "StringLike": { "s3:prefix": ["", "home/", "home/${aws:username}/"] }
      }
    },
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::BUCKET-NAME/home/${aws:username}",
        "arn:aws:s3:::BUCKET-NAME/home/${aws:username}/*"
      ]
    }
  ]
}
```
`"Resource": "arn:aws:s3:::*"`：Resource句で制御しているようにみえるが「"Resource":"*"」と同義
※引用元：[IAM JSON ポリシー要素 Statement](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_statement.html)

## 暗黙的な拒否について

IAM ポリシー内で明示的に Deny も Allow も記載していない状態を指します。
IAM ポリシーは、デフォルトでアクセスが拒否される仕様のため、
アクションを実行するには明示的に許可を記載する必要があります。

### 明示的な拒否と暗黙的な拒否と明示的な許可の優先順位

IAM ポリシーでは以下の順番で設定に優先順位があります。
明示的な拒否と明示的な許可をそれぞれ同じアクションを対象に設定していた場合、
明示的な拒否が優先され、アクションが実行できないです。

1. 明示的な拒否("Effect": "Deny")
2. 明示的な許可("Effect": "Allow")
3. 暗黙的な拒否(記載なし)

## 終わりに
IAM ポリシー制御で悩んでいる人の助けになれば幸いです。

## 参考

・[ポリシーの評価論理 - 明示的な拒否と暗黙的な拒否の違い](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#AccessPolicyLanguage_Interplay)
・[IAM JSON ポリシー要素 Statement](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_statement.html)
・[(Amazon S3 のアクション、リソース、条件キー - Amazon S3 で定義されるアクション)](https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/list_amazons3.html#amazons3-actions-as-permissions)
AZ-500: Microsoft Azure セキュリティ テクノロジ を取得しました

# 初めに
Azure Security Engineer Associate(https://learn.microsoft.com/ja-jp/credentials/certifications/exams/az-500/) を受験して合格しました。
これから試験を受験される方の参考になれば幸いです。

# プロフィール
- ITエンジニア歴：8年
- AWS歴：3年
- Azure歴：1年未満
- 取得資格
    - IPA：SA, DB, SC
    - AWS：DVA, SAA, SCS
    - Azure：なし

Azureの資格試験は今回が初挑戦でした。

# 受験のきっかけ
今年度から業務変更に伴い、Azureを触ることになりました。わからないなりに業務をこなしていましたが、一度しっかり勉強しようということで受験しました。
システム開発に関わりそうなAZ-204とAZ-500のどちらかを受けようと思っていたものの、AZ-204だと試験更新のタイミングと被ってしまうことからAZ-500にしました（Azureに限らず、クラウドの試験は試験要綱の変更が時々あるので、受験時には注意が必要ですね）。

# 学習方法
インターネット上のコンテンツを中心に主に２つのソリューションで学習しました。

1. Udemy
2. Microsoft 無料の練習用評価

## 1. Udemy
Udemyは2つのコンテンツをセールで購入して学習しました。

- Azure Security: AZ-500 https://www.udemy.com/course/azure-security-associate-az-500/
    - AZ-500のコンテンツとしては時間が短く、学習のハードルが低め
    - 短い分、浅い知識にとどまっており、少し物足りなかったです
	- 日本語字幕無し
- AZ-500: Microsoft Azure Security Engineer Practice Test 2023　https://www.udemy.com/course/az-500-microsoft-azure-security-engineer-practice-questions/
    - 模試が6セットあり、ボリュームは多め
	- 実際の試験に即した問題の出し方をしているので、試験対策としては良かったです
	- 解説が物足りない問題やサービス名が古いままの問題があるので、知識不足の状態で挑むと辛い(涙)

## 2. Microsoft 無料の練習用評価
- Microsoft 無料の練習用評価　https://learn.microsoft.com/ja-jp/credentials/certifications/exams/az-500/practice/assessment?assessmentId=57&assessment-type=practice
    - Microsoftが公式で出している模試
	- 1問ごとに解説出せる上に間違いの選択肢の解説もあるため非常にわかりやすい
	- あまり使いませんでしたが、公式のラーニングパスも合わせて使うとよかったかもです。

これらのコンテンツを使って、2ヶ月ほど学習したのち、テストセンターで受験しました。

# 試験について
試験は3つのセクションで構成されていました。
1. ケーススタディ：約10問
1. 選択問題：約40問
1. 選択問題（一度回答すると戻りできない1連の問題）：1問

MS Learnは使えたものの、ページ左にあるリンクが表示されなかったり、画面倍率が大きく見づらいなど、使いづらかったです。
いろいろ検索していたら結構時間がかかり、試験時間残り2分とぎりぎりでした。

# 結果
結果終了後、すぐに画面表示。
842点で無事合格でした :clap: 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296651/49f9e2c7-19e2-7b5b-4280-ca7736c9dac4.png)

ネットワークのセキュリティ保護が低いのがよろしくないけど、コンピューティング周りのセキュリティがとれているからヨシ！（よくない）


# 試験を受け終わって
AWSの経験があるからAzureにそこまで苦労せずに済むかなと思っていましたが、なかなか苦戦しました。
特に Azure は Microsoft Entra ID(旧Azure Active Directory) が根底にあり、その概念の違いに苦しみました。今でも「Microsoft Entra ID に アプリケーションを登録」の概念が理解できずにいます。
ただ、Azureでサービスを構築するためのセキュリティについて理解は深まりましたので、受験してよかったです。

Azureの勉強で疲れたので、次はAWSの試験に挑戦予定！
技術提案：RGBD画像カメラを利用したRGB画像での物体検出の学習

機械学習のアイディアは、それを実装するタイミングがないときに思いつくものである。
特許にするほどの新規性もなく、隠匿しておくことで得られるメリットもない状況にある。

学習用データセットの重要性は、Data-Centric AI という名称でも知られるようになってきている。
それでも、楽して必要な条件を達成するための手法は、まだ発展途上であると考えている。
この文章では、RGBD画像が取得できるカメラを用いて、物体検出を楽にする学習画像を収集することを提案する。
（既に、どこかで誰かが日本語で書いているにちがいないが。）

## 物体検出の学習用画像の課題
- ２次元画像としての学習であるので、視野の方向が少し変わっただけで、検出できなくなることがある。
- 異なる多様な環境での画像収集が難しい
- bbox(= bounding box)内に背景が占める比率が高い場合、背景部分の特徴を学習してしまう危険
  - 意図せずして、背景を学習してしまう危険

## 提案
RGBD画像を取得できるToFカメラを利用した物体検出の学習

- ToFカメラを利用して対象物のRGBD画像を撮影する。
- その画像RGBD画像から、対象物よりも背後にある領域の透過


## RGBDカメラの条件
- RGBのpixelとDepth(深度）のpixelとが対応がつくこと。なるべくなら、視野角が同じで、RGBカメラの位置とDepthカメラの位置が十分に近いのがよい。
- Depth(深度）の算出では、欠損値を生じやすい
- 欠損値の種類
    - 近距離すぎて算出できない。
    - 遠距離すぎて算出できない。
    - 受光する信号が弱すぎて算出できない（例：ToF)
    - 対応点がとれないので視差を算出できず、Depthが算出できない(例: ステレオ計測）

- なるべくなら、欠損値が出にくいDepthセンサを用いる。
- depthの測定に際して、RGB画像を壊さないこと。
    - structured light（光構造化法)は、パターン光をRGBの可視領域に光を照射してしまうので適さない。

- エンドユーザーによるキャリブレーションの必要性が少ないこと
    - だれにでも楽に使ってもらうためには、撮影の際のキャリブレーションの必要性が少ないこと。
    - 温度によって特性がずれてしまう、ちょっとしたショックで特性がずれてしまうものは、運用時の精度を出しにくい。

- RGBD画像データを取得するためのインタフェースが、PCで利用可能な標準的なインタフェースであること

## 候補となるセンサの例
- [市販ＴoＦカメラについて調査中(2023年版）](https://qiita.com/nonbiri15/items/5fdb9962bbdc76274d90)の記事を参考にしてください。
    - XVSIO社の製品、HMS社の製品では、RGBカメラとToFカメラの画像との画角が近いものになっています。
- [ステレオカメラ調査(2023年版）](https://qiita.com/drafts/4bd2fab5687ea4ebc416/edit)
    - StereoLabs のZED2なども深層学習でDepthを計算するので、従来手法では欠損点になっていた部分に値が算出できる。
Rustでpythonのように文字列をスライスしよう

# Rustでpythonのように文字列をスライスしたい

## Python使いがRustでハマる文字列スライス
RustにはPythonのように
```python
data = "これはテストです。"
print(data[0:2])
# "これ"が出力される
```
便利な日本語を直感的に文字列スライスするような関数は用意されていません。
最初、この仕様でハマっていました。やり方も一度StringをChar型に変換してfor文で回すという面倒なやり方でやっていました。

## トレイトとの出会い
トレイトの使い方がよく分からず、関数とStructで逃げていましたが[UdemyのRustコース(英語)](https://www.udemy.com/course/rustaceans/learn/lecture/19602324#overview)をtrait部分を受講・写経しているときに天啓が降りてきて、Rustの文字列はいつも同じやり方をしています。

## 具体的なコードは以下の様な感じ
```rust

//　pythonライクなトレイト（属性・性質）を定義
trait PythonLikeSlice {
    fn slice(&self,from:usize,to:usize) -> String;
}

// 次にString型に直にPythonLikeSliceを実装
impl PythonLikeSlice for String {
    // pythonで言うdata[0..5]に近いやり方を定義
    fn slice(&self,from:usize,to:usize) -> String {
    
        let mut slice_string = String::from("");
    
        for (i, c )in self.chars().enumerate(){
            if from <= i && i < to {
                slice_string.push(c);
            }
        }

        slice_string
    }
}

fn main(){
    // Pythonライクなスライスができる。
    let original_string = String::from("test_string");
    let changed_string = original_string.slice(0, 4);

    println!("{}",changed_string);
    // "test"が出力されます。

}
```

いつもこのやり方をやっています。
自分用の備忘録用に残しておきます。
wagtailで管理画面ページの表示を変える

デフォルでは、管理画面ページの表示はHomeのなっています。
![名称未設ああ定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332453/85e6d847-7cbb-bd6a-7ee4-d3339ccd6815.png)
このHomeの部分の表示を変えたいと思う方もいるのでは無いでしょうか？

こうすると、簡単にできます。

homeアプリケーションのmodels.pyを編集します。

```python:models.py

from django.db import models

from wagtail.models import Page


class HomePage(Page):

    def get_admin_display_title(self):
        return "オリジナル"

```
たったこれだけで変更できますよ
![名称未っっっっw設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332453/9a3395df-3cbc-6b52-1967-392e15f5cf71.png)
paizaラーニング解答: 標準入力サンプル問題セット[Ruby]

# 標準入力サンプル問題セット
https://paiza.jp/works/mondai/stdin/problem_index?language_uid=ruby
 
## 1つのデータの入力
```ruby
s = gets.chomp
puts s
```
sはstring（文字列）の略で、とりあえず文字列を受け取るときによく使います。
## 1行のデータの入力
```ruby
s = gets.chomp
puts s
```


## 3行のデータの入力
```ruby
3.times do
    s = gets.chomp
    puts s
end
```


## N行のデータの入力
```ruby
n = gets.to_i
n.times do
    s = gets.chomp
    puts s
end
```
nはnumber（番号）の略で、とりあえず数字を受け取るときによく使います。

## 3つのデータの入力
```ruby
a = gets.chomp.split
puts a
```
aはarray（配列）の略で、とりあえず配列を受け取るときによく使います。
splitで半角スペース毎に分け、配列に代入しています。

## N個のデータの入力
```ruby
n = gets.to_i
a = gets.chomp.split
puts a
```
nは使わなくてもOK。

## カンマ区切りの3つのデータの入力
```ruby
a = gets.chomp.split(',')
puts a
```


## カンマ区切りのN個のデータの入力
```ruby
n = gets.to_i
a = gets.chomp.split(',')
puts a
```
WEB基本用語について

## はじめに
記事をご覧いただきありがとうございます。
今回は『プロになるためのWeb技術入門』――なぜ，あなたはWebシステムを開発できないのかを読んで、下記のWEB基本用語について解説していきます。
　
- ステートフル
- ステートレス
- リクエスト
- レスポンス
- クッキー
- プロトコル
- ポート番号

## ステートレス/ステートフル
簡潔に言うと・・・
ステートレス→以前のやりとりを覚えていない
ステートフル→以前のやりとりを覚えている

例)百貨店の服屋さん
ステートレスは、以前来たお客さんの情報を覚えていない

![スクリーンショット 2024-01-10 21.20.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1003708/bdf570f5-f9af-2a9a-16fa-dd9eb231c834.png)


ステートフルは以前来たお客さんの情報を覚えている
情報を記憶しているため、やりとりがスムーズですね。

![スクリーンショット 2024-01-10 21.10.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1003708/3d05057c-88a8-525d-f987-acee1ec94edb.png)

FTP(File Transfer Protocol)はクライアントとサーバー間で、手順を踏んだ対話を行いながらファイル転送を行うため、ステートフル・プロトコルと言われています。
一方でHTTPは1回のリクエストだけで用が済むので、FTPのような丁寧な対話は不要です。
そのためHTTPは情報を保持しないプロトコル、ステートレス・プロトコルと言われています。

## リクエスト/レスポンス
私たちは、普段サイトを見るためにはWebサーバに「このサイトを表示して」など要求を出します。クライアントからサーバに出す要求のことをリクエストと言います。
要求を出すとサーバーから応答が返ってきて、目的のサイトが表示されます。サーバーからクライアントに対する応答をレスポンスと言います。

![スクリーンショット 2024-01-10 21.49.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1003708/8eefee46-d0a4-d0a2-aad2-124ea031490b.png)

## Cookie
データをブラウザに保存する仕組みのことがCookieです。
HTTPはステートレス・プロトコルでしたが、Cookieを使用してブラウザに情報を保存することで、情報を保持することができるようになります。

Cookieに保存される情報としては、利用者の識別や属性に関する情報・最後にサイトを訪問した日時・利用者のIDなどです。
ショッピングカートに商品を入れてログアウトしても再度ログイン時にはカートの中の商品が消えることはありません。これはカートの中の商品がCookieに保存されているためです。

Cookieはとても便利な機能ですが、その反面デメリットもあります。Cookieはブラウザから簡単に閲覧ができるため携帯を落としたりするとサイトのCookieが閲覧されて、なりすましなど悪用される可能性があります。

## プロトコル
プロトコルは、WebクライアントとWebサーバーがやりとりする際の「取り決め」「決まり事」です。
私たちが普段会話する際も、共通の言語がないと会話できません。同じように、コンピュータも共通の「決まり事」がないと通信ができなくなってしまうため、プロトコルが必要となります。
下記に主なプロトコルを記載しています。

|プロトコル|用途|
|:-----:|:-:|
|IP|インターネットを通信する際の決まり事|
|FTP|ファイルの受け渡しをする際の決まり事|
|HTTP|Webサイトを閲覧する際の決まり事|
|SMTP|メール送信する際の決まり事|
|POP|メール受信する際の決まり事|

## ポート番号
Webページを閲覧したり、DBとやりとりするなどアプリケーションと会話するための窓口のことです。
例えばHPを閲覧するなら80番ポート、メール送信をするなら587番ポートを使用するなど使用するポート番号が決まっています。

![スクリーンショット 2024-01-11 21.28.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1003708/b5bbe586-9992-4113-9f43-63cb6e19ebbe.png)

また、ポート番号は番号の範囲によって、使用目的が異なります。

- **0〜1023 ウェルノウンポート番号**
代表的なプロトコルで使用されています。

|ポート番号|プロトコル|
|:-----:|:-----:|
|20/21|FTP|
|25|SMTP|
|80|HTTP|
|110|POP3|
|443|HTTPS|

- **1024〜49151 登録済みポート番号**
よく使うアプリケーションに使用されています。

|ポート番号|サービス|
|:-----:|:-----:|
|1812|Radius（ラディウス）|
|443|Microsoft SQL Server|

- **49152〜65535 ダイナミック/プライベートポート番号**
サーバー側と通信する際に、クライアント側が一時的に使用します。

## さいごに
『プロになるためのWeb技術入門』を読むことで、HPはどうやって見ることができるのかといった基礎となる部分から、HPのセキュリティ部分までWEBの基礎となる部分を学習することができました。
なかなかボリュームはありますが、WEB技術を学ぶ第一歩として読んでおくとよりスムーズに学習が進むと思います。

## 参考文献
- プロになるためのWeb技術入門 著者：小森祐介
- ポート番号とは？｜図解を使って3分でわかりやすく解説

https://www.youtube.com/watch?v=ruIRm5O5j14
Google Cloudアップデート (12/28/2023-1/3/2024)

### Migrate to VMs: [Dec 27, 2023](https://cloud.google.com/migrate/virtual-machines/docs/5.0/resources/release-notes#December_27_2023)
- 1st, 2nd ,3rd genへのマイグレ対応がGAになったよ！

### Cloud Spanner: [Dec 27, 2023](https://cloud.google.com/spanner/docs/release-notes#December_27_2023)
- クライアントライブラリ更新

### Cloud Asset Inventory: [Dec 26, 2023](https://cloud.google.com/asset-inventory/docs/release-notes#December_26_2023)
- 複数のリソースタイプ追加

### Cloud Bigtable: [Dec 28, 2023](https://cloud.google.com/bigtable/docs/release-notes#December_28_2023)
- [DynamoDBユーザ向けのドキュメント](https://cloud.google.com/bigtable/docs/dynamodb-users)が追加されたよ！

### Vertex AI: [Dec 27, 2023](https://cloud.google.com/vertex-ai/docs/release-notes#December_27_2023)
- Vertex AI Prediction:
  - カスタムモデルのサービングがリアルタイムの利用状況をもとにクォータが処理されるようになったよ
    - これまではGPU等の利用状況をもとにしていたので利用量の最大が利用されていたので、クォータに対する消費が少なくなるけど、オートスケールができなくなる可能性があるので注意

### BigQuery: [Jan 2, 2024](https://cloud.google.com/bigquery/docs/release-notes#January_02_2024)
- Analytics Hubで提供するデータがCMEKにGA対応したよ！

### Cloud Firestore: [Jan 2, 2024](https://cloud.google.com/datastore/docs/release-notes#January_02_2024)
- europe-west1, me-central2で使えるようになったよ！

### Batch: [Jan 2, 2024](https://cloud.google.com/batch/docs/release-notes#January_02_2024)
- シングルゾーンとマルチゾーンで並行で処理できるジョブ数が変わるようになたよ！
  - 今はシングル2,000, マルチ4,000

### ディスクレーマ
- アップデートの内容はあくまでも個人の理解していることを書いています。正しい内容はリリースノート等を確認下さい。
- リリース内容できるだけ拾うようにしているのですが、抜けていそうなリリースノートは追加するのでぜひ教えて下さい！(一覧[ここ](https://qiita.com/kenzkenz/items/ac18a359b803dbb6b490)で更新してます。)
【備忘録】Supabaseでcreated_atを日本時間にする

# Supabaseを使ってcreated_atを日本時間にする
### きかっけ
prismaを使ってschemaでcreated_atしたら日本時間じゃなかった
### したこと
timezoneをAsia/Tokyoに変更
```sql
-- SQL Editorで
alter database postgres
set timezone to 'Asia/Tokyo';
```
Supabaseもしくはschemaで変更
### Supabase
![スクリーンショット 2024-01-11 204759.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194285/050b1932-28fa-ba30-a010-f20512b8c660.png)
DefaultValueをCURRENT_TIMESTAP
### prisma
```:schema.prisma
model ◯◯◯{
// それぞれのカラム
  createAt DateTime  @default(now()) @map("created_at") @db.Timestamptz()
}
```
```terminal:terminal
npx prisma migrate dev
```
### 参考

https://qiita.com/7mpy/items/bedd102355a51e93a7df

https://www.prisma.io/docs/orm/reference/prisma-schema-reference
AWSのマネジメントコンソールでSession Managerで仮想サーバーにログインするためのIAMロールを作成する

こんにちは。
本日は、仮想サーバーにSystems Managerのセッションマネージャーでログインするために必要なIAMロールを作成する手順を記載します。

# セッションマネージャーで仮想サーバーにログインするための準備

仮想サーバーにセッションマネージャーでログインするためには、以下が必要です。

1. 仮想サーバーを立ち上げるためのAmazon Machine Image（AMI）で、
Systems ManagerのSSM Agentが含まれるAMIを用意している
2. <b>仮想サーバーでセッションマネージャーを使うために必要な、
IAMロールを作成している
3. 仮想サーバーから、
セッションマネージャーのエンドポイントへのアクセス経路を用意している
4. 仮想サーバーに設定するセキュリティグループで、
0.0.0.0/0に対するhttpsのアウトバウンドの許可ルールを含むセキュリティグループを
用意している

<br>
ここでは、セッションマネージャーで必要なIAMロールを作成する手順を記載します。





# AWSのマネジメントコンソールでセッションマネージャーで仮想サーバーにログインするためのIAMロールを作成する手順

## 1. 以下のリンクにアクセス

以下のリンクでIAMロールを作成する画面に遷移します。

* 米国東部（バージニア北部、us-east-1）でIAMロールを作成する
[https://us-east-1.console.aws.amazon.com/iam/home?region=ap-northeast-1#/roles/create](https://us-east-1.console.aws.amazon.com/iam/home?region=ap-northeast-1#/roles/create "IAMロールを作成")<br><br>


## 2. 以下の値を入力/設定

遷移した画面で、IAMロールを作成します。
IAMロールの作成は、以下の3ステップあります。

1. <b>信頼されたエンティティを選択
2. <b>許可を追加
3. <b>名前、確認、および作成

### Step 1. 信頼されたエンティティを選択

「<b>信頼されたエンティティタイプ</b>」で、「<b>AWSのサービス</b>」が選択されています。
ここはそのままでOKです。

次に、「<b>サービスまたはユースケース</b>」欄をクリックします。

![IAMRole-20240108-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622796/19b6e82c-52b2-6999-3514-522b9f593e80.png)

<br>

「<b>サービスまたはユースケース</b>」欄をクリックすると、複数のサービスが表示されます。
ここで、「<b>EC2</b>」を選択します。

![IAMRole-20240108-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622796/ef9c6c8d-39a7-175f-248e-72daa26bc420.png)

<br>

「<b>サービスまたはユースケース</b>」で「<b>EC2</b>」を選択すると、さらにいくつかのユースケースが表示されます。
ここで、「<b>EC2 Role for AWS Systems Manager</b>」を選択して、「<b>次へ</b>」を押下します。


![IAMRole-20240108-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622796/fa966001-a543-c133-3ad3-afaff98b3467.png)



### Step 2. 許可を追加

前の画面で設定したユースケースに必要な権限が含まれるポリシーで、以下があらかじめ設定されます。

* <b>AmazonSSMManagedInstanceCore 

ここではそのまま「次へ」を押下します。

![IAMRole-20240108-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622796/8924ed18-4fd0-4f74-9750-50fe35297b8c.png)

:::note warn
ここでは、<b>セッションマネージャーの設定が行われていない状態</b>で最小限必要な権限を設定しています。
セッションマネージャーの設定で、S3にログを保存する設定などを既に実施済である場合、その設定に応じた権限が追加で必要になります。
:::

### Step 3. 名前、確認、および作成

設定内容の確認画面が出ます。
この画面で、「<b>ロール名</b>」を入力します。
ここでは、ロール名を「<b>EC2RoleForSSM</b>」と入力しています。

次に、「<b>ロールを作成</b>」を押下します。


![IAMRole-20240108-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622796/f2d1c382-c350-f42a-20a1-49e602cffd9d.png)

<br>

そうすると、画面が遷移してIAMロールの一覧画面が表示されます。
この画面の上部に、「<b>ロール EC2RoleForSSMが作成されました</b>」と表示されます。

![IAMRole-20240108-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622796/d2210e64-b60f-440a-9ca6-fac59dc3ce07.png)



<br>

セッションマネージャーで仮想サーバーにログインするための最小限の権限を持つIAMロールの作成は以上で終わりです。
どなたかのお役に立てれば幸いです。
Lambda@EdgeをNode.js 14から18に上げるのに苦労したメモ

# 概要
サポート終了の関係で既存のNode.js 14のLambda@Edge関数をNode.js 18にあげるにあたってランタイムを変えるだけでは上手くいかない場合があったので備忘します。

# AWS SDKが読み込めない
`const aws = require("aws-sdk");`としていた部分が`Cannot find module 'aws-sdk'`というエラーになってしまう。

原因はAWS SDK v2がNode.js 18のランタイムには同梱されなくなり、v3をインポートする記述への変更が必要になったため。
この関数ではSSMを使っていたので、
`import { SSMClient, GetParameterCommand } from "@aws-sdk/client-ssm";`
のように変更

# ES modules構文に変更
上記のためES modules構文を有効にするため、拡張子も`index.js`から`index.mjs`に変更。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/nodejs-handler.html

ハンドラーの書き方も変更する

# SDKの使い方を変更

SDKのバージョンが変わったので使い方を変える必要があった。

https://qiita.com/Yporon/items/512a8ceb9e949f95fd4d

こちらの記事を参考にさせていただきました。

# ES modulesでrequire構文を使う

AWS SDK以外のライブラリをrequire構文で読み込んでいたためそのままではエラーになってしまう。

https://stackoverflow.com/a/77047149

このライブラリでのimport構文の書き方が見つからなかったためこちらを参考にrequireで読み込むよう回避。

# 余談

https://qiita.com/t-kigi/items/0980ca292d7e046eff3a

後から気づいたがこちらの記事のようにCommonJSの構文を維持すればよかっただけかも…。
温度計を作る(STM32G071)(ILI9341)(STTS751)


温度計を作る(STM32G071)(ILI9341)(STTS751)


目的
液晶のテスト





配線

3.3V - 3.3V
SCL  - SCL
SDA  - SDA
GND  - GND


![o_cop887.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/1a814b6e-0bd0-931b-d604-3a9f74f9f492.jpeg)



```c++


//ili9341_stts751_071_1

//インクルド
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"

//センサーのアドレス
#define STTS751 0x39

//定義
char t_0001[][6] =
{
".0000", //0
".0625", //1
".1250", //2
".1875", //3
".2500", //4
".3125", //5
".3750", //6
".4375", //7
".5000", //8
".5625", //9
".6250", //10
".6875", //11
".7500", //12
".8125", //13
".8750", //14
".9375" //15
};

//設定
#define TFT_RST 54 //A1
#define TFT_DC 3
#define TFT_CS 4

//液晶の定義
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);


//初期化
void setup() {

  //シリアルの初期化
  Serial.begin(9600);
  Serial.println("ILI9341 Test!"); 

  //I2Cの初期化
  Wire.begin();

  //液晶の初期化
  tft.begin();

  //画面のクリア
  tft.fillScreen(ILI9341_BLACK);
  
}//setup


//無限ループ
void loop(void) {


  //温度の読み込み
  char s1[2] = {0,0}; //センサーの値
  char s2[2] = {0,0}; //センサーの値
  int ii=0;

  //0番目のレジスター 温度整数部
  Wire.beginTransmission(STTS751);
  Wire.write(0);
  Wire.endTransmission();
  delay(1);
  //1
  Wire.requestFrom(STTS751, 1);
  s1[0]=99;
  while(Wire.available())  {    // 要求より短いデータが来る可能性あり
    s1[ii++] = (int)Wire.read();       // 1バイトを受信
  }//while
  delay(1);

  //2番目のレジスター　温度小数部
  Wire.beginTransmission(STTS751);
  Wire.write(2);
  Wire.endTransmission();
  delay(1);
  //2
  ii=0;
  Wire.requestFrom(STTS751, 1);
  s2[0]=0xc0;
  while(Wire.available())  {    // 要求より短いデータが来る可能性あり
    s2[ii++] = (int)Wire.read();       // 1バイトを受信
  }//while


  //センサーの値を温度に変換
  //s1[0]=21;s2[0]=0x80;
  int d1 = s1[0];
  int d0001 = (s2[0]>>4)&0x0f;
  

  //温度の表示

  //クリア
  tft.fillRect( 0 ,0 , 24*5 , 24 , ILI9341_BLACK);

  //表示位置を0,0にする
  tft.setCursor(0, 0);

  //テキストの表示
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(3);
  tft.print(" ");
  tft.print(d1);
  //tft.print(".");
  tft.print(t_0001[d0001]);
  tft.print(" ");
  
  delay(1000); //1秒待つ

}//loop



```