OmniAICreator/Qiita-1.07M huggingface dataset:
責任あるAIとは？ - 公平性、信頼性、透明性を重視したAIシステム開発の原則

本記事は [生成AIセキュリティ by ナレコム Advent Calendar 2024](https://qiita.com/advent-calendar/2024/genai-sec-knowcom) の3日目の記事です。

本Advent Calendarは、国内で唯一の技術領域 **責任あるAI** の [MVP受賞者](https://mvp.microsoft.com/en-US/MVP/profile/28dff07e-3dba-4772-97b9-944418868456) を中心に、生成AIを含めたAIやデータを企業が利活用するときに気をつけるセキュリティやガバナンスを中心に紹介します。


## はじめに

責任あるAIは、AIシステムの開発、評価、展開において倫理的で信頼できるアプローチを指します。AIはユーザーによる多くの決定に基づいて構築され、その設計には公平性、信頼性、透明性、プライバシーとセキュリティの保護が重要な要素として含まれます。この記事では、Microsoftが提唱する責任あるAIの6つの基本原則（公平性、信頼性と安全性、プライバシーとセキュリティ、包括性、透明性、説明責任）を紹介し、Azure Machine Learningがこれらの原則を実現するためにどのようなツールとサポートを提供しているかを解説します。具体的には、AIシステムの公平性を評価するダッシュボード、モデルの解釈可能性を向上させるためのコンポーネント、プライバシー保護のための差分プライバシー技術などについて触れます。


## 責任あるAIとは

https://learn.microsoft.com/ja-jp/azure/machine-learning/concept-responsible-ai

責任あるAIは、Microsoftが責任ある AI の標準として開発したもので、Ver.2まで公開されています。安全で信頼できる倫理的な方法で AI システムを開発、評価、デプロイするためのアプローチで、以下の6つの原則に従っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/57bf803e-f448-2a57-5c20-d8e49eb0ac10.png)

各原則がどのように協力して、AIシステムの開発と運用における倫理的なガイドラインを提供するのかが視覚的に表現されています。以下に、各原則の関係性を解説します。

#### 1. 公平性（Fairness）
中央に位置: 公平性と包括性は、責任あるAIのコアとなる原則で、すべての人に対して平等に機会を提供し、AIが特定のグループに偏った結果を生成しないようにすることを目指します。これにより、AIシステムは社会的に望ましい結果を生み出すための基盤を提供します。
他の原則との連携: 公平性を達成するためには、信頼性、透明性、説明責任が密接に関わります。透明性が確保され、システムの動作が説明可能であれば、バイアスの原因を特定し、改善策を講じやすくなります。

#### 2. 信頼性と安全性（Reliability & Safety）
セキュリティと堅牢性の確保: AIシステムは信頼性が高く、安全に運用される必要があります。この原則は、モデルが期待通りに動作し、予期しない動作やセキュリティリスクを最小限に抑えるために重要です。
公平性との連携: 公平性を確保するためには、モデルが一貫して予測を行い、誤った結果を出さないようにする信頼性と安全性が不可欠です。

#### 3. プライバシーとセキュリティ（Privacy & Security）
個人データ保護: プライバシーとセキュリティは、AIシステムが扱う個人データや機密情報を適切に保護することを目的としています。これにより、AIシステムは不正アクセスやデータ漏洩のリスクを避け、利用者の信頼を確保します。
包括性との関連: プライバシーを保護することは、すべてのユーザーを平等に扱うために重要です。特定のユーザー層が不利益を被ることなく、個人情報が安全に扱われることが求められます。

#### 4. 包括性（Inlusiveness）
すべてのユーザーのニーズに対応: AIは多様なバックグラウンドを持つユーザーに対応できるように設計されるべきです。AIシステムがその利点を全てのユーザーに均等に提供できるよう、包括性は重要です。
公平性との相互作用: 包括性は公平性を実現するための一部であり、AIがすべてのユーザーを差別なく扱うための条件を提供します。

#### 5. 透明性（Transparency）
理解可能なシステム: AIシステムがどのように動作し、なぜその決定を下したのかを説明できることが透明性の鍵です。これは特に意思決定が社会的影響を与える場合に重要です。
信頼性と安全性との関係: 透明性が高いと、AIの出力がどのように生成されたかを明確にし、不具合や誤動作の原因を特定しやすくなります。

#### 6. 説明責任（Accountability）
成果を追跡・評価: 開発者や運用者がAIシステムの行動に対して責任を持つことは、システムの信頼性と透明性を高めます。AIがどのように結果を出したのか、またその過程での意思決定が適切であったかを評価することが重要です。
信頼性との関係: 説明責任を持つことによって、システムの信頼性が確保され、ユーザーやステークホルダーの不安を軽減することができます。

**相互関係の強調**
これらの原則は互いに補完し合い、責任あるAIシステムの実現に向けて働きます。たとえば、透明性が確保されることで、公平性の問題が特定しやすくなり、信頼性やセキュリティの確保にもつながります。また、プライバシーとセキュリティの保護は、ユーザーがAIシステムを信頼するための基盤となり、説明責任によってその信頼を強化します。

この図は、責任あるAIを実現するための包括的なアプローチを視覚的に示しており、AIシステムの設計・開発においてどの原則も単独で存在するのではなく、相互に作用し合いながら、より良い結果を導くことを示しています。

### まとめ

この記事では、責任あるAIの6つの基本原則（公平性、信頼性と安全性、プライバシーとセキュリティ、包括性、透明性、説明責任）について詳しく解説しました。これらの原則は相互に連携し、倫理的で信頼性の高いAIシステムの開発と運用を支えています。

次の記事では「Microsoft 責任あるAI」の全文翻訳＆解説を行います。

https://blogs.microsoft.com/wp-content/uploads/prod/sites/5/2022/06/Microsoft-Responsible-AI-Standard-v2-General-Requirements-3.pdf
elixirのバイナリデータパターンマッチについて理解を深める

``` elixir

iex> defmodule WebDB.Binary do
...>   def mime(<<0x89, "PNG", _::bits>>), do: "png"
...>   def mime(<<"GIF", 0x38, _::bits>>), do: "gif"
...>   def mime(<<0xFF, 0xD8, _::bits>>), do: "jpg"
...>   def mime(_), do: "unsupported file"
...> end
{:module, WebDB.Binary, <<（省略）>>, {:mime, 1}}
iex> {:ok, file} = File.read("image.png")
iex> WebDB.Binary.mime(file)
"png"
iex> WebDB.Binary.mime(1)   
"unsupported file"

```


## def mime(<<0x89, "PNG", _::bits>>), do: "png"

### なぜ0x89？
以下のサイトにPNGファイルシグネチャについて記載がある
> PNG バイナリは、先頭に PNG であることを示す８バイトの識別子があり、その後はチャンクと呼ばれるデータのまとまりが最後まで連なる構造になっています

https://zenn.dev/knowledgework/articles/read-png-file

> PNGであることを示す。
16進数で常に、89 50 4E 47 0D 0A 1A 0A

https://www.setsuki.com/hsp/ext/png.htm

この0x89は16進数で89を示している
そのため同じ値を取得できればそのファイルはPNGであることが判明する
<<>>はバイナリーリテラルを示す

https://dev.to/gumi/elixir-06--35na

_::bitsは残りのビットをすべて無視する内容となるためPNGファイルでさえあればどんな画像であっても一致する

## def mime(<<"GIF", 0x38, _::bits>>), do: "gif"
ここでは引数のGIFが先に来ているがその理由は画像ファイルのマジックナンバーが以下のようになっているためである
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/8bef917b-0b35-0844-7f52-7d4fa4fa73e4.png)

https://codeaid.jp/magic_number/

残りのロジックは先ほどと同様

## def mime(<<0xFF, 0xD8, _::bits>>), do: "jpg"
JPGの場合は以下

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/34869294-014a-9894-4d92-516f02e0322c.png)

以下の記事のコードを参考にした

https://qiita.com/the_haigo/items/68f52a6f9623d2da7d26

## 実験

実際に検証してみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/027cf3ff-d2b5-9037-7e8f-d320b5393778.png)
検証のためにubuntu上へそれぞれの拡張子の画像ファイルを作成した

iex経由で実行を行い正しく取得できているかを確認する

動かした結果
想定通りに動いていることを確認した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/8f9d5cbc-63bf-2253-d6b1-8d6c277ec4d3.png)
wsl2の環境をスマートフォンで確認する方法

## 環境

- Windows11
- WSL2
    - Ubuntu 20.04.6

## 事前準備

Windowsとスマートフォンは同じネットワーク内にいることが前提となります。

### WindowsのIPアドレスを確認

コマンドプロンプトかPowerShellで確認できます。

```bash
ipconfig
```

今回は「**192.168.1.100**」だったと想定して進めます。
※PC起動時するたびにこのIPアドレスは変わる可能性があります。

### WSL2のIPアドレスを確認

```bash
hostname -I
```

今回は「**172.21.98.200**」だったと想定して進めます。
※PC起動時するたびにこのIPアドレスは変わる可能性があります。

### WSL2で接続したい環境のポートを確認

今回は「**8080**」ポートと想定して進めます。

## 設定手順

### PowerShellを起動する
**※管理者権限で起動する必要があります**

WSL2へアクセスを許可するための追加、削除、確認コマンド

- **追加**
    ```bash
    netsh.exe interface portproxy add v4tov4 listenaddress=192.168.1.100 listenport=8080 connectaddress=172.21.98.200 connectport=8080
    ```

- **削除**
    ```bash
    netsh.exe interface portproxy delete v4tov4 listenport=8080 listenaddress=192.168.1.100
    ```

- **確認**
    ```bash
    netsh.exe interface portproxy show v4tov4
    ```
    
    確認コマンドで現在の許可状況を確認できます。
    
    ```bash
    ipv4 をリッスンする:         ipv4 に接続する:
    
    Address         Port        Address         Port
    --------------- ----------  --------------- ----------
    192.168.1.100   8080        172.21.98.200   8080
    ```

### ファイアウォールの設定

コマンドプロンプトかPowerShellで以下のコマンドを実行し、ファイアウォールの設定画面を起動する。

```bash
wf.msc
```

1. 受信の規則から新しい規則を追加する

    ![受信の新しい規則.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3926616/3492ea95-8df6-ed47-64dd-f9f5114c28f2.jpeg)

2. 規則の種類を選択

    ![ポート.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3926616/7260e9ee-e21d-0de8-cc36-35e60054be43.jpeg)

3. プロトコルおよびポートの設定

    ![8080.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3926616/48b5425d-71fe-8bc5-85ea-3e49d989aac6.jpeg)

    今回は「8080」を設定

4. 操作

    ![操作.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3926616/6a3a5e17-f187-3678-55c6-90986149aa48.jpeg)

5. プロファイル

    ![プロファイル.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3926616/2975eed1-6789-502f-154a-3479339bd52e.jpeg)

ここまで設定するとスマートフォンから以下のURLにアクセスすると確認ができると思います。



```
http://192.168.1.100:8080
```
※動作検証が終わったらファイアウォールの設定は削除しましょう。

## 参考

[WSL2で起動したReactアプリに外部端末からアクセスする](https://qiita.com/smallriv/items/698fb1373887aa1f7784)
TypeScript入門②型～Error

# プリミティブ型とオブジェクト型
プリミティブ型とはオブジェクト型以外の全ての型
数値型や文字型などすべてを含む

## 数値型について
桁の大きい数字はアンダースコアで区切ることが出来る。
区切っても数値としてちゃんと扱われる。
```typescript
999_999_999
```
# bigint型
末尾にｎをつけて表す
MAX_SAFE_INTEGERを超えるようなでっかい数字がある。
でもこれは数値型では表せないとする。
じゃあ後ろにnってつけとけば、勝手にbigint型で解釈してくれて、エラーにならないね！という話らしい。

ちなみにES2020以降でないとこの書き方は出来ない。
```typescript
 BigInt literals are not available when targeting lower than ES2020.
```

なので、コンパイルするESのバージョンを指定する。
```
tsc main.ts --target ES2020
```

# テンプレートリテラル
この名前が良くない。
用は文字列の中に、変数を埋め込めるよっていうこと。
```typescript
const mojjiretsu = 'いちご';
const temp = `${mojiretsu}はフルーツ`
console.log(temp)
```

# Symbol型
毎回違う値が生成される。
その姿、まるでメモリのアドレスを探すよう。
ただ、乱数を返す関数みたいに使うことはできない。
オブジェクトのプロパティに使う。
と、これじゃまるで意味が分からない。

要は重複させたくないオブジェクトのプロパティに使う

例えばこんなオブジェクトがあって
間違ってコードのどこかでオブジェクトのidを上書きしてしまうかもしれない。
そんなときにsymbol型でidという名前を付けてあげれば上書きされることはない。
何故なら、アプリ内で固有の値だから。
決まった場所にある箱じゃなくて、毎回ランダムに移動してる箱。
ゆえにその実態を誰もつかむことが出来ない。
要は上書きされたくないよ～とかそういう時に使うはず。（間違ってたらすいません）

```typescript
const id = Symbol();
const obj = {
    id: 1,
    id: 2,
    id: 3,
    id: 4,
    [id]: 0001, // idって名前だけど共存できるし、既存のidを上書きすることもない
}
```



# 型注釈
この型しか入れられないよ、というルール
```typescript
let moji :string; // 型は小文字
```

# 列挙型
定数をまとめて宣言してオブジェクトみたいに扱う。
キーワードは```enum```
```typescript
enum test { // test= {}みたいに=はいらない
    member1 = 'maria',
    member2 = 'mary',
    member3 = 'silent hill'
}

console.log(test.member3);
```

ちなみにメンバーの値は省略出来て、そうすると上から番号が０から割り当てられる。
この列挙型の便利なところは、メンバーの値が変わっても、
呼び出すメンバー名は変わらないということ。
まぁ、そのへんの変数と同じ。
```typescript
enum Silent { // test= {}みたいに=はいらない
    member1 = 'maria',
    member2 = 'mary',
    member3 = 'james' //ここの中身が変わっても呼び出し方は同じ
}

console.log(test.member3);
```

# ユニオン型
これか、これのどっちかの型ならOK、とする。
```
const union: string | number 
```

# ユニオン型と列挙型の応用
ユニオン型は「いずれかの型」のみ入れられる型。
列挙型の中のメンバーの値のいずれかのみを代入できる変数を作りたいってときがいつか来るかもしれない。来ないかもしれない

# リテラル型
ある具体的な値をそのまま型として使う。
要は、その具体的な値以外入れられないよ。
```typescript
let test: 'ペルソナ' | true | 1;
// このどれかの値しか代入できない
```

# 型エイリアス
ここまで好き勝手に型を作ってきた。
ユニオン型、リテラル型、列挙型みたいな。
いやいや、もうわけわからんからstringとかintみたいなプリミティブだけにしてくれ、
と思う。
だが、ここでさらに応用が行われてしまう。

ここまで好き勝手作ってきた型に、名前を付けて、今後も便利に使ってやろうという意志が芽生える。
キーワードは __type__ 
```typescript
type Persona = 'アルセーヌ' | 'イザナミ';

let main: Persona = 'ジライヤ' //NG
let main: Persona = 'アルセーヌ' //OK

```
```typescript
type Num = number | bigint;
// こんな風にtype型には:で型を定義するんじゃなくて、型を代入する。何故？

```

# keyof
オブジェクトのキーをリテラル型（この具体的な値なら代入できるよ）にして返す
あるオブジェクトのキーと同じ名前のみを定義できるユニオン型を返す


# if文
よくある書き方まんまなので割愛。

# 三項演算子
```typescript
条件式 ? trueのとき : falseのとき
```
# try catch
これもありきたり。
ErrorオブジェクトをExceptionの代わりに呼び出す。
急にeって出てくるのはErrorオブジェクトに名前が付いただけ。

```typescript
try {
    throw new Error('エラーメッセージ');
} catch (e) {
console.log(e)
}
```
24/11/27 読書記録 ~ソフトウェアテストの教科書~

# 書籍
[【この1冊でよくわかる】 ソフトウェアテストの教科書](https://amzn.asia/d/6jSYRVM)

# 書籍を読む目的

 - [ ] 「品質」を理解する
 - [ ] 品質を担保できるテストを理解する


# Part1. ソフトウェアテストの基本

## Chap01. ソフトウェアテストとは？

### 学び 📝

#### 狩野モデル
ユーザ満足と品質の関係を示すモデル。

| 品質要素 | 充足 | 不充足 |
|:-----------|------------:|:------------:|
| 当たり前品質       | 当たり前        | 不満         |
| 一元的品質     | 満足      | 不満       |
| 魅力的品質       | 満足        | 仕方がない         |

この考え方は学び。
テストを行う上で、当たり前品質の担保が大事なのだろう。

当たり前品質は「**ユーザの期待する結果を満たすか？**」と解釈。
電子レンジであれば、入れた物が「温められること」
LINE であれば「メッセージ送受信が可能であること」
Netflix であれば「選択された動画の閲覧が可能であること」

一元的品質は「ユーザが期待する結果へ **『容易に』** 満たすことができるか？」、
魅力的品質は「ユーザが**期待する結果以外の要求**も満たすことができるか？」と解釈

#### Never, Must, Want

これは意識していることだと感じた。
リリース直前は「Never」が生じないことの確認を行う。
システムが大きくなると、依存関係のあるコードが増え、予想外の不具合が生じやすいイメージ。

### Chap1 感想 :writing_hand_tone5:
品質に対する解像度が上がった。
狩野モデルの「当たり前品質」、Never, Must, Wantの「Never」はテストする上で必ず必要な観点だろう。日々の業務でも意識する必要がある。

次章が楽しみ。

## Chap02. ソフトウェア開発の流れとテスト工程

### 学び 📝

#### テスト工程の流れ

単体テスト：モジュール（ソフトウェアの最小単位）毎に行うテスト
統合テスト：複数モジュールの動作テスト。詳細設計で定めたモジュール間の連携をテスト
機能テスト：組み合わせたモジュールを1つの機能として行うテスト
システムテスト：要求定義の内容が実現されているかのテスト

各テストの各定義が曖昧だったので勉強になった。
機能テストをする必要があるのに、統合テストと読んでいたり、勘違いに気づけたのは大きい。
定義は大切にしていきたい。

### Chap02 感想 :writing_hand_tone5:

普段業務に取り掛かる中、テスト工程の沿って取り掛かっていることもあり、理解できる内容が多かった。エンジニア業務に携わったことのない方にとって、分かりやすい説明だったかも。
SC-900合格記(2024/11/27投稿)

# はじめに
この度MicrosoftのSC-900試験(Microsoft Certified: Security, Compliance, and Identity Fundamentals)を受験してきましたので、勉強した内容と受験した感想を書いておきます。
これから受験される方の参考になれば幸いです。


# 前提
* AZ-900/DP-900/AI-900/AZ-104/AZ-204/AZ-700/AZ-305/AZ-500/DP-203は取得済み
* AzureはAPIM、DevOpsを少し触って、VMを作った程度
* AWSの実務経験あり
* AWS認定は全て取っています(15資格)
* Google Cloud認定はMLとWorkspaceを除いた9つ取ってます


# 学習内容
ありがたいことに会社負担でトレノケートさんのMicrosoftトレーニング受講できることになったので、以下のトレーニングを受けて学習を行いました。

- [Microsoft セキュリティ、コンプライアンス、ID の基礎 (SC-900T00) バウチャー付き](https://www.trainocate.co.jp/reference/course_details.aspx?code=MSC0772V)

トレーニングには無料バウチャーも付いていたので、今回はバウチャーを使って試験を受けてきました。

## Microsoftトレーニング
当然のことながらトレーニング内容には言及できないのですが、トレーニングとしては次のような学習内容がありました。(上記リンクに記載されています)

===

１. セキュリティ、コンプライアンス、およびIDの基本的な概念
  - セキュリティの概念と方法
  - マイクロソフトのセキュリティとコンプライアンスの原則

２. Microsoft IDおよびアクセス管理ソリューションの概念と機能
  - IDの概念
  - Azure ADの基本的なサービスとIDの種類
  - Azure ADの認証機能
  - Azure ADのアクセス管理機能
  - Azure ADのID保護とガバナンス機能

３. マイクロソフトのセキュリティソリューションの機能
  - Azureの基本的なセキュリティ機能
  - Azureのセキュリティ管理機能
  - Azure Sentinelのセキュリティ機能
  - Microsoft 365の脅威対策機能
  - Microsoft 365のセキュリティ管理機能
  - Microsoft Intuneのエンドポイントセキュリティ

４. マイクロソフトのコンプライアンス管理の機能
  - マイクロソフトのコンプライアンス管理機能
  - Microsoft 365の情報保護およびガバナンス機能
  - Microsoft 365のインサイダーリスク機能
  - Microsoft 365の電子情報開示機能
  - Microsoft 365の監査機能
  - Azureのリソースガバナンス機能

===

弊社はAWS、Microsoft Azure、Google Cloudと3つのパブリッククラウド上でのシステム構築などをご支援させていただいておりますが、最近ではマルチクラウドを利用されるお客様もかなり増えてきました。
私も過去にAzure←→AWS間の連携検証などを行ったりしたことがあるのですが、その際Azure AD(現Entra ID)の仕組みが中々馴染みづらく、理解にかなり時間がかかった記憶があります。

趣味でこんな本とかも書いてみましたが、それでも触りの部分をざっくり理解できただけで、「じゃあ何ができるの？」という問いに説明できるレベルまではなれていません。

https://techbookfest.org/product/21v7k0tUSqfNP5wV1e2YLz?productVariantID=1KZGPDErDrY8BDLjFj6dtc

それもあって一度ちゃんとMicrosoftのセキュリティや認証認可周りについて学習しようと思って受講を決めました。

トレーニングでは、以下のMS Learnの内容にも言及しながら説明や解説を行っていただいたので、かなりわかりやすかったです。
MS LearnはMicrosoft Learn プロファイルを作成していれば無料で見れるので、理解が不足している部分などを後から振り返ることもできて良かったです。

https://learn.microsoft.com/ja-jp/training/courses/sc-900t00?WT.mc_id=ilt_partner_webpage_wwl&ocid=523802#study-guide


## Udemy
ラーニングパスでの学習が完了したら、知識確認のために以下の公式問題を解きました。

- [試験 SC-900:認定試験の内容に沿って作成された模擬試験です。Microsotサービス全体のセキュリティ、コンプライアンス、およびIDについて幅広く学ぶことができます。](https://www.udemy.com/share/107oHI3@wpbxGkH5dfL6O4R11tSEKJOBKd2EKph_Vg7EKOHGeSDyMNh0BR11R8oqkEC4cXub/)

Udemyの内容としては、46問1セットの問題が4セット含まれていました。
難易度は本番と近いか若干簡単なぐらいでしたが、MS Learnを読んだだけだと理解しずらい内容などもちゃんと出題されていて、理解不足な箇所に気付くのにちょうどよかったです。


# 受験した感想
難しいといってもFundamentalsレベルなので、模擬問題をある程度解いておけばそこまで難しくはなかったです。多分30分ぐらいで回答して退出したと思います。


# 受験結果
合格でした。思ったよりも平均的に取れてました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/31b7e292-84d2-49a1-d9c1-45ad863dbce4.png)


# おわりに
Microsoft IntuneやMicrosoft 365、Azure Sentinelは普段の業務で絶対触る機会のないサービスなので、良い勉強になりました。

次の目標資格ですが、Xでこんな投稿をみかけて、Microsoft Fablicは周りでも割と名前が挙がるようになっていたのもあって、DP-600バウチャーもらうべく申込んでみました。
バウチャーもらえたらチャレンジしてみたいと思います。

https://x.com/mrk_17tksm/status/1861266453913313292

この記事がどなたかの参考になれば幸いです。
【原因不明だが解決した】PlatformIOでESP32「BLEDevice.h: No such file or directory  」への暫定解決策

表題のエラーについて、 **原因不明のままだが、なぜかうまくいった** 内容を自分向けにメモで残します。とはいえ、同様のエラーメッセージについてGithubで解決されていないissueがいくつかあったようなので、事例の一つとして蓄積する価値はあると思っています。

**本質的な解決策がわかるつよつよの方、アドバイスをお待ちしています！**

## 状況
### device
* M5atom lite
    * ESP32マイコンを積んでいます。ESP32 S3を積んでいるマイコンでは本記事の手順でもうまくいかなかった(後述)
### 開発環境
* Visual Stdio Code
* PlatformIO拡張機能
### やっていたこと
* atom liteでphyphoxBLEライブラリを使うと思ってコードをビルドしたところ表題のエラーでビルドができなかった。
* `BLEDevice.h: No such file or directory `

## うまくいかなかったけどやったこと
https://github.com/BrewNinja/RadonEye-ESP32/issues/2
* エラーメッセージをそのままググって出てくるようなことはやりました。例えば上の記事のように特定のライブラリを強制的に読ませるなど...効果なし

## 解決策
* 事前にm5stick c plusで同様のphyphox BLEライブラリが動いていたことがわかっていたから、ダメ元でPlatformIOで、使いもしない`	m5stack/M5StickCPlus@^0.1.0`をライブラリとしてプロジェクト内にインストールしました。
* **すると、なぜかビルドが通過しました！**
* さらに **`m5stack/M5StickCPlus@^0.1.0`をプロジェクトからアンインストールした後も、引き続きビルドができています！**


## まだわからないこと
* 上記対策は、ESP32S3シリーズを積んでいる、atomS3では通用しませんでした。ESP32シリーズだけで有効みたいです。
CycloneDXの仕様

# 概要
## CycloneDX オブジェクトモデル
* JSON Schema、XML Schema、および Protocol Buffers で定義されています
* 指定的で簡単に使用できます
* SBOM、SaaSBOM、AI/ML-BOM、CBOM、VEX などの xBOM ユースケース向けに設計されています
* 複雑な関係を簡単に記述できます
* 特殊なユースケースや将来的なユースケースをサポートするために拡張可能です
## BOM メタデータ
BOM メタデータには、サプライヤー、製造者、および BOM が記述する対象コンポーネントが含まれます。また、BOM を作成するために使用されたツールや、BOM ドキュメント自体のライセンス情報も含まれます。

## コンポーネント (Components)
コンポーネントは、ファーストパーティおよびサードパーティのすべてのコンポーネントの完全なリストを記述します。この仕様では、ソフトウェア、ハードウェアデバイス、機械学習モデル、ソースコード、設定情報を表現できます。さらに、製造者情報、ライセンスや著作権の詳細、各コンポーネントの系譜や出所情報を記述できます。

## サービス (Services)
サービスは、ソフトウェアが呼び出す可能性のある外部 API を表します。エンドポイント URI、認証要件、信頼境界の移動を記述します。また、ソフトウェアとサービス間のデータフローを説明し、データ分類やフローの方向を特定できます。

## 依存関係 (Dependencies)
CycloneDX は、コンポーネントとその他のコンポーネントへの依存関係を記述する機能を提供します。依存関係グラフは、直接的および間接的な関係を表すことができます。また、サービスに依存するコンポーネントや、他のサービスに依存するサービスもグラフで表現できます。

## 構成 (Compositions)
構成は、構成要素（コンポーネント、サービス、依存関係）とその完全性を記述します。各構成の集合体は、完全、部分的、ファーストパーティのみの部分的、サードパーティのみの部分的、不明として記述できます。

#脆弱性 (Vulnerabilities)
サードパーティやオープンソースソフトウェアの使用により継承される既知の脆弱性や、それらの脆弱性の利用可能性を CycloneDX で伝達できます。さらに、コンポーネントやサービスに影響を与える未知の脆弱性も CycloneDX を使用して公開可能で、脆弱性開示や VEX ユースケースに最適です。

## 製造プロセス (Formulation)
製造または展開された方法を記述します。CycloneDX は複数のフォーミュラ、ワークフロー、タスク、ステップをサポートし、再現性のための宣言された製造プロセスや、実際の製造過程で行われた行動を表現します。

## 注釈 (Annotations)
注釈は、コメント、メモ、説明など、注釈対象に追加のコンテキストを提供するテキスト内容を含みます。これらは、ツールによる自動生成や、人や組織による手動レビューの結果として BOM に追加されることがよくあります。注釈は、デジタル署名を使用して独立して署名および検証することが可能です。

## 定義 (Definitions)
標準、要件、レベル、およびすべてのサポート文書がここで定義されます。CycloneDX は、ほぼすべての種類の標準を機械判読可能な形で定義する一般的な方法を提供します。OWASP ASVS、MASVS、SCVS、SAMM などのセキュリティ標準が CycloneDX 形式で利用可能です。他の団体による標準も利用可能で、組織は内部標準を作成し、それを CycloneDX で表現できます。

## 宣言 (Declarations)
宣言は標準への適合性を記述します。各宣言には、証明書、主張、反主張、証拠、反証、適合性および信頼性が含まれる場合があります。署名者を宣言し、デジタル署名やアナログ署名の両方をサポートします。宣言は「コードとしてのコンプライアンス」の基盤を提供します。

## 拡張機能 (Extensions)
CycloneDX オブジェクトモデルには複数の拡張ポイントが存在し、新しい機能の迅速なプロトタイプ化や、特殊なユースケースや将来のユースケースをサポートします。CycloneDX プロジェクトは、コミュニティ全体に利益をもたらす拡張機能を維持しており、専門的または業界特化のユースケースをターゲットにした拡張機能の開発をコミュニティに奨励しています。

## 高レベルオブジェクトモデル
CycloneDX オブジェクトモデルのスイムレーン（概要図）。

## 登録済みメディアタイプ
以下のメディアタイプは IANA に正式登録されています：

メディアタイプ	フォーマット	割り当て元
application/vnd.cyclonedx+xml	XML	IANA
application/vnd.cyclonedx+json	JSON	IANA
特定の CycloneDX バージョンは、バージョンパラメータを使用して指定できます。例：application/vnd.cyclonedx+xml; version=1.6
Protocol Buffer フォーマット用に公式にサポートされているメディアタイプは application/x.vnd.cyclonedx+protobuf です。

## 認識されるファイルパターン
CycloneDX BOM ファイルを保存するために慣例的に使用されるファイル名：

JSON エンコードの場合: bom.json
XML エンコードの場合: bom.xml
また、以下のグロブパターンに一致するファイルも認識されます：

*.cdx.json（JSON エンコード）
*.cdx.xml（XML エンコード）

## 認識される述語タイプ
ソフトウェアサプライチェーンの多くのツールは、実行時に証明をキャプチャします。述語は証明に関するメタデータを含みます。in-toto などのツールは、述語タイプを使用して述語の主題に関するコンテキストを提供します。OWASP は、CycloneDX の BOM バリエーション（SBOM、SaaSBOM、HBOM を含む）の公式述語タイプとして https://cyclonedx.org/bom を認識しています。
ダブルバッファリングでテトリスの画面のちらつきを抑える

## ダブルバッファリングによる内容の上書きとsystem("cls")の画面クリアから再描画の違いについて

テトリミノが動くとコンソール上にすさまじいちらつきがあったのでこれを改良するために発見したことを忘れないようにまとめておきたいと思います。同じくこの壁にぶつかった駆け出しプログラマーの助けになればなぁと思います(笑)


大事なポイントは画面を上書きすることと画面をクリアすることの違いです。
system("cls")は画面をクリアすることに該当します。

ちらつきを抑えるためには画面を上書きすることが重要です。なので今回はダブルバッファリングを用いて下記のコード

```
printf("\033[H");
```
がとても重要になります。
これはとてもシンプルでカーソルを画面左上（スタート位置）に移動するというものです。
プログラムは単純にスタート位置からゴール位置まで飛ばすことなく値を出力していきます。


```tetris.c

void DrawScreen() {
    // バックバッファをクリア
    memset(backBuffer, 0, sizeof backBuffer);

    // 枠の描画
    for (int y = 0; y < FIELD_HIGHT + 2; y++) {
        backBuffer[y][0] = 1;                     // 左枠
        backBuffer[y][FIELD_WIDTH + 1] = 1;       // 右枠
    }
    for (int x = 0; x < FIELD_WIDTH + 2; x++) {
        backBuffer[FIELD_HIGHT + 1][x] = 1;       // 下枠
    }

    // フィールドの描画
    // テトリミノが一番下に来たときブロックを置いた場所(field配列)に1を入れる
    for (int y = 0; y < FIELD_HIGHT; y++) {
        for (int x = 0; x < FIELD_WIDTH; x++) {
            if (field[y][x]==1) {
                backBuffer[y + 1][x + 1] = 1;
            }
        }
    }

    // テトリミノの描画
    for (int y = 0; y < mino.shape.hight; y++) {
        for (int x = 0; x < mino.shape.width; x++) {
            if (mino.shape.patterm[y][x]==1) {
                backBuffer[mino.y + y + 1][mino.x + x + 1] = 1;
            }
        }
    }

    // バックバッファの内容をコンソールに出力
    for (int y = 0; y < FIELD_HIGHT + 2; y++) {
        for (int x = 0; x < FIELD_WIDTH + 2; x++) {
            if (backBuffer[y][x]==1)
                printf("■");
            else printf(" ");
        }
        printf("\n");
    }
}


```
ダブルバッファリングで内容を保存していきます。
```
  memset(backBuffer, 0, sizeof backBuffer);
```
保存した内容を一度初期化する、とても重要です。
```
int main() {
    // フィールドを初期化
    initializeField();

    // キーボード入力を待つループ
    while (1) {
        if (_kbhit()) {
            switch (_getch()) {
            case 'a':
                selectedTetrimino.currentX--;
                break;
            case 'd':
                selectedTetrimino.currentX++;
                break;
            case 's':
                selectedTetrimino.currentY++;
                break;    
        } 
        // カーソルを左上に準備
        printf("\033[H");
        DrawScreen();
    }
 
}
```

カーソルを左上に持っていきbakBuffer配列で保存した内容を順にスタート(左上)から上書きしていくという流れです。この流れがとても重要になります。
```
printf("\033[H");
```
これを書いていない場合、コンソール上ではおびただしい量のテトリスが描画され続けます。


また配列には全角文字の"■"は入らないので条件分岐で出力することもポイントです。
Power AutomateでSharePointリストの5000件以上の項目からデータを抽出する

# やりたいこと
Power AutomateでSharePointリストの5000件以上の項目を取得し、フィルター条件に合致した項目のみを抽出する。

# 前提条件
- Microsoft 365 開発者プログラムをアクティブ化し、以下製品ライセンスを有効化する
  - Microsoft 365 E5 Developer
  - Microsoft Power Automate Free

https://learn.microsoft.com/ja-jp/office/developer-program/microsoft-365-developer-program

- SharePointリストの項目数は5000件以上
- トリガーはフローを定期的に実行できる［繰り返し］を使用する

# 手順1.［HTTP要求を送信する］でSharePoint REST APIを使用する
一般的には、SharePointの［複数の項目の取得］アクションで5000件以上のデータを取得しますが、以下記事を参照したところ、<INS>パフォーマンスプロファイル = 低 のライセンスおよび［繰り返し］トリガーの場合、［複数の項目の取得］アクションで5000件以上の項目を取得し、フィルター処理をすることができません。</INS>フロー保存時にエラーとなってしまいます。

https://learn.microsoft.com/ja-jp/power-automate/limits-and-config#performance-profiles

https://itc-engineering-blog.netlify.app/blogs/powerautomate-over5000#h2-titile-108

［SharePoint - HTTP要求を送信する］アクションで5000件以上の項目に対してフィルター処理をすることができます。ただし、SharePoint REST APIの制限で、1回のAPIコールで5000件以上の項目を取得することはできません。したがって、5000件以上の項目からfilterクエリおよびtopクエリで5000件未満の項目を抽出します。
```text:HTTP
GET https://{site_url}/_api/web/lists/GetByTitle('list_name')/items?$filter=ColumnName eq 'Hello World' &$top=5000
Accept: "application/json;odata=nometadata"
```

![SPO REST API.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/4bbb5b0b-84d1-de00-5040-61ecc77c0053.png)

<br>
SharePoint REST API 実装およびODataクエリ操作の詳細は、以下記事をご参照ください。

https://learn.microsoft.com/ja-jp/sharepoint/dev/sp-add-ins/working-with-lists-and-list-items-with-rest#retrieve-all-list-items

https://learn.microsoft.com/ja-jp/sharepoint/dev/sp-add-ins/use-odata-query-operations-in-sharepoint-rest-requests

# 手順2. SharePointリストでインデックスを作成する
filterクエリで使用するSharePointの列にインデックスを作成する必要があります。SharePoint Onlineサイトの設定から［リストの設定］⇒［インデックス付きの列］⇒［新しいインデックスの作成］をクリックし、対象の列を選択してインデックスを作成します。

SharePointリストのインデックス作成手順は以下公式ドキュメントをご参照ください。

https://support.microsoft.com/en-us/office/add-an-index-to-a-list-or-library-column-f3f00554-b7dc-44d1-a2ed-d477eac463b0?ui=en-us&rs=en-us&ad=us
とある大学生の色変記事-茶色編

はじめまして、returnhanamaruと申します。
この度報告が三ヶ月ほど遅れましたがAtCoderにユーザー登録をし、完全未経験の状態からプログラミングを始めてから丁度一年で茶色コーダーになることができました。

https://atcoder.jp/users/returnhanamaru
     　
筆者の	AtCoder	登録時点でのスペック
・情報系の大学一年生(プログラミングの授業は履修前)
・本当にプログラミングに関しては何も分からない。それこそ”Hello World”の出力のやり方すら分からないレベル。
・大学入学時点ではタッチタイピングもできず人差し指でキーボードを使っていたレベル(登録時点では実用的なレベルにはなっていた)。
・ITに関する知識も皆無で資格も未所持(登録から数ヶ月後にIパスと基本情報を取得する)。

競技プログラミングを始めようと思ったきっかけは本当に大それたものではなくただC言語を使う練習をするために登録したので、レートを上げようとか茶色コーダーになろうとかそういう目標は一切ないまま無欲なスタートすることになります。

ほかの方の色変記事を読んでいると、実務経験があったり情報系の大学や院を既に出ていたり、登録以前に何らかの言語を触ったことがある方が多い印象を受けましたが私に関しては全くそんなことがなかったので、ほかの人と比べるとかなり不利な状態からのスタートだったと思います。

・最初の1ヶ月間(2023年9月)
先ずは、C言語の書き方について勉強するところから始まります(後にC++に乗り換える)。とは言えプログラミングの勉強方法についても何もわからなかったので、とりあえずC言語の教科書に載っているサンプルコードを写経するところから始めました。それにより基本的な入出力やfor文やwhile文の書き方覚えていくことができました。
そして一番最初に立てた目標は、どんなに時間がかかってもいいからコンテスト中に何としても一問解くというもので目標としてはかなり低い部類のものだと思います。
しかし、この頃はコードの書き方を覚えきれていないので方針を立てることができてもA問題ですら実装の仕方がわからないということが割とあり、もどかしい思いをすることになります。

・2023年10月～11月
ここら辺からようやくC言語でコンテストに参加することが大幅に不利になるということに気が付きC++に乗り換えることを決意する。
そして、入出力のcinやcoutのことやSTLの存在を知ることになる。
ソートするときも以前は二重for文を使ったバブルソート(計算量O(n^2))を使っていたが、sort(a.begin(),a.end());などを使えるようになる。

・2023年12月
ここら辺から本格的にレート上げたいという思いや茶色コーダーになりたいという思いが出始めてきて、ここから本格的に精進が始まることになります。
この頃やったことは非常にシンプルで、とにかく過去のA問題を解くというものでした。
そのおかげか以前よりも遥かに素早くA問題を解けるようになったり、たまにB問題も解けるようになり一回だけだが茶色パフォを出すことに成功する。

・2024年1~３月
A問題は大方解き終わったので、B問題とC問題を解いていくことになる。
また1月にIパス、３月に基本情報に合格する。
ここら辺から茶色パフォをとれることが増えて順調にレートを伸ばしていき三月ぐらいになるとレートは300台に乗った上に平均パフォが大体500ぐらいだったので茶色コーダーになれるのは時間の問題だと思い始める(死亡フラグ)。

・2024年4月
ここら辺から暗黒期が始まることになる。
なんと茶色パフォは一回も出せず挙句の果てには一完で終わった回も存在するぐらい。結果的にレートは22も下がってしまう。

・2024年５～７月
ここら辺から、なかなかレートが上がらずコンテストに参加すること自体がしんどいと感じ始めるようになる。
参加回数は三か月でなんとたったの三回。

・2024年８~9月
ここら辺から一気に覚醒することになる。
これまで停滞していたレートが噓のように上がり始めたった三回のコンテストでレートを90近く上げ、入茶した際のコンテストでは過去最高のパフォーマンス788を記録し色変に成功しこの時初めて初心者から抜け出すことができたように感じます。

・これからAtCoderを始めようとしている方へ
私はAtCoderに登録しコンテストに参加するようになるということはプログラミングやアルゴリズムの能力を大幅に向上させる代わりに常にレートやコンテストのことが頭をかすめ続けるようになるという悪魔の契約だと思っています。また、ユーザーレベルは向上し続けているため年々レートを上昇させたり色変するハードルが上がり続けているように感じます。それでもレートが上昇したりプログラミングのスキルが向上した行くのはとても楽しいことなので興味のある方はぜひ参加してみてください。
SQL Serverのトリガーの定義を確認する

# 1. はじめに
* SQL Serverに登録しているトリガー情報をまとめて取得したい

# 2. 開発環境
* SQL Server 2017

# 3. SQL文
```SQL:
SELECT 
	O.name AS 'テーブル名'
	, O.type_desc AS 'オブジェクト区分'
 	, TR.name AS 'トリガー名'
	, TE.type_desc AS 'トリガータイプ'
	, CASE TR.is_disabled WHEN 0 THEN '有効' ELSE '無効' END AS '有効無効'
	, S.definition AS 'クエリ'
FROM sys.triggers TR 
INNER JOIN sys.objects O 
	ON TR.parent_id = O.object_id 
INNER JOIN sys.trigger_events TE 
	ON TE.object_id = TR.object_id 
INNER JOIN sys.all_sql_modules S 
	ON S.object_id = TR.object_id 
;
```

# 4. 使用テーブルの説明

|テーブル名  |説明  |
|---|---|
|sys.objects  |データベース内に作成されているユーザー定義のスキーマ スコープ オブジェクト (ネイティブ コンパイルされたスカラー ユーザー定義関数を含む) ごとに 1 つの行が含まれます。  <br>https://learn.microsoft.com/ja-jp/sql/relational-databases/system-catalog-views/sys-objects-transact-sql?view=sql-server-ver16|
|sys.triggers  |TR トリガーまたは TA トリガーであるオブジェクトごとに、1 行のデータを格納します。 DML トリガー名はスキーマ スコープであるため、 sys.objectsに表示されます。 DDL トリガー名は親エンティティによってスコープ指定され、このビューでのみ表示されます。 <br> https://learn.microsoft.com/ja-jp/sql/relational-databases/system-catalog-views/sys-triggers-transact-sql?view=sql-server-ver16 |
|sys.trigger_events  |トリガーが起動されるイベントごとに 1 行のデータを保持します。 <br>https://learn.microsoft.com/ja-jp/sql/relational-databases/system-catalog-views/sys-trigger-events-transact-sql?view=sql-server-ver16 |
|sys.all_sql_modules  |sys.sql_modules と sys.system_sql_modules の和集合を返します。 <br>https://learn.microsoft.com/ja-jp/sql/relational-databases/system-catalog-views/sys-all-sql-modules-transact-sql?view=sql-server-ver16 |


# 5. 参考文献

https://notepad-blog.com/content/107/

https://nanashipgmer.hatenablog.com/entry/2016/05/15/192326
社内のQ&Aフォーラムに寄せられて嬉しかったこと Part3

以前「[GitHub Discussionsで社内のQ&Aフォーラムを開設する](https://www.lifull.blog/entry/2022/02/24/100000)」でもご紹介した通り、LIFULLではGitHub Discussionsを使った社内向けのQ&Aフォーラムを有志で運営しています。

> このフォーラムは「あるシステムについて誰か詳しい人に相談したい」とか「設計についてチーム外にも相談したい」とか、エンジニアリングで困ったことをなんでも聞ける窓口になることを目指しています。最近ではアーキテクトチームや QA チームなどの公式の窓口としても利用でき、質問の内容に応じて適切な部署や人がアサインされる体制も整い始めました。

[去年](https://qiita.com/ninomiyt/items/ecffed50bda4ea6bec93)も書いたように、生成AIブーム以降質問ペースは落ちていたのですが、ここ最近おもしろい使われ方をされるようになってきました。それをこの記事ではまとめてみようと思います。

社内の雰囲気もなんとなく伝わると思うので、そういう意味でも楽しんで読んでいただけると嬉しいです。

## パブリックコメントの場として利用してもらった

長沢さん（CTO）から、「海外拠点のメンバーは必ずしも日本語が流暢ではない。彼らが情報のキャッチに苦戦しているので、Slackでの広報ルールをきちんと明文化して運営したいのでパブリックコメントを募集したい」という投稿がありました。

> 運用ルール
>
> * 全体に伝えたい広報はメンションしましょう
> * 広報はトランスレーションしましょう
> 
> と決めれば、LFTxメンバーもteam-engineerでやり取りされるすべてを翻訳する必要がなく、@channelや@here、もしくは UG に対してメンションのあった必要なもののみを意識すればいいと思うので、そのようなルールを確立して運用していきたい。
>
> パブリックコメントを募集するので、意見があればいただきたいです。

今までも[レガシーシステムの廃止確認](https://qiita.com/ninomiyt/items/ecffed50bda4ea6bec93#%E5%85%A8%E4%BD%93%E7%A2%BA%E8%AA%8D%E3%81%AE%E5%A0%B4%E3%81%A8%E3%81%97%E3%81%A6%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%82%E3%82%89%E3%81%88%E3%81%A6%E3%81%84%E3%82%8B)などでは利用してもらえていたのですが、こうした建設的な用途で使ってもらえてるのは嬉しいです！

もちろん、他にも「共用リポジトリで使われているライブラリがメンテナンスされていない。今後は新規利用を停止して、将来縮退する方針を決めてもいいか」というような、技術的な議論の場としても利用されています。


## 横断的なドキュメントを投稿する場として利用されるようになった

[昨年](https://qiita.com/ninomiyt/items/ecffed50bda4ea6bec93#chatgpt-retrieval-plugin%E3%82%92%E3%83%99%E3%83%BC%E3%82%B9%E3%81%A8%E3%81%97%E3%81%9F%E7%A4%BE%E5%86%85ai%E3%81%A8%E9%80%A3%E6%90%BA%E3%81%97%E3%81%9F)書いたように、このDiscussionsはkeelaiと呼ばれる内製AIに自動でドキュメントとして取り込まれています。

https://www.lifull.blog/entry/2023/11/16/170000


これで社内ドキュメントを集約する動きが出てきました。例えば次のような内容です。

> クライアントサイドのコーディングに便利な資料やツール集 #919
>
> 他にいいやつあったらコメントください
>
> **全般**
> **社内ツール**
>
> * LIFULL HOME'S Frontend Recipes
>   * よく使われるコンポーネントを集めたカタログ。コピペで爆速実装しよう！
> * lifull/lh-tailwind-config
>   * ガイドラインに基づいた tailwind.config.js 設定。


## ベトナム所属のメンバーから投稿してもらった

上記の情報集約の流れで、何度か日本だけでなく、ベトナム子会社（LFTV）のメンバーからも投稿がありました。英語で投稿してもらってます。

本当は[LLMを利用したPlatform Engineering](https://www.lifull.blog/entry/2024/08/29/173000)にあるように、GitHub Actionsを使った自動翻訳にも将来的には期待してます。「特定のラベルをつけたときだけDiscussionsのやり取りを自動翻訳する」機能が欲しいのですが、Issuesは実現できたものの、APIで取得できる項目では足りてなくてDiscussionsは未対応だそうです。

気がつけば弊社もインターナショナルな感じになってきています。

## 今後の展望

昨年末は「生成AIにも質問できるから質問自体が減ってくるだろうな」と考えていて、実際減ってきているものの、「生成AIに取り込まれるドキュメントの手軽な集約先」や海外からの利用など、意外な展開もありました。

LIFULLではよりチームの多国籍化・多拠点化が進むはずなので、よりフォーラムで明示的に議論するような文化を作っていこうと思います。もしLIFULL社員が読んでいたら、その可能性を一緒に探っていって頂けると嬉しいです。
VSCodeでDjangoの環境構築

### 概要

VSCodeでDjangoの環境を構築する方法や手順について

### Djangoの環境を構築する手順

①VSCodeでUbuntuを起動し、ターミナルから以下の2つのコマンドを実行して環境を最新にする

```
sudo apt-get update
```
```
sudo apt-get upgrade
```
②仮想環境を以下のコマンドにより作成

```
python3 -m venv sample
```
lsコマンドでsampleが作成されていることを確認できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3926100/53275615-f376-2872-1aa5-3082bf7edc9d.png)

③ファイルを実行する
sourceはファイルを実行するという意味。引数はどのファイルを実行するか
```
source sample/bin/activate
```
④Djangoのインストール

```
pip install django==バージョン数
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3926100/0e8b4ee5-669d-2eae-5309-dabbafa16fa5.png)
4.テスト実行


**4.テスト実行**

スクリプトの実行方法をまとめます。


・目次
4.1.Python実行
4.2.2端末同時実行

<br>
<br>

4.1.Python実行
---

・Appiumを起動
```ターミナル.
appium
```

別のターミナルウィンドウにて、作成したPythonファイルを以下のように入力して実行

```ターミナル.
python3 X.py
```


<br>
<br>


4.2.2端末同時実行
---

2つのターミナルウィンドウを開き、2つの異なるポート番号でappiumを起動する


・1つ目
```ターミナル.
appium --port 4723
```

・2つ目
```ターミナル.
appium --port 4724
```


<br>
<br>
<br>

以上！
重大なアップデート！VertiTabがクラウド同期、ツリー型タブ、自動スナップショット機能を新たに追加、タブの消失問題を解決し、ブラウジングをより効率的で便利に！


今回のアップデートでは、VertiTabがタブの消失や管理の混乱など、非常にフラストレーションを引き起こす問題を解決するために、いくつかの重要な新機能を追加しました。新しいクラウド同期機能により、どのデバイスでもタブやグループ、ウィンドウを同期できるようになり、ツリー型タブによってタブの整理がより効率的になります。

### **1. クラウド同期：タブの消失を心配しなくてよい！**

タブが消えてしまうことは多くのユーザーにとってストレスの原因ですが、システムのクラッシュやブラウザのエラーによって作業中のタブが一瞬で消失してしまうこともあります。VertiTabでは、新たにクラウド同期機能を導入し、この問題を解決しました！

**クラウド同期を有効にする理由は？**

- **デバイス間でのデータ同期**  
  どのデバイスで作業しても、クラウド同期を使用するとタブ、タブグループ、ウィンドウ、ブラウザ設定がすぐに同期されます。異なるデバイスでもデータが自動的に一致し、ブラウジング体験がスムーズに保たれます。

- **単一デバイスのユーザー向けデータ保護**  
  単一のデバイスだけを使用している場合でも、クラウド同期は非常に役立ちます。システムクラッシュやブラウザのエラーが発生したり、再インストールが必要な場合でも、すべてのタブと設定が迅速に復元され、再設定の手間が省けます。

- **セキュリティとプライバシー保護**  
  VertiTabでは業界最先端のAES-GCMローカル暗号化技術を使用して、データがクラウドにアップロードされる前に暗号化されることを保証しています。データ転送と保存中のセキュリティが確保されているため、プライバシーを心配することなく使用できます。

### **2. ツリー型タブ：タブ管理をさらに効率化！**

タブ管理は決して簡単ではありません。特に、複数のタブを開いているときに、タブを効率的に整理するのは多くのユーザーにとって課題です。そこでVertiTabでは、新たに**ツリー型タブ**機能を導入しました。親子関係に基づいてタブをツリー構造で整理し、タブ管理をより視覚的に効率的にします。

**なぜツリー型タブが効率的なのか？**

- **より明確なタブ構造**  
  ツリー構造を使用すると、タブの階層関係を簡単に表示・管理でき、従来のタブバーの混乱を避けることができます。

- **作業効率の向上**  
  ツリー型タブは、必要なタブをより簡単に見つけ、関連するタスクやページを集中して管理できるため、作業効率が向上します。

### **3. 自動スナップショット：データの二重保護！**

ブラウザクラッシュやシステムの突然のシャットダウンにより、タブや作業中のウィンドウを失うのは非常にストレスです。これを防ぐために、VertiTabでは**自動スナップショット**機能を導入しました。最新のタブ状態を自動的に保存し、作業を保護します。

**自動スナップショットはデータをどのように保護するのか？**

- **タブ状態をリアルタイムで保存**  
  タブを閉じたり変更を加えたりすると、VertiTabはタブの状態を自動的に保存し、問題が発生した際に最新の状態に復元します。

- **クラウド同期とスナップショットの二重保護**  
  クラウド同期と自動スナップショットを組み合わせることで、システムのクラッシュやブラウザの再インストールがあっても、タブや作業状態をすぐに復元できます。

---

今回のアップデートにより、タブ管理がよりスマートで効率的になり、データ保護が強化され、ユーザーが直面する多くの問題が解決されました。最新バージョンをダウンロードして、より安定した、安全なタブ管理を体験してください！

[VertiTabを今すぐ試す](https://chromewebstore.google.com/detail/vertitab-vertical-tabs-in/chejfhdknideagdnddjpgamkchefjhoi)

---

ご質問やフィードバックがありましたら、いつでもご連絡ください。このアップデートがより良い体験を提供できることを願っています！
TEST

📧 新しいメールを受信しました
件名: @{triggerOutputs()?['body/subject']}
受信日時: @{triggerOutputs()?['body/receivedDateTime']}



















https://help.deepsecurity.trendmicro.com/aws/system-requirements.html?utm_source=chatgpt.com


Windows Server のハードウェア要件

https://learn.microsoft.com/ja-jp/windows-server/get-started/hardware-requirements?utm_source=chatgpt.com&tabs=cpu&pivots=windows-server-2022



SQL Server 2022: ハードウェアとソフトウェアの要件

https://learn.microsoft.com/ja-jp/sql/sql-server/install/hardware-and-software-requirements-for-installing-sql-server-2022?view=sql-server-ver16


JP1/Base





















![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363928/312c9606-93ac-40f6-a265-d8a40203f07f.png)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363928/655b5875-1d13-435c-af24-04d77e4a1180.png)
ROS2でnodeが終了してしまった時に再起動させる

# 内容

`respawn=True`を設定してあげたら良さそう。

```python
from launch import LaunchDescription
import launch_ros.actions


def generate_launch_description():
    return LaunchDescription(
        [
            launch_ros.actions.Node(
                namespace="turtlesim1",
                package="turtlesim",
                executable="turtlesim_node",
                output="screen",
                respawn=True
            )
        ]
    )
```

# 参考
https://docs.ros.org/en/rolling/Tutorials/Beginner-CLI-Tools/Launching-Multiple-Nodes/Launching-Multiple-Nodes.html
https://github.com/ros2/launch_ros/blob/rolling/launch_ros/launch_ros/actions/node.py
【AWS】各ECSタスクのCPU利用率の推移の調べ方

# 概要
EC2 on ECSタスクの構成で、各タスクのCPU利用率の推移ってどうしたらわかるんだろう？と思って調べてみました。

## ①CloudWatchメトリクス

CloudWatchメトリクスには、ECSクラスタ、サービス単位でのCPU利用率(CPUUtilization)の推移は確認することができましたが、タスク単位では存在しないようです。


## ②Container Insights

Container Insightsは、ECSクラスタやタスク単位のメトリクスが取得できるサービスです。
ざっくり言うと、ECSクラスタでこの機能をオンにして、CloudWatchの画面からInsightへ飛ぶだけで見れるようになります。

詳細は以下の記事がわかりやすかったです。

https://dev.classmethod.jp/articles/container-insights-ga/

> 下に「Task performance」が表示されており、各タスクの負荷状況を個別に閲覧できます。これが欲しかったんやで！！

上述の通り、各タスクの負荷状況を確認することはできます。
ただし、これは平均使用率らしく、各タスクのCPU利用率の「推移」についてはわからないようでした。

惜しい...

## ③`docker container stats`コマンド

ECSタスクが起動しているEC2サーバに入り、`docker container stats`コマンドを使うと、以下のように各タスクのCPU利用率がわかります。
目視での観測になりますが、これであれば各タスクの利用率推移がわかりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/f85666dd-a2e3-122f-b931-721890aeb26d.png)

100%に近いもの、もしくは超えるものがあればvCPUが足りないな、など確認が可能です。
また、タスク分散が均等に割り振られていないことなどがあれば、それもここで確認できますね。

せっかくAWSにはCloudwatchメトリクスがあるので、タスクごとのCPU利用率の推移がわかる画面があると嬉しいんですが...今後に期待（知っている方がいたらぜひ教えてください）。
Juliaで自作Pythonパッケージを呼び出す手法

# 結論：パスを追加しましょう

`PyCall` で自作パッケージを `import` するとき、実行場所のパスをPythonのパスに自動で追加してくれないらしいです。なので、事前にJuliaのパッケージなり、実行するJuliaファイルなりのパスをPythonのパスに追加すれば問題は解決します。

ただ、実行箇所によってパスが変わるといけないので、`@__DIR__` を使っておくのが一番良いかと思います。

https://github.com/JuliaPy/PyCall.jl/issues/502#issuecomment-433285447

下記がおそらく最小構成です。

```MyJuliaMod.jl
module MyJuliaMod

using PyCall
const mypymodule = PyNULL() # https://github.com/JuliaPy/PyCall.jl?tab=readme-ov-file#using-pycall-from-julia-modules

function __init__()
    pushfirst!(pyimport("sys")."path", @__DIR__) # これが大事！！
    copy!(mypymodule, pyimport("your_python_module"))
end

export mypymodule # モジュール名なしで呼び出しを行うのに必要

end
```

```your_python_module.py
def greed():
    print("hello.")
```

# 参考にした記事

https://github.com/JuliaPy/PyCall.jl/issues/502

https://discourse.julialang.org/t/local-python-file-in-module/91080

https://discourse.julialang.org/t/importing-a-python-module-from-another-directory/28310/3

https://www.juliasos.com/integration/local-python-file-in-module/

https://github.com/JuliaPy/PyCall.jl?tab=readme-ov-file#troubleshooting
リバースプロキシ×Nextcloudの環境構築のために必要なこと

環境変数として以下の4つを追加で設定する。

```
OVERWRITEPROTOCOL=
OVERWRITEHOST=
OVERWRITEWEBROOT=
OVERWRITECLIURL=
TRUSTEDPROXIES=
```

```dokcer-compose.ymlの例
services:
  db:
    container_name: nextcloud-db-container
    image: postgres:16.2
    env_file:
      - .env
    expose:
      - "5432"
    volumes:
      - db_data:/var/lib/postgresql/data
      - ./database/postgresql.conf:/etc/postgresql/postgresql.conf
    command: -c 'config_file=/etc/postgresql/postgresql.conf'
    restart: always

  app:
    image: nextcloud
    env_file:
      - .env
    ports:
      - ${NEXTCLOUD_PORT}:80
    links:
      - db
    volumes:
      - nextcloud:/var/www/html
    restart: always
    depends_on:
      - db

volumes:
  db_data:
  nextcloud:

```

```.envファイルの例
# postgresql(docker)
POSTGRES_DB=
POSTGRES_USER=
POSTGRES_PASSWORD=
POSTGRES_HOST=
TZ=

# nextcloud(docker)
NEXTCLOUD_PORT=
NEXTCLOUD_ADMIN_USER=
NEXTCLOUD_ADMIN_PASSWORD=

# nextcloud
NEXTCLOUD_TRUSTED_DOMAINS=
OVERWRITEPROTOCOL=
OVERWRITEHOST=
OVERWRITEWEBROOT=
OVERWRITECLIURL=
TRUSTEDPROXIES=
```

参考↓

https://docs.nextcloud.com/server/30/admin_manual/configuration_server/reverse_proxy_configuration.html
Proj #001 キャンバスアプリで支払申請のフォームを作成するゾ～第5回 委任の問題が解決しないならもうDataverseを使おう～

https://qiita.com/Novskiiiiiiiiii/items/c0ea6c4ccc1ef6dab4fc

もう超しんどい。

キャンバスアプリで別のリスト（取引先マスタ）からChoisesしてたんだけど、アイテムの件数が数万あって委任問題に喘いでいたわけ。

で、試行錯誤して脳みそねじれるくらいトライして、もうDataverseでやろうと思ってそっちでも試行錯誤してたんだけど、もうあかん今日は諦めて退勤しようと思ったその時。

できたのよ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3891071/d0efd77e-6c4e-5b1a-4f02-d5a7ef42691b.png)

上のテキストフィールドに取引先コードを入れると、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3891071/33e7a9a0-abac-5280-7b57-8b480b64fd7b.png)

あーめっちゃ嬉しい。

諦めたらそこで試合終了だわホント。

ちなみにコードは何のこっちゃないシンプルなもの。

    Filter('相手先コード一覧s', タイトル=TextInput1.Text)

でミソなのはここよ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3891071/203f4bfc-1930-c4e0-ded2-ef17bab1771c.png)

Dataverseから列を持ってくる場合、ここでValueを選択する必要があるようだ。

実務でDataverse使うの今日が初めてだからそんなの初めて知ったよ。

ちなみにDataverseのテーブルは、もともと使ってたリストからインポートした。

動作確認だけのために空のキャンバスで実験してただけだから、
本体のフォームへの反映は明日やろう。

、、、と思ったけどキリが悪いからちょっとだけいじった。

もとのフォームに設置してたのがDataCardだったから、
コンボボックスを追加して、DisplayMode.Disabledに。

これで、テキスト入力フォームに入れた取引先コードを、Dataverseのテーブルから検索して
コンボボックスに表示する事が出来た。

コンボボックス使えないのは見た目的に微妙だけど、
数万レコードから見つけるよりコードを入力してもらう方が
ユーザビリティは高いはず。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3891071/d97d19fa-3649-b00b-d7d1-2d3ef1123703.png)

あとはここにセットされた値をもとに制御してる部分をメンテして、
いらなくなったDataCardを削除すればイケるはず。

最初にDatacardを削除しちゃうとなんか色々エラーが出たから最後に消す。
キャンバスアプリってマジでデリケートなやつだね。

何はともあれ、希望の光が見えた状態で眠れます。
ここ数日でかなりキャンバスアプリと仲良くなった気がする。

あと、フォームはマジでこまめにパッケージのエクスポートしといた方がいいね。
エクスポートする前に公開するのも忘れずに。

公開しないでエクスポートするとデフォルトのフォームがエクスポートされて後悔すること必至だから、
ローカルで編集したアプリは公開してエクスポートするように。

まあ本番リリースしたあとはそうはいかないだろうけど。
そのへんはよしなにやってくれ。

病み上がりというかまだ全然コンディション良くないからさっさと寝る。

それではまた。

追記：後日談
Dataverse使わなくても解決した。

https://qiita.com/Novskiiiiiiiiii/items/97e79643e873fdedd85b
+=演算子について

-------2024/11/27------

勉強していたらいきなり出てきました「+=」
```ruby
this.Left += e.X - mouseX;
```
+= と記載すると、左辺の変数に右辺の値が足されるみたい。

なので
```ruby
this.Left =this.Left + e.X - mouseX;
```
と同じっちゅうわけやな。
Enhancer for YouTubeでミニプレイヤーで動画を見ながらタイムスタンプをクリックしたときに勝手にスクロールされなくする

## はじめに

拡張機能[Enhancer for YouTube](https://chromewebstore.google.com/detail/enhancer-for-youtube/ponfpcnoihfmfllpaingbgckeeldkhle?hl=ja)を導入すると、Youtubeがめっちゃ便利になります。
この機能の一つにミニプレイヤーというものがあり、下にスクロールすると動画が固定位置で再生されるので、動画を見ながらコメントや関連動画を確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3485511/f6d4ed54-d755-1477-6e20-ae6de47003c1.png)


しかし、**タイムスタンプをクリックすると勝手に一番上までスクロールされます。**
コメント欄の続きを確認したいときに、下まで再度スクロールする必要があり、大変不便。
この挙動を回避すべく調べたところ、シンプルな解決方法を見つけたので備忘録として残します。


## 解決方法
1. **Enhancer for YouTube**の設定画面を開き、カスタムスクリプトに以下のコードを貼り付けて保存
2. 「YouTubeがタブに読み込まれたときに自動的にスクリプトを実行する」のチェックボックスを有効化

```javascript
document.addEventListener('click', (event) => {
    // クリックされた要素がリンクであるか確認
    const target = event.target;
    if (target.tagName !== 'A') return;

    // YouTubeのリンクであるか確認
    const isYouTubeLink = target.href.includes('youtube.com/watch');
    if (!isYouTubeLink) return;

    // 同じ動画かどうかを確認
    const currentVideoId = new URL(window.location.href).searchParams.get('v');
    const targetVideoId = new URL(target.href).searchParams.get('v');
    if (currentVideoId !== targetVideoId) return;

    // タイムスタンプが含まれているか確認
    const hasTimestamp = new URL(target.href).searchParams.has('t');
    if (!hasTimestamp) return;

    event.preventDefault();  // デフォルトのリンク動作を無効化
    event.stopPropagation(); // イベントのバブリングを停止

    // 動画要素を取得
    const videoElement = document.querySelector('video');
    if (!videoElement) return;

    // タイムスタンプを取得
    const timestamp = new URL(target.href).searchParams.get('t');
    if (!timestamp) return;

    // 非数値文字を取り除いて数値に変換
    const timeInSeconds = parseFloat(timestamp.replace(/[^\d]/g, ''));
    if (isNaN(timeInSeconds)) return;

    // 動画の再生位置を設定して再生
    videoElement.currentTime = timeInSeconds;
    videoElement.play();
}, true);
```

これにより、タイムスタンプをクリックしても勝手にスクロールされなくなります。
AWS SCS-C02合格記

# はじめに
AWS認定資格のAWS Certified Security - Specialty (SCS-C02)に合格したので、その合格記について書いていこうと思います。以前、SCS-C01(前バージョンの試験)では、既に合格しており、その更新で受けております。
# スコア
以前のスコアと比較すると、3年分の業務での実績がプラスされたことで、以前よりは少しスコアが伸びたかな。って感じです。(更新と書いているけど、期限をすっかり忘れて1回失効してます笑)

| 受験日 | 資格名称 | スコア |
|:-----------|------------:|:------------:|
| 2021/04/04     | SCS-C01        | 777         |
| 2024/11/27     | SCS-C02      | 810      |

あとは、細かな配分についてだと、こんな感じです。

**SCS-C01**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252895/01e94611-1416-056d-37db-6900c1203495.png)

**SCS-C02**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252895/cad2f0da-8e8b-0850-9523-4cc702c1328d.png)

今回の試験では、**第 2 分野: セキュリティロギングとモニタリング** が改善が必要と判定されました。(((あらら。まだまだ、勉強不足ですね。。。(´・ω・)

#  勉強した内容について
今回の試験で、勉強した内容は、下記リンクの問題集をひたすら解いただけです。

https://cloud-license.com/

# 試験についての所感
今回の試験で感じたことは、「細かなポリシー関連の問題が予想以上に出るな」と感じました。AWSでは、必要最小限の権限付与が一番のセキュリティ対策だぞ。と訴えてきているようで、ちょっと耳が痛かったです（笑）普段、AWSのマネージドポリシーをフル活用しているので、この機に権限付与の考え方を改めないといけないですかね(;´･ω･)
あとは、普段使ったことがないAWSサービスもいくつかあり、いい勉強になりましたね。特に下記のサービスについては、「あらら、初めまして～」状態で、学ぶいいきっかけをいただきました。

- Amazon Detective
- AWS Audit Manager
- AWS Signer

# 最後に
資格試験って、普段の業務では触らなサービスを知るきっかけにもなるので、いい刺激になりますね～
【Salesforce】【サブフロー】フロー開発でDRY原則を適用する

Salesforceのフローには、「サブフロー」という機能が用意されています。
処理を分割して管理しやすくするためのものですが、同様の処理を繰り返す際に
実装をシンプルにしてくれる効果があります。（＝DRY原則(Don't Repeat Yourself)）

実際の要件を例に説明します。

#### 要件
平日の朝に、自分の承認待ちで止まっているレコードがあれば、その一覧を
　　　通知するメールを送る。1件もなければ何もしない。これを担当者ごとに実行する。

以下のように機能を分割して実装しました。
①スケジュールフロー：平日の朝に実行するようスケジュールを設定する
　　　　　　　　　　　処理の中で担当者の分だけ②を呼び出す
②サブフロー：①から渡された担当者に関して、承認待ちレコードが存在するか確認する
　　　　　　　1件以上存在した場合、③のURLを記載したメールを送信する
③レポート：自分（＝ログインユーザー）の承認待ちレコードの一覧を表示する


#### ①スケジュールトリガーフロー
土日 or 平日で分岐。平日の場合、担当者の分だけサブフローを呼び出す。
「担当者名（person_name）」「宛先メールアドレス（toAddress）」を渡している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336848/d17b921d-aeb0-2d4d-d76d-ee1cc0fb6cf2.png)

#### ②サブフロー
承認待ちレコードが存在した場合、メール送信

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336848/2fd23ec6-ebe6-e3f1-a2af-e4a1c7c20310.png)

「person_name」「toAddress」は「入力で使用可能」にチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336848/377b1a4d-91ad-4b0e-15f4-bc3af7b29052.png)




#### ③レポート
本記事の趣旨から外れてしまうので別記事にまとめました。
→ [【Salesforce】自分の承認が済んでいないレコードが存在する場合、その一覧を毎朝メールする](https://qiita.com/kagehikozaemon/items/ca4d03fae861ec7db65f)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336848/f2492028-c747-cec8-220d-8ec558c2a05e.png)

<br />
サブフローを用いることで似た処理を複製する必要がなくなり、保守性が向上します。

今回の例の他に、『「取引先の重複を調べて自身の項目にセットする」処理をサブフローにまとめ、それをトリガーフローやスケジュールバッチから呼び出す』といった機能郡を実装したりしました。
近い内にそれも記事にしようと思います。

サブフローをうまく使いこなせると、フロー開発者として初心者レベルは卒業できたと言って良いのかなと思います。
はじめまして

## はじめまして
はじめまして。ちなっぷです。
現在（2024年11月時点）26歳の女子です。
Javaエンジニアの兄に憧れて、25歳の時にエンジニアへキャリアチェンジする決意をしました。
主にバックエンドは**Java**、フロントエンドは**React**や**Next.js**を勉強中です。
主な学習方法は:point_down:です。

**無料：**
-ブログ記事
-YouTube
**有料：**
-[Udemy](https://www.udemy.com/)
-[ShinCode_Camp](https://code-s-school-5bc2.thinkific.com/bundles/shincode-camp)


これからよろしくお願いいたします。
STYLY Mobileの平面検知、実は天井でも使えます。

# はじめに
STYLY Mobile皆さんは使ってますか？最近はイベントタブが増えて、STYLY Mobileを利用したイベントも開催されてますね。今回の記事はSTYLY Mobileのお話なので、お手元のスマホにまだインストールされてない方は、ぜひお手元でアプリを起動しながらご覧ください。
 [STYLY Mobileのインストール方法](https://styly.cc/ja/manual/how-to-experience-styly-mobile-by-smartphone/)
 [AppStore](https://apps.apple.com/jp/app/styly/id1477168256)
 [GooglePlay](https://apps.apple.com/jp/app/styly/id1477168256)

本題ですが、STYLYでARを初めて作る方はきっとSTYLY Studio標準のAR Templateをベースに作るはずです。STYLYの標準のAR体験は、任意の床面にARを登場させるものになります。任意の床面に登場させるために平面検知するわけですが、平面を認識するとその位置にアイコンが出ます。こんな感じ。
 <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197699/f2392ba9-d189-aced-e923-a399f284acee.png">

では、そのまま天井にスマホを向けるとどうなるでしょうか。
 <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197699/27e35657-b704-f281-fd09-33770cd6121a.png">
ご覧の通り、天井でもばっちり認識してますね。いつから私たちはSTYLY MobileでのARは床にしか出せないと誤解していたのでしょうか。

ぜひ、これを機に皆さんも天井AR作ってみてください。
<完>











ここで終わってもよかったですが、折角なのでもう少し天井ARについて考えてみます。

# STYLY Studioで天井ARを作る
普通にSTYLY Studioで作るときは、原点より高い位置に置きます。これにより、床に置いてあるように見せているわけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197699/d1f96cdf-1c8d-101a-0b96-82476b2ee0ab.png)

天井ARをする場合は逆に、原点より低い位置に置きます。これにより、天井にぶら下がっているように見えるわけですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197699/68420835-f9bb-5571-b0e2-04aaf6267e71.png)

[上記シーンを公開しました。](https://gallery.styly.cc/scene/64d02ca6-de94-4107-bd87-dbb138026643)実際に動かしてみます。
床面ARすると、床より下に配置したゴリラが見えませんね。
![IMG_5023.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197699/f5435e42-7c4b-61a6-b8dd-d4d1cf997a4f.png)
逆に天井ARすると、天井より上に配置したゴリラが見えません。
![IMG_5024.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197699/b660c29b-f72d-abf9-62ca-684815f02242.png)
これはSTYLY StudioのEnable AR Occulusionアセットを配置していることで、現実のモノに合わせて奥行き表現してくれてるわけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197699/1d0ad86d-0bbd-1969-8bc0-16f56c58bce8.png)
この機能のおかげで、1つのARコンテンツを作るだけで床面も天井も両対応でどこにでもゴリラを登場させられるコンテンツを作ることができましたね。

それ以外の天井AR利用方法で思いつく使い方として、天井を突き抜けて空が見える、といった表現でしょうか。
STYLY Studioの注意点で、Skyboxで空を配置するとVRコンテンツと認識される点に注意して作ってみてください。代わりに空の画像などを配置するイメージですね。また、天井より奥に配置したものは、前述のEnable AR Occulusionにより見えなくなってしまいます。これを回避するためにEnable AR Occulusionを削除してください。
これだと天井を突き抜けた感が出しにくいので、任意の形状のオブジェクトを使ってOcullusionさせることができます。STYLY Studioで3D Object->PrimitiveからBoxなど配置し、ModifierでAR Occulusion Maskを追加するだけです。Modifierをご存じない方は[マニュアル](https://styly.cc/ja/manual/modifier-starter-guide/)をご覧ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197699/3ad5e8c9-463a-7045-2646-09dd1f2b5a88.png)
さて、この機能を使って[適当に1つ作ってみました。](https://gallery.styly.cc/scene/eb59d1f1-b82a-4afd-96ba-b5c347e6320b)最近のアニメでダンダダン見てるんですが、妖怪などいきなり出会っちゃった感しますかね。しますね。してます。
![IMG_5027.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197699/e11e7d95-3e04-16cf-5d74-c343139a2892.gif)


# おわりに
そろそろ皆さん、天井ARの可能性に気付いてきたのではないでしょうか。
STYLYのARはほかにもImmersalなどVPSを利用したものが主流になりつつありますが、たまにはユーザーに天を仰がせてやりましょう。