OmniAICreator/Qiita-1.07M huggingface dataset:
残念なUI設計を行わないために考慮すべき5つの状態(UI Stack)

# はじめに
UIの設計を行うときに理想とする状態だけを作成したために、実装の段階でローディング中のUIが足りないことに気づき改めてUIの設計を考え直したことはありませんか。私は似たような経験が何度かあります。この記事ではそのような手戻りや実装漏れをなくすために設計時に心がけると良い5つの状態を紹介します。

この記事は[scotthurffの記事](https://www.scotthurff.com/posts/why-your-user-interface-is-awkward-youre-ignoring-the-ui-stack/)を参考に記述しています。利用した画像の幾つかはこちらの記事から拝借しています。

# UI Stack
読み込み中に何の画面も表示されずユーザーが今どのような状態になっているか分からず不安になってしまうことがあります。このような現象はあるルールに従うことで起きにくくなります。その一つとしてUI Stackというルールがあります。
![ui-stack.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591069/9a07cb40-9042-facc-6418-f200b796f96a.jpeg)
UI StackではUI設計を行うときに忘れてはいけない5つの状態があります。
- Blank State: 空の状態
- Loading State: 読み込み中の状態
- Partial State: 中途半端な状態
- Error State: エラー中の状態
- Ideal State: 理想的な状態
UI設計時に全ての状態を含める必要はありませんが、これらを考慮することで良い設計ができます。

## Blank State
Blank Stateには3種類の状況が存在します。ユーザーが初めて利用したとき、ユーザーが能動的にデーターを空にしたとき、検索などの結果で表示するデータが存在しなかったときです。
### 初めて利用したとき
この状況はデータが存在したときに表示されるものの説明、データ作成などの行動促進、行動をすることでどのようなメリットを得られるかを説明できるチャンスです。この方法によってそのアプリもしくは機能の第一印象を与えます。
具体的な設計として以下のようなものが考えられます。
- ユーザーがその画面でしばらく行動を起こさなかった場合画面の端でヒントを出す
- 起こして欲しい行動をジェスチャーで表示しつつアプリケーションの紹介をする
- ダミーデータをおいてユーザーに行動後のイメージを想起させる

### データを空にしたとき
この状況は起きにくいように考えられますが、通知を空にしたときやTODOリストを空にしたときなど意外とよくあります。このようなケースでは空にしたことに対して褒めることや次にして欲しいことを紹介することでユーザーが満足感得たりや次に行う行動を知ることができます。

### 結果が存在しない
この状況はユーザーが何かを探した結果存在しなかったことを意味するので、ユーザーが探したかった何かをサポートすることが良い手法です。AmazonやGooglでは結果が存在しなかった場合は類似した単語で検索した結果を表示するようにしています。他にもそもそも結果が存在しない状態を作らないためにタグなどを設定して定型文でのみ検索できるようにすることでBlank Stateを作らないように対策することができます。

## Loading State
データを読み込んでいるとき、インターネットに接続しているとき、ページの遷移しているときなどの状況で読み込み中の状態を設計する必要があります。
### 部分的に読み込ませる
データを読み込んでいるときにページ単位でSpinnerなどで読み込み中の状態を表現するのではなく、データを必要としている部分だけをSkeltonに置き換えて用意出来次第表示させるような表現にします。下の例は[materil ui](https://mui.com/material-ui/react-skeleton/)のサンプルを拝借しました。データが準備できた記事から表示させていくようなものとなっています。
![スクリーンショット 2022-12-11 18.39.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591069/9af8dfcd-0f19-228a-947d-bc23fbfaf0b9.png)

これによってどのようなコンテンツが表示されるのかが分かりやすくなることや、読み込みが不要な部分や完了した部分へのアクセスが可能となりユーザーからの印象が大きく変わります。

### ユーザーの行動を即時反映させる
例えばTwitterの機能であるいいねをユーザーが押したときにサーバーに送信して結果が返ってきてからユーザーの画面に反映するのではユーザーは行動に対する結果をすぐに得ることができず、満足な体験を得ることができません(Twitterの実装が実際にどうなっているか確認したものではありません)。ユーザーの行動をユーザーの画面ですぐに反映し、裏側でサーバーとの通信を行わせることでユーザーのストレスが少ない状態で利用させることができます。これLoading Stateをユーザーに悟らせないようにするための戦略です。

## Partial State
この状態が一番想像しづらい状態だと考えています。この状態はBlank StateとIdeal Stateの中間のような状態を指します。例えばアカウントに登録して欲しい項目として名前、誕生日、住所があったときに、名前と誕生日しか登録されていない状態がPartial Stateです。この状態ではユーザーにIdeal Stateにするために導くための設計が必要となります。必要なタスクと完了したタスクを一覧にして表示したり、どの段階まで進んだかを表す進捗表示を行うことでユーザーに対してIdeal Stateになるための行動の促進を行うことができます。

## Error State
この状態はフォームデータが正しくない、ネットワークやサーバーに接続できない、タスクを完了せずに次の状態に進もうとしたときなど様々なケースがあり、さらに複合して行われることも考慮しなければいけないので複雑な状態となります。Error Stateにするためにユーザーのデータを失うような設計やエラーの静的な検出はできるだけ避けた方が良いです。また、曖昧な表現や技術的な専門用語、画面の大きな変更は避けるべきで、何をすれば良いかを簡潔に分かりやすく伝えるような表現にすると良いです。

## Ideal State
アプリや機能の最終的な状態で作り忘れることはない状態です。この状態に関して記述することはほとんどないですが、他の状態から遷移と他の状態への遷移を考慮して作成すると画面の変化が少ないストレスない画面を構成することができます。



# 最後に
UI Stackを意識した設計を行なって、より良い価値を迅速にユーザーに届けられるようにしていきたいですね。
ServiceNowのGlideRecordでReference項目をdot walkする

こういう書き方が出来ると最近知りましたIncidentのReference項目をdot walkしています

```
var gr_i = new GlideRecord("incident");
gr_i.query();
while (gr_i.next()) {
  gs.info(gr_i.number);
  gs.info(gr_i.short_description);
  gs.info(gr_i.cmdb_ci.name); // dot walk
  gs.info(gr_i.cmdb_ci.company.name); //dot walk x2
}
```

今までこんな書き方してたのですが。。。だいぶ楽に書けました(内部的に同じような処理が走ってるかもですが見た目もすっきりです)

```
var gr_i = new GlideRecord("incident");
gr_i.query();
while (gr_i.next()) {
  gs.info(gr_i.number);
  gs.info(gr_i.short_description);
  var gr_c = new GlideRecord("cmdb_ci");
  gr_c.get(gr_i.cmdb_ci);
  gs.info(gr_c.name);
  var grc_cc = new GlideRecord("core_company");
  grc_cc.get(gr_c.company);
  gs.info(grc_cc.name);
}
```
新しい メール-to-ケース のスレッド化がどういう内容かわからない

テクサポ 日本 10月18日 11:20 の記事の転載です。
個別に記事に直接アクセスできないので...

メール-to-ケースのこれまでの動作では、Salesforce が受信したメールの件名または本文の Ref-ID（ref:XXXXX）という文字でどのケースに紐づくかを判定しておりました。そのため Ref-ID を消してしまうと既存のケースに紐付きませんでした。

今回の新しい挙動では、 In-Reply-To および References ヘッダーに含まれる Message-ID を使用してケースと照合されます。
+ Message-ID、In-Reply-To、References はメールのメッセージヘッダー上に存在します。
+ RFC に記載されているメールのスタンダードの規則では、通常、これらの値がメッセージヘッダー上に存在します。

# 新しい挙動について

メール-to-ケース でやり取りしているメールにそのまま返信すれば、今までの Message-ID が References に残っている状態であるため、既存のケースに紐づくこととなります。

しかしながら、件名や本文の内容が一緒だったとしても、メールを「新規作成」から送信してしまうと、既存のケースには紐づきません。なぜなら、Reference に今までのやり取りの Message-ID が残らないためです。

新しい挙動が自身の組織で適用されているかどうかの確認方法は以下の通りです。
+ Winter '21 以降に作成された組織では自動的に有効になります。
+ 組織でメールヘッダーベースのスレッドを使用していることを確認するには、[設定] の [メール-to-ケース] ページに移動します。[メール件名にスレッド ID を挿入] と [メール本文にスレッド ID を挿入] という設定が表示される場合、メールヘッダーベースのスレッドに更新する必要があります。これらの設定が表示されない場合、更新は必要ありません。

本記事に関する詳しい内容については以下の内容をご参照ください。

+  [【メール-to-ケースのスレッド】](https://help.salesforce.com/s/articleView?id=sf.support_email_to_case_threading.htm&type=5)
+ [【メール-to-ケースの無効化された参照 ID と新しいスレッドの動作】](https://help.salesforce.com/s/articleView?id=000355168&type=1)
GraphQLサーバーを構成する要素

[Next.js + サーバーサイドTypeScript + 関数フレーバーでクリーンなアプリを作ったので実装意図とか書く Advent Calendar 2022](https://qiita.com/advent-calendar/2022/shwld)
の**12日目**。[株式会社mofmof](https://www.mof-mof.co.jp/)に生息している[shwld](https://twitter.com/shwld)です。

前日は[リポジトリ層](https://qiita.com/shwld/items/b4de03555f0e91a4f3ca)について書きました
# GraphQLサーバーを構成する要素

GraphQLのサーバーサイド実装は [@graphql-codegen](https://the-guild.dev/graphql/codegen)をメインにThe Guildのツールを多数使って実装しています。
いろいろ試していますがまだ、これがいい！みたいなのは自分の中で見つかっておらず、experimentalな感じです。

利用しているパッケージは以下。

## Next.js配下
Next.jsのapiルートで使うためのパッケージです。

### [GraphQL Yoga](https://the-guild.dev/graphql/yoga-server)
GraphQLサーバーです。サーバー自体はNext.jsのAPIルートを使っておりfastifyなど他のライブラリは使ってません。

### [GraphQL Envelop](https://the-guild.dev/graphql/envelop)
Yogaを拡張するために使っています。
ContextやLoggerなどを使えるようにしています。

## GraphQLリゾルバ
GraphQLのリゾルバはNext.jsとはレイヤーを分けています。
また、ユースケース層は分けず、GraphQLリゾルバをユースケース層として扱っています。
リゾルバーを作るために使っているパッケージは以下です。

### [@envelop/generic-auth](https://the-guild.dev/graphql/envelop/plugins/use-generic-auth)
- コンテキストとして受け取ったユーザーを認証する
- ユーザーが存在しない場合にどうするかなどまだ、ちゃんと設定できてない

### [@graphql-codegen](https://the-guild.dev/graphql/codegen)
- GraphQLのschemaからリゾルバの型を生成するために使っています

構造化とモジュール整理のために[GraphQL Modules](https://the-guild.dev/graphql/modules)も試しましたが、こちらはfsを使ってファイルを引いて来るみたいな仕様が嫌で使っていません。


```ts:/advent-calendar/use-cases/graphql-resolvers/src/index.ts
const executableSchema = makeExecutableSchema<GraphqlServerContext>({
  typeDefs,
  resolvers: merge.all<Resolvers<GraphqlServerContext>>([
    userProfileModule.resolvers,
    storyModule.resolvers,
    projectModule.resolvers,
    accountModule.resolvers,
    viewerModule.resolvers,
  ]),
});
```

[/advent-calendar/use-cases/graphql-resolvers/src/index.ts](https://github.com/shwld/uzumaki/blob/advent-calendar/use-cases/graphql-resolvers/src/index.ts)

### [zod](https://zod.dev/)
- バリデーションライブラリ

### [GraphQL Shield](https://the-guild.dev/graphql/shield)
- これでやっているのはログインしてるかどうかのチェックのみで、細かい認可制御は別でやっています
- これいらないかもなーとか思ったりしなくもない。理由はGraphQL Middlewareの項で

### [GraphQL Middleware](https://github.com/dimatill/graphql-middleware)
- GraphQLShieldを利用するために使っています。
- Middlewareを使うとレイヤー化を促進しますが、個人的にはGraphQL全体を責務でスライスするよりも、feature単位でスライスしたくて、あんまり好みとは合わない気がしています。
- はがそうかなーと思っています。

### [graphql-relay](https://www.npmjs.com/package/graphql-relay)
- relay styleのページネーションを実装するためだけに使っています。
- 後日このカレンダーで記事にします。

# 次回予告
明日は、[GraphQLリゾルバのディレクトリ構造](https://qiita.com/shwld/items/e1b2c7c8440c3048269f)について書きます
STM32H743のI2Cを使い、AQM0802A液晶で文字表示(簡易版)((理系フリマ)でGET)


x NUCLEO-STM32H743ZI2 480MHzのすごいやつ


x 原因は、わからないが液晶がちらつく場合は、ウェートを調整してね!!

目的
I2C液晶のテスト


![o_cop244.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/e3461fbd-8dbd-0b27-12d6-d647d8a01016.jpeg)



arduinoのプログラムと完全に同じ




```c++



//AQM0802A_DEMO1

#include <Wire.h> //I2C library

//i2cバッファー
char data_read[4];

//初期レジスター
char INIT_com[] = {
  0x0, 0x38, //1
  0x0, 0x39, //2
  0x0, 0x4,  //3
  0x0, 0x14, //4
  0x0, 0x70, //5
  0x0, 0x56, //6
  0x0, 0x6C, //7
  0x0, 0x38, //8
  0x0, 0xC   //9
};

//画面のクリアレジスター
char INIT_cls[] = {0x0, 0x1};


//i2c書き込みルーチン
void i2c_lcd_w(char *buff1) {
  Wire.beginTransmission(0x3E);
  Wire.write(buff1[0]);
  Wire.write(buff1[1]);
  Wire.endTransmission();
  delay(2);
}//i2c_lcd_w


void ns_putc(char ch)
{

  data_read[0] = '@';
  data_read[1] = ch;

  //I2Cに送信
  i2c_lcd_w(data_read);

}//ns_putc


void ns_puts(const char *str1)
{

  //文字の中身がゼロか
  while (*str1) {

    //一文字出力
    ns_putc(*str1 ++);

  }//while

}//ns_puts


//カーソルの移動
void setCursor(int col, int rows)
{

  data_read[0] = 0x0;
  data_read[1] = 0x80 +  (rows * 0x40) + col ; //カーソルを移動

  //I2Cに送信
  i2c_lcd_w(data_read);

}//setCursor


//初期化関数
void setup()
{

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

  //液晶の初期化
  for (int ii = 0; ii < 9; ii++) {
    i2c_lcd_w(&INIT_com[ii << 1]);  // ii << 1 = ii * 2
  }//for

  //画面のクリア
  i2c_lcd_w(INIT_cls);

  //表示
  setCursor(0, 0); ns_puts("HELLO");
  setCursor(0, 1); ns_puts("WORLD");

}//setup


//メインループ
void loop()
{}//loop



```
Microsoft データ保護

（この記事は、2021年8月20日に執筆しました）

　テナント内の情報をラベル付けし、情報の保護を適用します。Microsoft 365 のエンタープライズのライセンスと、管理者権限が必要です。

# DLPポリシーの設定

### 1. [Office 365 セキュリティ/コンプライアンス](https://protection.office.com/homepage)から「データ損失防止」の「ポリシー」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/4470e058-6cb1-4360-75bf-77c9b78ebe15.png)
　あるいは、[**Microsoft 365 コンプライアンス**](https://compliance.microsoft.com/homepage)から「データ損失防止」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/b51116f5-4f3a-073c-7eb4-405338f4840e.png)

### 3.「ポリシーを作成」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/d1f20a9e-5ba1-2600-fd25-0b46598ba43b.png)

### 4. カテゴリから「カスタム」、テンプレートから「カスタムポリシー」を選択し、「次へ」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/3482416d-0d6a-5700-57b9-7e3ccdf3a8ff.png)
### 5. DLPポリシーの名前を設定して「次へ」を押します。

### 6. ポリシーを適用する場所を全て有効にして「次へ」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/5411d06f-0939-843a-575f-6fcc35811edd.png)

### 7. ポリシー設定の定義は、「詳細なDLPルールを作成またはカスタマイズします」を選択して、「次へ」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/98542ba7-6eb0-30bc-98da-cdd2178d2aad.png)

### 8. ルールの作成で、適用する条件を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/e3f402af-d092-beeb-2a0b-c281f7bce573.png)

### 9. アクションを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/5bb35f8b-a1bf-d05c-43b5-ca422ea99621.png)

### 10. ユーザーへの通知、管理者へのアラート等が必要な場合はオンにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/6a5aa76a-82d4-3db0-839f-3500b0f47f8c.png)
### 11. 新しいルールの内容が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/f6755d50-ba7c-d3a4-c2b3-3d80658453a9.png)
### 12. 適用する前にテストをします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/cd7e9b47-ed30-95bf-3c64-888c26e983d2.png)
　**新しいDLPポリシーは、すぐには反映されず、マイクロソフトのドキュメントでは、1時間以内に反映すると書かれています。**

---
Power BIデータモデルの型システム (3) ブランク／ヌル型

# 5.ブランク型／ヌル型（Blanks/null）
 データベースnull値とExcelの空白が読み込まれたとき、Blankに置き換わります。DAXでは、null、空白値、空のセル、または欠落値はすべてBLANKで表されます。
　Power Queryで作成されたテーブルにあるnullと「""]をテキスト型と整数型に変換すると、以下のようになります。

```text:null&Blank
let
    Source = 
        Table.FromRecords(
            {
                [CustomerNumber = 1001, Name = "Tanaka", Value = 10],
                [CustomerNumber = 1002, Name = null, Value = null],
                [CustomerNumber = 1003, Name = "", Value = ""]
            },
            type table[CustomerNumber = Int64.Type, Name = Text.Type, Value = Int64.Type]
        )
in
    Source
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/cf99ee9f-71e0-8be3-60fa-d49ae51fee92.png)
　このまま読み込むと、「""」がInt64.Typeで解決できないためエラーになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/22a4117a-880d-45e3-6e35-d3cb6e2cba32.png)
　数値型は「""」を暗黙的に変換することはできないので、Power Queryで事前に変換作業を行う必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/0e073fc6-3402-1433-983d-2ed81059cf07.png)
　変換(Int64.From(""))されると、結果はnullになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/9ec18e7c-4d39-9241-92a8-88f0b5b7735c.png)
　テキスト型は、「""」はそのまま読み込むことができますが、nullはBlankに変換され、「""」は長さ0の文字列になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/7a3fc0db-c7c0-9094-eabc-6b6295b1c80f.png)

# 6.バイナリデータ型（BINARY）
　バイナリのデータ型がメニューに表示されますが、Power BIデータモデルではサポートされていません。バイナリ列を読み込もうとするとエラーが発生する可能性があります。
paiza.ioでelixir その141

# 概要
paiza.ioでelixirやってみた。
練習問題やってみた。
構想編

# 練習問題
オセロを書け。

# 方針

- 盤の表示

```
   A B C D E F G H
1
2
3
4        ○ ×
5        × ○
6
7
8
```

- データ構造

```
	[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

```

- 置く

盤に、石を置く。

- チェック

そこに石が置けるかチェックする。

- 色を変える

８方向で石の色変える

- 指す

定石を指す

- 終わり

終わりかチェックする

- 判定

どっちが勝った

- フロー

黒が指示
チェックして、置く（色が変わる）
盤を表示
白が指す（色が変わる）
盤を表示
終わりか
繰り返す
判定

以上。
【Linux】現地調査用情報収集スクリプト

# Linuxサーバの情報収集用シェルスクリプト

``` gathering.sh
#!/bin/bash

TODAY=`date +%Y%m%d`
#INTERVAL="3"

command_list(){
        ps aux
        sysctl -a
        rpm -qa
        systemctl list-unit-files --type service | cat
        uname -a
        cat /etc/redhat-release
        systemctl get-default
        cat /etc/passwd
        cat /etc/group
        cat /etc/shadow
        ls -al /home/
        ls -al /var/spool/mail/
        date
        timedatectl show
        chronyc sources
        cat /etc/chrony.conf
        cat /etc/nsswitch.conf
        env
        cat /etc/environment
        getenforce
        systemctl status firewalld
        ls -al /etc/skel/
        ip addr
        cat /etc/resolv.conf
        cat /etc/hosts
        netstat -tupnl
        ss -tupnl
        ping -c 3 8.8.8.8
        nslookup google.com
        cat /etc/fstab
        mount
        df -h
        lsblk
        blkid
        fdisk -l
        du -hc /home/
        du -hc /var/
        du -hc /etc/
        kill -9 $$
}

while true;
do
        command_list 1>> result_${TODAY}.log 2>> error_${TODAY}.log
#       sleep ${INTERVAL}
done
```
CTO興味ある人へ：CTOの業務についてその３　チームビルディング/評価制度

CTOを長年やってるとよく聞かれる質問です。
```
CTOの仕事ってどんな仕事があるんですか？
```
から始まった**CTOの業務について**のその３です。

# チームビルディング
最も大きいタスクのうちの一つです。チームメンバーが居ないと仕事は始まりません。チームビルディングが上手く出来ればCTOのタスクの半分くらい終わった感じではないでしょうか。ただこのタスクのボリュームは大きいです。
採用の次は、**評価制度**です。
## 評価制度
評価と給与設計は、色々あります。MBO、OKR、360度評価等ありますが、どれもメリット・デメリットがあります。
ポイントは、下記の４つです。
## １．エンジニア独自に評価・給与設計を行う事
エンジニアは、評価部分や成長速度等が違うため総合職の方とは全く別の評価制度を構築する必要があります。
特に若手エンジニアでは、スキル部分の育成が重要で、
スキルは
- 開発言語
- サーバー
- フレームワーク
- データベース
- ネットワーク
- フロント
- アプリ

等幅広い部分についての評価制度をしっかり入れ込む必要があります。
そして一番問題なのは**給与テーブル**です。
エンジニアの給与は、賃金水準が停滞している日本の中でも賃金高騰しています。リモートワークの普及により世界的にもエンジニアのニーズアップで賃金高騰しています。全社的な他の職種と比較するとバランスが取れない**給与テーブル**になると思います。しかし、給与は最低限必要な条件となるので、絶対に他社に負けない様に作る必要があります。ここはCTOとして強い意思で**給与テーブル**を作り上げて下さい。

## ２．キャリアの柔軟性を作る事
エンジニアには、ビジネス力、エンジニアスキル、マネジメント力の３つが必要となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/14955341-ac9b-b4be-5922-cd0bb5d44842.png)
この３つの何処を伸ばしていくのかを個人で選択できる様なキャリア設定にします。
- ビジネス力を伸ばして技術・開発に強いプロダクトマネージャーになる人
- エンジニアスキルを伸ばしてプロフェッショナルなエンジニアになる人
- マネジメント力を伸ばして、エンジニアマネージャーになる人

各々を評価できる様な評価制度の構築が必要です。

## ３．給与以外の価値を作る事
下記記事でも書きましたが、報酬には、外的報酬と内的報酬があります。給与は、外的報酬のうちの一つです。
外的報酬と内的報酬の設計は、とてもクリエイティブな領域で、CTOだけではなく人事と共に案を出し合って決めていきましょう。当然ながら内的報酬については、エンジニア部署以外の全社的な部分も大きいです。CEO,COOと共に動くことが必要です。
エンジニアマネージャー必見：報酬設計の考え方:
https://qiita.com/k1morikawa@github/items/d13e1a4430d8ba17a5ad

## ４．スキルマップを作る事
エンジニア給与テーブルを作る際にグレード設定をすると思います。このグレードに合わせて必要スキルを定義しましょう。会社によって、アプリが必要な会社もあれば、インフラメインの会社もあると思いますが、可能性を広げる意味で幅広目でスキル設定をして下さい。このスキルは、目安という形にしてマストではないです。しかし、この基準を策定する事で、目線のすり合わせ出来ます。
![スクリーンショット 2022-12-06 7.47.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/88795709-aef8-6da8-3af9-8cd0941907c6.png)

・評価の正当性を担保　→　評価に対して足りないスキルを明確化にして説明しやすさを確保
・キャリアの明確化　→　次に獲得すべきスキルを明確化
・採用時のグレード明確化　→　社内と社外のギャップ分析
・採用計画に適用　→　どのグレードの人数を伸ばしていくかを定義

モチベーションの促進サイクルが形成される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/bbcc7b55-9f35-4350-c0b9-569f2cce8a5f.png)

# まとめ
エンジニアの評価制度は、とても重要な制度です。これが肝となって採用や定着にも繋がってきますので、時間掛けてしっかりとやり切りましょう。評価制度、スキルマップの構築などの相談も受付ます。
kei1.morikawa@gmail.com
ひき続き記事を書いていきますので、フォロー、イイねお願いします！

# シリーズ記事
CTO興味ある人へ：CTOの業務についてその１　会社組織内での話
https://qiita.com/k1morikawa@github/items/5e9022a99a51d9a57576
CTO興味ある人へ：CTOの業務についてその２　チームビルディング/採用
https://qiita.com/k1morikawa@github/items/b2b3fb2246bd0984bab1
eSIMと物理SIMのデュアルSIMのやり方。(IIJ)

ジョブチェンジして、MVNOの中の人になったので、eSIMを使ってみます（技術的興味）。

# ■目的
　SIMカード不要で、通信できるeSIM使ってみたい。

# ■サマリ　デュアルSIMイメージ
データ専用eSIMが440円だったので、eSIMを買い足して、物理SIMとeSIMのデュアルSIMデビューできました。
構成は下記です。
　　サービス名：IIJmioギガプラン タイプD(ドコモ網)
　　　　　　　　**IIJ eSIM [データプランゼロ]**
　　SIM　　　 ：物理SIM + **eSIM**
　　無線回線　：ドコモ回線＋**ドコモ回線**

IIJ ライトMVNO（ドコモ回線）に、IIJフルMVNO（ドコモ回線）が追加される感じ？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/6125f289-84ac-fe44-74f8-3f251711a935.png)
※HSSはIIJのなのか、ドコモのなのかわからず。（フルMVNOとライトMVNOの違いが分からず。）


---以下詳細---

# ■現状
　端末：Pixel 7
　　サービス名：IIJmioギガプラン タイプD(docomo網)
　　SIM　　　 ：**物理SIM**
　　音声　　　：〇
　　データ　　：〇
　　無線回線　：ドコモ回線
　　月額例　　：1,500円　音声＋8G
　　
# ■切り替え後の選択肢
## 案1 物理SIM⇒eSIMに乗り換え[シングルeSIM]
　　サービス名：IIJmioギガプラン タイプA(au網)
　　SIM　　　 ：**eSIM** ~~物理SIM~~
　　音声　　　：〇
　　データ　　：〇
　　無線回線　：**au回線**
　　月額例　　：1,500円　音声＋8G

## 案2 今の物理SIMに追加でデータ専用eSIM[デュアルSIM]
　　サービス名：IIJ eSIM [データプランゼロ]
　　SIM　　　 ：**eSIM**
　　音声　　　：**×**
　　データ　　：〇
　　無線回線　：ドコモ回線
　　月額例　　：440円　データ2ギガ

⇒デュアルSIMしてみたい　案2のデータ専用eSIM追加に決定！

# ■確認
## Pixel 7 の　eSIM対応
　⇒デュアルSIM（eSIM＋物理SIMに対応している様子）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/acdd6f43-24fd-8904-a3ba-c6deeb8a3841.png)
図の出典：https://www.iijmio.jp/gigaplan/esim/phone/

## 料金
　初期費用：2,640円
　月額：440円

## 初期設定
申し込みから5分ぐらいで開通。
https://www.iijmio.jp/hdc/guide/norikae.html
### アクティベーションコード確認 on IIJ web
020番号(11桁)で発行された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/60734c43-dfac-4974-cf52-61086a033bdc.png)

## eSIM有効化
端末でSIMの追加⇒IIJのHPで発行されたQRコードを読み取る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/a99ec7c8-e14c-a7ca-63e4-412a5c7964ee.png)

無事　IIJのアンテナピピクトがたちました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/ff19863f-bcd5-412b-73db-36ebcb777836.png)


# 切り替え後
月額に440円プラスしてデータ専用eSIMをゲットしました。
（両方ドコモ回線なので、冗長の意味はあまりないかも・・・）

　端末：Pixel 7
　　サービス名：IIJmioギガプラン タイプD(docomo網)
　　　　　　　　**IIJ eSIM [データプランゼロ]**
　　SIM　　　 ：物理SIM + **eSIM**
　　音声　　　：〇
　　データ　　：〇
　　無線回線　：ドコモ回線＋**ドコモ回線**
　　月額例　　：1,940円　音声＋8ギガ＋**eSIM 2ギガ**
Edge のブックマークレットについて知らなかったこと

2020 年からアドベントカレンダー期に毎日何かを投稿するという奇祭に参加する習わしがあり今年もゆるゆる参加してみようと思い書くもの。

[ブックマークレットの登録方法 - Qiita](https://qiita.com/aqril_1132/items/b5f9040ccb8cbc705d04)
[今見ているページのタイトルとURLをMarkdown形式で取得するブックマークレット - Qiita](https://qiita.com/rohinomiya/items/55111e2b8e73b4542b89)
[Tips: Qiitaに書いている文字数が知りたい - Qiita](https://qiita.com/e99h2121/items/8c556a1317b5e71d4931)

などということを Chrome でしていたがさて Edge ではどうすればよいのか。
と、思っていたところこんなことが書いてあった。

[任意の Web ページで JavaScript のスニペットを実行する - Microsoft Edge Development | Microsoft Learn](https://learn.microsoft.com/ja-jp/microsoft-edge/devtools-guide-chromium/javascript/snippets?WT.mc_id=twitter#open-the-snippets-tab)

> スニペットは ブックマークレット の代替手段であり、スニペットは DevTools でのみ実行され、URL の許可された長さに制限されないという違いがあります。

スニペットだという。
つまりまあ

```js
console.log(  `[${document.title}](${location.href})`);
```
みたいなものをスニペットのところに登録しておいて

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/abf0e5f6-869c-2879-54a1-02cc5b54940d.png)

F12 押して実行してねっていうことかなあ。

```出力
[Azure サービス プリンシパルを作成する – Azure CLI | Microsoft Learn](https://learn.microsoft.com/ja-jp/cli/azure/create-an-azure-service-principal-azure-cli)
```

IE モードについて調べだすとハマりそうだったので一旦このページを貼って本日の小ネタとしておく。
[IE モードのよくあるご質問 | Japan Developer Support Internet Team Blog](https://jpdsi.github.io/blog/internet-explorer-microsoft-edge/ie-mode-faq/) 
以上私が知らなかったことでした :snowboarder:
コミットする前

```
Sub test()
    Dim cn As Object
    Set cn = CreateObject("ADODB.Connection")
    
    On Error GoTo err
    
    cn.Open "myMySQL_ODBC"
    cn.BeginTrans
    
    Sql = "INSERT IGNORE INTO test VALUES(1,'isao','test','2022-12-12');"
    cn.Execute Sql

    Sql = "INSERT IGNORE INTO test VALUES(1,'atushi','test','2022-12-12');"
    cn.Execute Sql
    
    cn.CommitTrans
    GoTo finally
    
err:
    cn.RollbackTrans
    
finally:
    cn.Close
    Set cn = Nothing
End Sub
```

2個目のSQL分は無視されます
複数のレコードの同時更新とエラー表示/Rails

# やまないエラーはない

　デプロイが終わったはずなのに、まだ大きなエラーがあって、いろいろわやわやしていた。アプリでは振り返りの際に複数の目標の状態を更新したりする。複数の進行中の目標について、進行中から完了に変更させたり、期限を延ばしたりできるためだ。

　複数のレコードを更新するやりかたは過去に学んだ。しかし、それがひとつでもバリデーションエラーがあったらどうなるか。今のコードではエラーが出たやつだけ保存されずに、あとは保存されてしまう。なんかいただけない。

```
振り返り
　振り返りレコード保存OK.

関連づけられた目標達
-　目標A
　　状態変更終了。　進行中→完了
-　目標B
　　締め切り変更　→2002/1/1
   バリデーションエラー：過去の日付は締め切りに設定できない
```

　この場合、振り返りと目標Aは保存される。しかもバリデーションエラーの画面が出ない。どうしよう。

# それより先にその傘をくれよ

　トランザクションという概念を導入しよう。これはその中に入っている処理のうち、ひとつでも正常に処理されないと、他の全ての処理が未完に終わるものだ。銀行のお金のやりとりのシステムとか、そんなものに利用される。

　Railsの場合はtransactionメソッドというのが提供されている。Railsのドキュメントにはモデルのメソッドとして記述されているが、ActiveRecord::Baseとつなげてもかける。

https://railsdoc.com/page/transaction

```ruby
    ActiveRecord::Base.transaction do
      # 同時に行いたい処理
    end
```

　私はその中で
- ひとつのReviewレコードの新規作成・保存
- 複数のPlanレコードの更新

　行っている。ひとつでもできなかったら、バリデーションエラーが出るようにしたい。

```ruby:app/controllers/reviews_controller.rb
#略
def create
#略
# いろんなパラメータ設定
#略

# @plan トップページのバリデーションエラーを表示させるためのインスタンス
    @plan = Plan.new
    all_valid = true
    ActiveRecord::Base.transaction do
      all_valid &= @review.save
      plan_keys.each_with_index do |id, i|
        
        @plan_select = Plan.find(id)
        
        if !@plan_select.update(item[i])
          @plan.errors.merge!(@plan_select.errors)
          all_valid = false
        end
      end

      if !all_valid 
        raise ActiveRecord::Rollback
      end

    end
    if all_valid
      plan_keys.each_with_index do |id, i|    
        @plan = Plan.find(id)
        all_valid &= @review.review_items.create!(plan_id: id)
      end
    end 

    if !all_valid 
      flash.now[:alert] = "投稿に失敗しました"
        @plans = Plan.where(id: plan_keys)
        @review_item_array = Array.new(@plans.size, ReviewItem.new)
        binding.pry
        render :new
    else
      flash[:notice] = "振り返りを投稿しました"
      redirect_to action: 'index'
    end

  end
```

なにを行ったか。まず、 ` all_valid`　は正常に動作が終了したかどうかを示すフラッグだ。　 `all_valid &=　A ` で `all_valid = all_valid && A`ということをしている。

```ruby
@plan.errors.merge!(@plan_select.errors)
```

　これはエラーメッセージをひとつのインスタンスに格納している。ループで回していくと、いろんなインスタンスにいろんなエラーが格納されている。このままエラーを表示させようと思うと、view画面でちょっと面倒な記述をしないといけない。調べたらちょうど良いメソッドがあったので、これを使うことにした。

https://api.rubyonrails.org/v6.1.4/classes/ActiveModel/Errors.html

```ruby
if !all_valid 
   raise ActiveRecord::Rollback
end
```

　これはわざと例外を発生させて、エラーを起こさせている、、のだが本当にこれが正しい使い方なのか。ここらへんはもうちょっと勉強が必要。


# あれが欲しい全て欲しい　ただ虚しい
　
　個人開発に限らず、全てのものはエラーと隣り合わせ。現実世界はエラーが表示されないこともあるので、わりと幸せな世界なのかもしれない。もうちょっと開発していこう。


　トランザクションの処理を書く際に、伊藤さんの以下の記事を参考にした。が、自分の書いたものがこれで正解なのかよくわからない。テストも書かないといけないよなぁ。


https://qiita.com/jnchito/items/3ef95ea144ed15df3637
リモートワーク環境のメンター業務にて重要なポイント

:::note info
本記事は ZOZO Advent Calendar 2022 カレンダー Vol.2の12日目の記事です。
昨日の投稿は @kurosuke1117 さんの 「[5日で100万人超えのChatGPTって何なのか使い倒してみる](https://qiita.com/kurosuke1117/items/e63242456ffa80a04f3f)」でした。
:::

# はじめに
2022年の個人的な初挑戦は『新卒メンバーのメンター業務』でした。
1-3月は内定者アルバイトのメンターを努め、4月以降は同じチームに配属されたメンバーのメンターを担当しています。

弊社はリモートワークを主体とするメンバーが多く、実際に顔を合わせる機会は年に数回しかありません。
私も普段は札幌に住んでおり、２ヶ月に一回程度オフィスに出張するのみです。
そんな状況ではありますが、嬉しいことに新卒メンバー含め数人の新メンバーがチームにjoinして大活躍しています。

私はリモートワーク環境に入ってから4-5人のメンターとして対応しましたが、はじめの頃はリモートワーク環境での新メンバーの対応に慣れておらず数々の失敗を繰り返しました。
しかしながら、２年ほど続けてきたことで汎用的なポイントが見えてきたのでご紹介できればと思います。

# 本記事の対象読者
- 今後リモートワーク環境で新メンバーのメンターを担当する人
- 今後リモートワーク環境に新メンバーとして入る人
- 来年の新卒メンバー受け入れを検討している人

# リモートワーク環境で新メンバーを受け入れる上で意識すること
## 雑談する時間を定期的に確保する
リモートワーク環境では定期的に『チームメンバーと雑談をするための時間』を予定に入れるようにしています。

当初は『業務に関係無い事を予定とするのは迷惑なのでは』との思いがありました。
ですが、新メンバーがチームに溶け込む為に必要な情報を提供するのもメンターの大きな役割の一つになります。
人間は「未知のものに恐怖を感じる生き物」であり、交流が少ない人は恐怖の対象になります。
その恐怖を取り除きチームメンバーに対して恐怖感を抱かない為にも強制的に交流の機会を増やす事は効果的でした。

## 新メンバーを褒める(感謝する)事を意識する
リモートワーク環境では『新メンバーの成果を褒める(感謝する)』事をミーティング内で意識しています。

人によっては当たり前の事だと思うかもしれませんが、とても大事なポイントになります。
『失敗等を注意する時間』は確保しても『成果を褒める(感謝する)時間』をわざわざ確保してない人が多いのではないでしょうか？

リモートワーク環境ではコミュニケーションの量がオフィスと比べて少なくなる事が一般的です。
その少なくなったコミュニケーションの中で『相手を褒める』といった行為は意図せず削減している事が多く、メンバーに対して『成果を認められてない』といった印象を強く与える原因にもなります。

新メンバーの心理的安全性や自尊心を育たせるためにも『褒める(感謝する)』といった行為は意識して行ってください

## 作業進捗等を『説明する』時間を多く取る
リモートワーク環境では『新メンバーが自身の思考/作業を説明する』時間を多めにとっています。

先にも書きましたがリモートワークではオフィス環境より絶対的にコミュニケーション量が少なくなります。
その中で新しい業務に取り組む際に起こりやすい問題が『理解してない部分がわからない』状態に陥る事になります。

リモートワーク環境で情報をキャッチアップを行っている新メンバーは自身の理解度を客観的に測ることが難しく、周囲のメンバーも判定する事が困難になります。
実際に作業をし始めてから『メンターの想定してた理解度』と『新メンバーの理解度』に差があり、想定外の準備作業などが増えていく事が多くありました。

そのため実際に作業を依頼する前に『メンターの想定している理解度』と『新メンバーの理解度』のすり合わせを行う事が重要になっていきます。
効果的な方法としては依頼した作業の進め方を新メンバーから説明してもらい、メンターがチェックするといった形になります。
メンバーの理解が不足している部分を見つけてあげるのもメンターの大きな役割になります。

# リモートワーク環境のメンターは試行錯誤が大事
今回は自身の経験から特に効果を実感したポイントを3点ほどご紹介しました。
細かなポイントはまだまだあるので、いずれ整理して記載したいと思います。

リモートワーク環境で新メンバーのメンターをするのは大変な部分が多いです。
コミュニケーションの量が少ないので相手を推し量るための情報が少ない状態なので細部やニュアンス等が正しく伝わらない事が多いと感じています。
これはメンバー側も同じで、表情を始めとしたメンターの情報が少ないので『自分の受け取り方は正しかったのか』といった不安が常に付きまとう事になります。

これからリモートワーク環境でメンターをする方(もしくはメンターを受ける方)は相手の情報を積極的に取得して二人三脚で進む事を意識してみましょう。
1投稿で192万文字のツイートをしようぜ！あ、ついでにバイナリファイルも！

# はじめに

この記事は、["Tokyo City University Advent Calendar 2022"](https://adventar.org/calendars/8133)の11日目の記事になります！

https://adventar.org/calendars/8133

えっと…投稿遅れてごめんなさい！

# 前置き

皆さんは、Twitter使っていて、こんなこと思ったことはありませんか？？

**あー。このコード共有したいけど、140文字に収まりきらないなぁ…**

やっぱり、ありますか？ありますよね！そう！あるんですよ。
ということで今回は、192万文字のツイートを可能にするアプリを作ってきました。その名も、[**ImageCodeChanger**](https://amefuritell.github.io/amayadori/adventC/ImageCodeChanger.html)です。

# Twitterの仕様

全角で140文字、半角で280文字の投稿制限があります。つまり、280Byteの文字を投稿できるわけですね。

さて、ここで注目したいのが「画像の投稿」です。
画像は、大体5MBまで投稿でき、種類はGIF/JPEG/PNGだそうです。これを聞いて私は、『**ここに文字を埋め込めばいいんじゃね？**』と考えつきました。

そのためには、「**可逆性**」があり「**ツイッターで圧縮されない**」という2つの条件を満たす画像を投稿する必要があります。
今回は、試しに800*800のPNGに埋め込むことにしました。

# 作ったもの

以下のURLから飛ぶことができます。

https://amefuritell.github.io/amayadori/adventC/ImageCodeChanger.html

また、GitHubにコードを公開しておりますのでこちらも参照してください。

https://github.com/AmefuriTell/amayadori

## 使い方

### ファイルを画像へ
「TextコードをImageコードへ変換」の「ファイルを選択」をクリックし変換したいファイルを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562969/61cb08c0-f82d-59a9-e2f8-fdd9862fb6c3.png)

選択し、「開く」を押すと解析が始まり、画像が出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562969/7d4fe1a7-e173-0f7f-db9d-db1e0c3b6999.png)

「画像をダウンロード」を押すと、出力された画像をダウンロードすることができます。

### 画像をファイルへ

「ImageコードをTextコードへ変換」の「ファイルを選択」をクリックし戻したい画像を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562969/df4bde3d-8278-43c3-2b35-85b9251af962.png)

選択し、「開く」を押すと解析が始まり、バイナリのasciiが出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562969/f6ffb6d8-5b58-45d4-aa5f-860c0d87ff59.png)

「データをダウンロード」を押すと、出力されたバイナリをダウンロードすることができます。この時に、拡張子を手動で入力してください。


## 簡単な仕組みの話

画像に変換する際、まず変換したいファイルをバイナリデータとして開き1byteずつに区切ります。次に、3Byteずつ前から順番に取り出しそれぞれRGBの値に割り当てていきます。PNGには透明度の値がありますが、そこにはRGBのどこまでがファイルのバイナリなのか判別するデータを割り当てています。
割り当てが完了したら、800*800pxのPNGデータとして出力します。

逆に、画像からファイルに戻す際は逆の行動をとります。
透明度の値を読み、RGBのデータからバイナリを抽出し、ファイルに書き込むことで復元することができます。

# 使用した技術

今回使用したのは、JSのcanvasとBlobです。
canvasは、主に画像の入出力とRGBへの分解を行ってもらい、Blobはファイルの出力を主に行ってもらいました。

苦労した点としては、Twitterに投稿 + ダウンロードした際に劣化しない大きさを探したり、画像からバイナリへの変換の際にファイルが終了したことをどう検知するかを考えるところが苦労しました。

# 今後のこと
現在は、作ったページを経由していますが、拡張機能を使用することでTwitter.comのページで完結することができるようにしたいです。
また、拡張子の推定や拡張子を保存しておく場所を設ける必要があるかなと感じました。
また、800*800px以上のファイルでも劣化しなければ読み取れるためそれの出力をするなどして容量を増やしたいです。

# 最後に
ここまで読んでいただきありがとうございました。
Twitterでバイナリを共有したり、そんな長文を共有する必要があるかどうかは全くの未知数ですが、面白がっていただけたら幸いです。
2022/12/12主にITとかセキュリティの記事

脆弱性が修正される兆候がない3つのAndroidアプリに注意(12/10)
https://news.mynavi.jp/techplus/article/20221210-2533671/

ネットギア製ルータに重大な脆弱性、確認と更新を(12/10)
https://news.mynavi.jp/techplus/article/20221210-2534058/

イラン系サイバー攻撃グループ、イスラエルのダイヤモンド産業を攻撃(12/10)
https://news.mynavi.jp/techplus/article/20221210-2532724/

Apple、アプリがクラッシュする不具合や複数の脆弱性を修正したMac用X Window System「XQuartz v2.8.3」をリリース。
(12/10)
https://applech2.com/archives/20221210-20221210-xquartz-v2-8-3-update.html

オリコを偽るフィッシング確認、注意を(12/10)
https://news.mynavi.jp/techplus/article/20221210-2534465/

ラック社長 西本逸郎氏 ―― トップに聞く(12/10)
https://zuuonline.com/archives/243026

W杯のSNS投稿、不正アカウント15%　イスラエル社調べ(12/9)
https://www.nikkei.com/article/DGXZQOUC0786Z0X01C22A2000000/

中国の科学者、超伝導システムで量子敵対的機械学習を実現(12/10)
https://www.afpbb.com/articles/-/3441987?cx_part=top_category&cx_position=1

イーロン・マスクとティム・クックは何を話したのか？--Appleニュース一気読み(12/10)
https://japan.cnet.com/article/35197194/

G7広島サミットへ官民演習　サイバー攻撃に備え(12/9)
https://www.nikkei.com/article/DGXZQODE09BDZ0Z01C22A2000000/

米歌劇場ＭＥＴにサイバー攻撃　ロシア報復の見方も(12/10)
https://www.sanyonews.jp/article/1339952/
Goでハッカソン

# はじめに
僕が今日までにハッカソンに参加して、どういうことがあったのか書こうと思います。

# 自己紹介
* 生命医科学系の学部
* 高専卒
* Atcoder茶

# はじめてのハッカソン
元々僕は競プロをやっていて、毎週土日をatcoderに捧げる日々を過ごしていました。atcoderは茶色に行ってicpcも本選に出場することができましたが、サマーインターンでいくつかの企業に応募した時にほとんど書類選考が通らなくて、競プロはなんか違うんだろうなと思って、Goの勉強を始めました。Goの勉強は「Goプログラミング実践入門 標準ライブラリでゼロからWebアプリを作る」という本でやっていました。それで初めて技育展に出て、先輩に教えてもらいながら初めてバックエンドとしてプロダクトを作りました。
競プロとは違った面白さがあったし、色々と初めて触ったものが多かったのでとても面白かったです。賞は取れませんでしたが、チームメンバーと一つのプロダクトを作ったのはとても貴重な経験でした。
リファクタリングでテストも書けたし、全部標準ライブラリできました。標準ライブラリで作ったことは面接でいいねと言われることが多くてうれしいですね。技育展は来年もう一回チャレンジしたいですね。


# 他のハッカソン
技育展後も、東京web3ハッカソンや技育キャンプに出ました。この前の技育キャンプは努力賞をもらうことができてよかったです。それに、審査員の人にテスト書いてて偉い的なこと言われたのは結構嬉しかったです。(個人的にテストの書き方とかを勉強していたから)　どのハッカソンでも出るたびに自分が新しくしたい技術を試すことができて、そのたびにいろいろな学びや気づきがあります。Goのテストの書き方はまだ悩んでいるので、特にDB周りのテストの書き方はぜひ教えてほしいです。あと、ハッカソンに出るたびにgoでの技術的挑戦が無くなってくるのでなんかGoで面白いものも教えてください。


# その他
ハッカソンを通じてGoに興味を持ちましたし、そこからアーキテクチャやインフラなど多くの技術に興味を持てました。そっからGoを使って長期インターンしたり、個人的にGo書いたりGoが人生に組み込んできていて気持ちいいです。

# 最後に
時間が無くてあまり書けませんでしたが、ハッカソンに出て良かったし、Goに出会えてよかったです。Doerに皆さんに感謝です。
僕を採用してくれる"Goを使っている"企業さんぜひスカウトください。
vPro対応PCを検証用仮想プラットフォームにする話(4)〜MeshCommanderによるリモート制御編〜

# vPro対応PCを検証用仮想プラットフォームにする話(4)〜MeshCommanderによるリモート制御編〜
## [前回](https://qiita.com/JUNKER_TOMATO/items/d8aa7e1c7a688b3a949b)まで
AMT標準WebUIによる制御について書きました。

今回は AMT対応ソフトウェアである MeshCommanderについてご紹介します。

## MeshCommander について
AMTのコントロール用のソフトウェアとして、intel純正の[Intel Manageability Commander](https://www.intel.co.jp/content/www/jp/ja/download/18796/27807/intel-manageability-commander.html)がありますが、今回はフリーソフトウェアの[Meshcommander](https://www.meshcommander.com/meshcommander)による接続方法をご紹介します。

MeshCommanderは Ylian Saint-Hilaire 氏を中心として開発されている intel AMT対応ソフトウェアです。
Apache License 2.0のOSSとして[開発](https://github.com/Ylianst/MeshCommander)されています。<br>

Intel Manageability Commanderがどちらかというとリファレンス実装の側面があるのに対して、MeshCommanderは[Update History](https://www.meshcommander.com/meshcommander#h.p_ID_212)にあるように継続的にバージョンアップを重ねており、Win32バイナリ版以外にNodeJS版もリリースされるなどマルチプラットフォーム化も進んでいます。

現在、MeshCommanderは以下の４つの形式が提供されています。NodeJS版はmacOSやLinux等にも対応します。
* Windowsアプリ版(Win32,MSI)
* NodeJS版
* IISアプリ版
* MicroLMS版

## MeshCommander のインストール　（Windowsアプリ版)
まずは Windows版からご紹介します。

[公式サイト](https://www.meshcommander.com/meshcommander)から最新版の MeshCommander をダウンロードしてインストールを行ってください。MSIインストーラーなので、管理者権限で実行するだけでインストールできます。
![4-1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114505/77dfe071-5cdc-6839-d676-a5cf9af46d6c.jpeg)

インストールされたMeshCommanderを実行すると以下のような画面が表示されます。
![4-5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114505/40e56d32-d240-5e5c-cc57-812161ecee8b.jpeg)



## MeshCommander のインストール(NodeJS版)
macOSを前提にNodeJS版のインストール方法をご紹介します。

NodeJS版をインストールするためには まずNodeJSのパッケージ管理ソフトウェアである `npm` をインストールしてください。
macOSの場合は [NodeJS公式サイト](https://nodejs.org/ja/)から[ダウンロード](https://nodejs.org/ja/)できるインストーラを使うのが簡単だと思います。

MeshCommanderは npm公式リポジトリに登録されているため、`npm install`でインストールできます。
```bash
mkdir meshcommander
cd meshcommander
npm install meshcommander
```

インストールできたら、`node`コマンドで実行します。
```js
node node_modules\meshcommander
MeshCommander runing on http://127.0.0.1:3000.
``` 
表示されるように localhost の　3000/tcp でhttpで待ち受けて起動するので、ブラウザで接続します。
接続するとWebUIが日本語で表示されますが、翻訳が完全ではなく逆に意味が分かりづらいため、以下のURLで英語版UIに接続すると良いでしょう。
    `http://localhost:3000/default.htm`
以下のような画面が表示されます。
![4-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114505/b77967be-9f35-5631-b46e-4c113f8a754c.png)

## MeshCommanderの初期設定
MeshCommnder起動直後の状態は接続先の登録がないため、`Add Computer`ボタン押下でvPro対応PCを登録します。
![4-2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114505/bc39a6c8-fe5c-b274-1435-d61b3ee7331e.jpeg)

## MeshCommander によるvPro対応PCの管理
vPro対応PC登録後のMeshCommanderの画面です。

![4-3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114505/e74c1cba-2e73-3178-7499-c9f403074e1d.jpeg)

IPアドレス、ID、パスワードが正しく設定されている場合、登録してしばらくすると 登録アイコン側のLED様の部分が灰色から緑に変化します。ここで`CONNECT`ボタンを押下するとAMTに接続します。

次のような画面が表示されます。標準のAMT WebUIよりも内容が充実しているのがわかると思います。
![4-4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114505/dbec0948-5323-8931-69bf-88d8b7b6afe6.jpeg)

## まとめ
今回は AMT対応ソフトウェアである Meshcommander のインストール方法と初期設定方法についてご紹介しました。

## 次回予告
MeshCommander の `Remote Desktop` 機能と `IDE Redirect` 機能を使ってネットワーク経由でのOSインストール方法についてご紹介する予定です。
pxrUSD の Matrix は row-major であるので注意

pxrUSD ライブラリの Matrix は row-major + matrix 演算順は pre-multiply です!!!(あんまり主流ではない)

https://graphics.pixar.com/usd/release/api/usd_geom_page_front.html

メモリレイアウト上は変わらないのですが, OpenGL のように column-major, もしくは右が先に評価(?)されると想定して matrix mul を pxrUSD の GfMatrix4d とかで行うと転置(transpose)しますので注意です!

たとえば TRS(translate, rotate, scale)行列があるとして,
ベクトル p に適用,

```
p' = T * R * S * p
```

のように C++ コードで書くと, 通常は右から評価で p を Scale し, Rotate し, Translate になると思ってしまいますが, Translate し, Rotate し, Scale するとなってしまいます!

したがって row-major(or pxrUSD)で行列かけるばあいは,

```
p' = p * S * R * T
``` 

と書きます.

world matrix 求めるのも,

```
worldMat = localMat * parentWorldMat
```

とちょっとややこしい.

TinyUSDZ は column-major で実装していたのですが, やはり pxrUSD との整合性考えて row-major に変えました :cry:

https://github.com/syoyo/tinyusdz/wiki/Matrix-is-row-major

ちなみにさらに法線(cross-product)は right-handed(通常 counter-clock wise), Geom には handless 設定もあるので注意ネ

## 参考情報

https://qiita.com/takahito-tejima/items/4c30dd882ea3fdd737fb
アクセシビリティを考慮した CSS

## ウェブアクセシビリティ

### アクセシビリティとは

アクセシビリティとはできるだけ多くのユーザーにとって、提供されるコンテンツにアクセスできるようにすることです。

Web においては想定されるユーザーのウェブサイトの閲覧環境が非常に多様で、プラットフォームや OS やデバイス性能の優劣関係なく動作し、障碍などさまざまな特性を持ったユーザーであってもできるだけウェブコンテンツを解釈できるように考慮したりします。

### アクセシブルな Web を実現するために

ブラウザは HTML や CSS や JavaScript などを解釈してウェブコンテンツを構築しますが、それぞれのリソースに記述されるコードによってブラウザのユーザー操作の補助機能が動作します。

つまり、HTML や CSS や JavaScript でアクセシブルな実装ができていないとブラウザの支援技術が正しく動作しないことがあります。アクセシブルな実装を行うためには、HTML Standard や WCAG の記載に則った実装をするとよさそうです。

しかし、あくまで実装の解釈を行うのはブラウザであり稀にブラウザごとで挙動が異なることがあるのでそれぞれのブラウザで意図する動作をしているかを確認することも大切です。

## アクセシビリティツリー

ブラウザではウェブコンテンツの要素ごとのアクセシビリティ情報について、アクセシビリティツリーというツリー構造のデータを生成して解釈しています。

また、アクセシビリティツリーは DOM と CSSOM（CSS から生成されるスタイルのツリー構造データ）を元に生成されます。なので、場合によっては CSS をウェブサイトに使う前と使う後でアクセシビリティ情報が変わっていることがあるので注意をする必要があります。

## CSS に影響を受けるアクセシビリティツリーの例

### display: none;

要素を非表示にする `display:none` を適用するとアクセシビリティツリー上でもその要素のコンテンツがされます。なのでスクリーンリーダーなどでも display:none が適用された要素は認識されません。

また、Webkit で動作しているブラウザ（Safari など）のみで、特定の CSS を適用するとアクセシビリティツリーが変更される場合があります。

### table 要素

table 要素に対して display スタイル属性の table 以外の block や inline などの値を適用したときに、 table 要素は table role を失います。なのでやむを得なく display: table 以外の値を適用したいときには table 要素に対して明示的に table role を付与する必要があります。

### list-style

よく使われる HTML 要素としてリストがありますが、 list 要素の左側に表示される装飾を消すために list-style: none を適用すると list 要素の list role を失います。リストとして扱いたい場合にはこれについても明示的に list role を付与する必要があります。

### おまけ

#### display: contents;

仕様では display: contents はセマンティクス的に影響を及ぼすものではありませんが、2022年12月現在のブラウザでは、バグで影響を及ぼしてしまう挙動をしています。

display: contents を適用した要素の role が消える事象が起きるので、明示的に意図している role を付与しておく必要があります。

このように、HTML などで DOM を構築しても CSS によってアクセシビリティが変化することがあり得るのでスタイルを適用する際にも注意をする必要があります。
noImplicitAnyはstrictNullChecksを無効化してしまう

正確に言えば無効化ではなく、挙動の変化というか弱体化というか…どちらにしろ直感的な挙動では無かったのでメモ。

# 動機

以下の記事を読んで、とてもモヤモヤしたので調べてみました。

TypeScriptのnever型について - Qiita https://qiita.com/clown6613/items/042082f50534bafdc0a2

元々コメントで返すつもりだったのでそういう文体ですが、長くなりそうなので別記事にします。途中から一人語りのような書き方に変わっているような気がする…。

# 回答

極めて直感的ではないですが、`tsconfig.json`に`"strict": true`を入れることでエラーを出ないようにできます。VSCode標準のjsconfigでは`strictNullChecks`と`strictFunctionTypes`のみがtrueとなっていますが、`strict`をtrueにすることで多くのstrict系のオプションをまとめてtrueにすることができます。 https://www.typescriptlang.org/tsconfig#strict

`strict`をtrueにしてトランスコンパイルすることが「最もTypeScriptらしいコード」を書く条件であるとされているため、おそらく参照された本でも`strict`をtrueにしているのでしょう。VSCodeでは、 以下のコミットでようやくstrictのうちの2オプションが追加されているので、おそらくstrictオプションは最低限としたいのでしょう。

Add setting to enable strict null checks in implicit JS files · Issue #109988 · microsoft/vscode https://github.com/microsoft/vscode/issues/109988 

というか、VSCodeデフォルトのconfigだと、関数の引数に型書かなくても(`noImplicitAny`が無いので)エラーにならないんですね。初めて知りました。

さて、`strict`をtrueにすると、当然`strictNullChecks`はtrueになりますが、他にも`noImplicitAny`もtrueになります。`noImplicitAny`は「暗黙的なanyを排除する」オプションです。しかし、後方互換性の問題から`noImplicitAny`をtrueにした場合は、空の配列をany[]型として扱って、この配列に変更が加えられた場合に型推論を行うようです。以下がそのIssueのリンクです。

Empty array's type changes from never to any when turning on noImplicitAny · Issue #36987 · microsoft/TypeScript https://github.com/microsoft/TypeScript/issues/36987 

## 後方互換性？

この後方互換性というのが実際に何かというのも調べたのですが、最低でも以下の現時点で8年前のIssueまでは遡ることが可能でした。`noImplicitAny`は`strictNullChecks`を上書きしてしまうという認識で良いのかは分かりませんが、挙動上そんな感じです。

No widening in strict null checking mode by ahejlsberg · Pull Request #8944 · microsoft/TypeScript https://github.com/microsoft/TypeScript/pull/8944 
Infer bottom type for type argument when passing empty array · Issue #8878 · microsoft/TypeScript https://github.com/microsoft/TypeScript/issues/8878 

最後に挙動を再確認してみましょう。空の配列ではなく、再代入可能な変数で見ると分かりやすいです。これを空の配列にしてpushなどで変更しても、同じことが起きます。

### `strictNullChecks`がtrueの場合

#### `noImplicitAny`をfalseにした場合

```ts
let a = null // aの型はnullになる
a = 'aaa' // エラー
```

#### `noImplicitAny`をtrueにした場合

```ts
let a = null // aの型はanyになる
a = 'aaa' // string型になる
```

### `strictNullChecks`がfalseの場合

#### `noImplicitAny`をfalseにした場合

```ts
let a = null // aの型はanyになる
a = 'aaa' // any型のまま
```

#### `noImplicitAny`をtrueにした場合

```ts
let a = null // aの型はanyになる
a = 'aaa' // any型になる
```

これがモヤモヤの原因です。

しかし、どう考えても`strictNullChecks`はtrueの方が良いのは明らかですよね。これが無いとこの書き方がanyまみれになってしまう。VSCodeのPRでもIntelliSenseのためと書かれています。

だからと言って、`strictNullChecks`を今更優先させてしまうと多分阿鼻叫喚になるのは明らかで、`strict`というおまとめオプションで縛られている以上breakingな変更もできないしと言うことで、残されているのでしょうか。

浅い理解&憶測が多いので、マサカリが飛んでくる可能性がありますが、解決方法は分かったのでとりあえずヨシとします。

書いてから気づきましたが、もっと細かいことが書かれている記事がありました。コメント返すだけならこのURLを書けばそれで良かったのでしょう。
`let h = null`について、TypeScript はどのような型を推論するか - Qiita https://qiita.com/eyuta/items/31abebb2395c136e0591
AWS EC2でログをcloudwatchに送るベストプラクティス

# AWS EC2でログをcloudwatchに送るベストプラクティス

オートスケールで自動でスケールアウトしてスケールインする場合、問題になるのはログになります。
自動でスケールインされた場合、ログがそのまま消えてしまい、そのサーバでエラーが発生した場合、追えなくなります。

よって、ログについては、ストリームで送るの必要があり、何年か前までは、fluentdで送るのが主流でしたが、
awsからawslogsができて、簡単にcloudwatchに送れるようになりました。

### 前提条件
OS:AmazonLinux2
対象ログ：nginx


### awslogsのインストール
```
sudo yum install awslogs
```

### リージョンの設定 /etc/awslogs/awscli.conf
```
[plugins]
cwlogs = cwlogs
[default]
region = ap-northeast-1
```

### 出力ログの設定
```
[/var/log/nginx/access.log]
file = /var/log/nginx/access.log
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = {任意のロググループ名}
```

### サービスの有効化
```
systemctl enable awslogsd
```

### サービスの開始
```
systemctl start awslogsd
```

しばらくするとcloudwatchのロググループにログが出力されます。


以上になります。
Google Colaboratoryを使ってFastAPIでLINE Botを動作させる

# はじめに

学生向けハッカソン/ワークショップの題材にLINEBotをつかってましたが、Heroku無料枠廃止をうけて環境見直す機会に、サンプルをリライトしようということでFastAPI＋GoogleColaboratory版を作成します。

* ハッカソンやちょっとしたプロトタイプ作成向けにクレジットカード登録不要で無料で使える環境を
* いままであまり触ってないけど今後伸びそうなFastAPIを使う
* LINEDevelopersの登録方法や使い方、ngrokの使い方については割愛

# できあがり

https://colab.research.google.com/drive/10lj4fltJkosfoXBSK93wbG54QtV66GDV?usp=sharing

送られたメッセージをそのまま返すエコーbotです。自分のドライブにコピーして、トークンとシークレットを設定して使ってください。

```
# ngrokのauthtoken
NGROK_AUTHTOKEN = '入力して下さい'

# LINE Bot のチャンネルアクセストークン
LINEBOT_ACCESS_TOKEN = '入力して下さい'

# LINE Bot のチャンネルシークレット
LINEBOT_SECRET = '入力して下さい'
```

# いくつか説明

## ngrok

最初に起動したらあとはそのままでOK。
無料の場合は張れるトンネルがひとつだけなので、トンネルを切断したりurlを変更したくなったら、ランタイムをいったん終了してください。
またブラウザから閲覧するとき、初回は確認画面が挟まれるのでVisitSiteで画面へ移動してください。

```
!pip install pyngrok
!ngrok authtoken $NGROK_AUTHTOKEN

from pyngrok import ngrok
from pyngrok.conf import PyngrokConfig
import os

os.system('kill -9 $(pgrep ngrok)')
ngrok_tunnel = ngrok.connect(addr='127.0.0.1:8000', pyngrok_config=PyngrokConfig(start_new_session=True))
print (ngrok_tunnel)
```
## uvicorn

先にngrokを起動して、後からuvicornの起動でOK。ngrokのトンネルの設定とポート番号をあわせてください（今回の例では8000）。
セルがずっと実行中になるので、終了する場合は選択して実行を停止してください。

```
!pip install uvicorn nest_asyncio

import uvicorn
import nest_asyncio

# 設定や動作確認で使用するURLをここで表示しておく
print('public_url : ' + ngrok_tunnel.public_url + '/')
print('health_check_url : ' + ngrok_tunnel.public_url + '/health')
print('doc_url : ' + ngrok_tunnel.public_url + '/docs')

# サーバ起動
nest_asyncio.apply()
uvicorn.run(app, port=8000)
```

# ここまでの感想

* コード量が少ないのはたいへん便利
* FastAPIのドキュメント自動生成も便利

# 今後の予定
* uvicornからgunicornへ変更
* databaseがわりのgooglespreadsheet連携サンプル
* 適当な外部apiの利用サンプル

# 参考記事

https://qiita.com/uezo/items/7fa15f3d77b140190981

https://medium.datadriveninvestor.com/flask-on-colab-825d2099d9d8
Python開発環境2022年度末版

[MIXIアドベントカレンダー2022](https://qiita.com/advent-calendar/2022/mixi) の12日目の記事です。

~~タイトルは、「ぼくの考えた最強の Python 環境」 にしようかと思いましたが、そんなに尖っていないので、やめました。~~

長期運用を見据えた場合を想定して、それなりにいろいろはいっているリポジトリです。 個別の記事はたくさんありますが、全部のせリポジトリはあまり見ないので、 `git clone` すればいいリポジトリを作ってみました。

```bash
git clone https://github.com/arrowkato/my_favorite_python_env.git
```

各種説明は、 [README.md](https://github.com/arrowkato/my_favorite_python_env/blob/main/README.md) とそのリンク先参照です。


対象読者

- 他のサーバーサイド言語での実装経験はあるものの、Python では、初めて開発環境を作るエンジニア
- 人が作った開発環境上で、Python のコード自体はかけるものの、DevOps 周りに領域を広げたいエンジニア

全体的に奇をてらわず、類似のサービス、ライブラリの中では、シェアのなるべく多いものを選んでいます。 結果的に、経験のあるエンジニアからすれば、どこかで見た構成になっていると思います。
shopifyでブログ記事一覧の絞り込み機能を作成する

# 概要
shopify案件を対応していると、よく、ブログ記事一覧に絞り込み機能を作成出来ないか？という要件が発生するため、個人的な備忘録も含めて、作成方法を書いていこうと思います。

# この記事で伝えたいこと
shopifyにある既存機能を使って、最も簡単な絞り込み機能の作成方法をお伝えできればと思います。
ブログ記事の作成方法や、liquidの基本説明など、基礎的な部分に関しては、今回の趣旨とは異なるため、割愛します。

# 実装方法
## 記事にタグを設定
shopifyの管理画面より、ブログ記事の編集画面を開きます。
編集画面右のサイドバーにタグと書かれた欄があります。
![スクリーンショット 2022-12-12 0.09.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905389/7588a3fc-99a8-149c-1e8f-821f254ecb51.png)
ここに、絞り込みをしたいカテゴリーを追加していきます。
このタグを利用して、絞り込み機能を実装していきます。

### タグの仕様
blog用のテンプレートを使用している場合、追加したタグ毎に以下のようなURLを持つようになります。（newsというブログを作成した場合）
``` url
/blogs/news/tagged/タグ
```
このタグ毎のURLに遷移すると、「タグ」が付与された記事のみが一覧に表示される仕様になっています。
これを利用していきます。

## 追加したタグ一覧をセレクトボックスに出力する
liquidの記法を使い、以下のように実装します。
``` liquid:記事一覧のliquidファイル
<select id="filter-tag" class="js-filterBtn">
 <option value="{{ blog.url }}">すべて</option>
 {%- for tag in blog.all_tags -%}
 <option value="{{ blog.url }}/tagged/{{ tag | handle }}" {% if current_tags contains tag %}selected{% endif %}>{{ tag }}</option>
 {%- endfor -%}
</select>
```
### {%- for tag in blog.all_tags -%}・・・{%- endfor -%}
`{{ blog.all_tags }}`で、該当のブログカテゴリー内で追加されたタグ一覧を取得できます。
for文で回して、セレクトボックスのそれぞれの`optionのvalue属性`に、タグ毎のURLを設置していきます。

### {% if current_tags contains tag %}・・・{% endif %}
`{{ current_tags }}`でタグ毎のURLに遷移した際に、現在選択されているタグの値を取得できるため、セレクトボックスに`selected`を付与し、選択中のoptionを表示させたり、選択中のタグをテキストとして表示したりすることも可能です。

## JavaScriptの実装
セレクトボックスにおいて、選択されたタグのURLに遷移するように、JavaScriptに記述していきます。

``` JavaScript:jQuery
$('.js-filterBtn').on('change', function () {
  window.location = $(this).val();
});
```
セレクトボックスの値が変わった時に、value値に設定されたURLに遷移するように記述しました。
これで絞り込み機能の完成です。

# 最後に
いかがでしたでしょうか？
shopifyの既存機能を使えば、すごく簡単に絞り込み機能を作成できてしまいます。
liquidの知識は必須のため、最初は難しく苦戦しますが、理解すれば、さらに複雑な実装もできそうな気がしています。
引き続き、shopifyと、liquidの知識を深めて、備忘録を残していこうと思います。

# 参考文献

https://www.metaphase.co.jp/blog/shopify%E3%83%96%E3%83%AD%E3%82%B0%E8%A8%98%E4%BA%8B%E3%82%92%E3%82%BF%E3%82%B0%E3%81%A7%E3%83%95%E3%82%A3%E3%83%AB%E3%82%BF/

https://help.shopify.com/ja/manual/shopify-admin/productivity-tools/using-tags

https://ec-penguin.com/blogs/shopify/sidebar-categories-archives
Babylon.jsでマウスカーソルをあてたオブジェクトを調べてみる

この記事は [Babylon.js アドベントカレンダー 2022](https://qiita.com/advent-calendar/2022/babylonjs) の 23日目の記事です。


#### はじめに
Babylon.jsで、マウスカーソルを当てたオブジェクトの判定をする処理の書き方について記載しました。
サンプル：マウスカーソルを当てると、グラフの情報が画面左上に表示されています。
![babylon2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594551/31e4e680-d8b5-5ca2-c40a-31217a69a1b6.gif)

## 処理の概略
以下の３つの処理で実装します。

１．判定するオブジェクトを作成する。
２．マウスの割り込み（MoveとかClick）が発生したら、レイキャストでオブジェクトがあるか判定をする。
３．２で交差するオブジェクトがあれば、そのオブジェクトを対象にする。


## 処理の内容

### １．オブジェクトを作成
今回はCreateBoxで立方体を作成しますが、メッシュならなんでもよさそうです。作成するコードは下記。
普通にCreateBoxをするだけですが、引数に名前を定義しておきます。
他に必要な情報があれば、作成したオブジェクトへ追加しちゃいましょう。

```
        //オブジェクトを作成する
        const box = BABYLON.MeshBuilder.CreateBox(【名前】, {width: 【幅】, height: 【高さ】, depth: 【奥行】})   
        box.position.x = 【X座標】;
        box.position.y = 【y座標】;
        box.position.z = 【z座標】;
        box.追加情報 = 【使用したい任意の情報】;
```

### ２．マウスの移動時に判定を行う
マウスが移動した際に割り込ませたいので、onPointerMoveに下記の処理を行いします。
・レイキャストを作成
　レイキャストは、光線（ray）を投射（Cast）するという意味で、直線上に存在するオブジェクトを取得します。
・createPickingRayで、マウスのポインター座標と視点（camera）を結んだ直線を 変数 に格納。
・pickWithRayで、上記の直線で最初に衝突したメッシュを格納します。
　該当するオブジェクトがあれば（nullでなければ） 情報を画面に表示する処理を実行します。

```
        //マウスの移動時にマウスカーソルの場所にオブジェクトがあるか判定する
        scene.onPointerMove = function castRay(){
            var ray = scene.createPickingRay(scene.pointerX, scene.pointerY, BABYLON.Matrix.Identity(), camera);	
            var hit = scene.pickWithRay(ray);
    
            if (hit.pickedMesh){
                //対象のオブジェクトがあれば処理をする
                createGUIButton(hit.pickedMesh);
            }
        }
```

### ３．対象オブジェクトの処理を行う
オブジェクトの情報を画面に表示する処理です。
    （Playgroundにテキストを切り替えながら表示するのに簡単だったのでボタンを使いました。本来の用途と違いますが）
    ボタンを作成する際に、引数にボタンに埋め込む文字列（今回は名前と追加情報）を指定して、表示したい文字を含むボタンを作成して、
    画面にボタンを追加しています。

```
        function createGUIButton(pickedMesh){
            //指定されたMeshオブジェクトの情報を表示する
            let guiCanvas = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
            //ボタン生成時に表示するテキストを指定する
            let guiButton = BABYLON.GUI.Button.CreateSimpleButton("guiButton", 
                            "オブジェクト名：" + pickedMesh.name + pickedMesh.追加情報 ); 
            guiButton.width = 【ボタンのサイズ】;
            guiButton.height = 【ボタンの幅】;
            guiButton.color = 【文字色】;
            guiButton.background = 背景色;
            //ボタンを画面の左上に表示
            guiButton.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
            guiButton.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
            guiCanvas.addControl(guiButton);
        }
```

上記の処理で、マウスカーソルを重ねた場所にあるオブジェクトを指定して処理を行うことができます。

サンプルのURLは下記になります。
https://playground.babylonjs.com/#1JQRXD#24


## 終わりに
サンプルのようにマウスでオブジェクトを操作する時や、FPSで発射した弾が当たるかの判定なんかに使用できるかと思います。
日本語のサンプルが少なかったので、このメモが参考になれば幸いです。

## 参考文献

上記のレイキャストについてのドキュメントは下記のページを参考にさせていただきました。
https://doc.babylonjs.com/features/featuresDeepDive/mesh/interactions/picking_collisions
LovyanGFX で画面描画(2):基本描画

コマンドで基本図形を組み合わせて描画する際に利用する命令です

# カラーモード

デバイスに接続したLCDモジュールなどによって、何色表示できるかの性能は異なります。LovyanGFX では RGB888 / RGB565 / RGB332 などがあります。
それに合わせてカラーモードを設定します。

```
lcd.setColorDepth(16);
```

16だとRGB565、24だとRGB888 となります。

# 色値

描画コマンドに指定する色はデバイス色モードにかかわらず、RGB888形式です。
RGB888形式ですが、RGB565 や RGB332 で動作しているものでも RGB888形式で渡せます。
色の値は
```
lcd.color888(R,G,B);
```
で示すことができ、RGBはそれぞれ0〜255までです。

また、直接 0xFF0088 のように指定することもできます。

# 色名

色名はTFT_ではじまる名前が定義されています。
TFT_BLACK、TFT_BLUE、TFT_BROWN などです。

# 描画コマンド

- クリア
- 線分
- 色変化する線分
- 矩形
- 円
- 角丸


# クリア
```
lcd.fillScreen(color);
```
または
```
lcd.clear(color);
```

`clear();` とすると、`setBaseColor(color);` で指定した色でのクリアとなります。

# 線分

```
lcd.drawLine(x0,y0,x1,y1,color);
```

# 色変化する線分


```
lcd.drawGradientLine(x0,y0,x1,y1,startcolor,endcolor);
```

# 矩形


矩形枠
```
lcd.drawRect(x0,y0,x1,y1,color);
```

塗りつぶした矩形

```
lcd.fillRect(x0,y0,x1,y1,color);
```


# 円

半径を指定して描画。」
円周
```
drawCircle(x,y,r,color);
```
塗りつぶした円
```
fillCircle(x,y,r,color);
```

# 角丸

```
drawRoundRect(x, y, w, h, r, color);
```
wとhは角が丸い部分以外の直線部分のサイズ、r は半径。

# 詳細

https://github.com/lovyan03/LovyanGFX/blob/master/examples/HowToUse/1_simple_use/1_simple_use.ino