OmniAICreator/Qiita-1.07M huggingface dataset:
HTML & CSS学習の記録2

# はじめに
HTML, CSSの学習を進めていく中で，新たに学んだことをアウトプットしていきます．

# CSSで１番目，２番目の要素を指定する
- １番目の要素を指定するときは，要素の後ろに`:first-child`をつける
- N番目の要素を指定するときは，要素の後ろに`:nth-child(N)`をつける
- 最後の要素を指定するときは，要素の後ろに`:last-child`をつける

参考サイト

https://web-camp.io/magazine/archives/97620


# 画面幅によって表示する画像を変える方法
画面幅によって表示する画像を変えるには，HTMLの`<picture>`タグを使用し，以下のように記述する．
```html
<picture>
    <source srcset="画面幅600px以下のときに表示する画像のURL" media="(max-width:600px)">
    <img src="画像のURL">
</picture>
```

参考サイト

https://webcreatetips.com/coding/70/

# セレクタの詳細度
セレクタの書き方によって，詳細度が変わる．詳細度が高いセレクタのCSSが優先して適用される．
例えば，同じ要素でも，`main ul li{}`という書き方の方が，`main li{}`よりも詳細度が高い．

ある要素に対して，responsive.css内でのセレクタ詳細度が，stylesheet.css内でのセレクタ詳細度よりも低いと，レスポンシブデザインが適用されないので注意が必要．
stylesheet.cssと同じセレクタの書き方をすれば問題はない．

参考サイト

https://zero-plus.io/media/degree-of-detail-of-css/
WEBスクレイピングで使うブラウザは？

# 記事概要
Webスクレイピングで利用すべきブラウザを経験則から語る。

# 経験
（少し前まで）Webスクレイピングを業務で利用していた時、何も考えずにPCにインストールされているChromeを利用していた。正直これはナンセンスだった。勝手にChromeのアップデートが走ってしまいChromeDriverのバージョンとChromeのバージョンが合わなくなって幾度となく対応に追われた。

# なにを使う？
**Chrome for Testing**という勝手にアップデートされない専用のChromeがあるので、それを使おう！  
<a href="https://googlechromelabs.github.io/chrome-for-testing/" target="_blank">https://googlechromelabs.github.io/chrome-for-testing/</a>  
⇑ここからChromeとChromeDriverがDLできる。  

Pythonで使う場合は
```python
options = Options()
options.binary_location = 'ChromeforTesting.exe'
driver = webdriver.Chrome(executable_path='chromedriver.exe'), options=options)
```

```chrome.exe```を```ChromeforTesting.exe```にリネームして、タスクスケジューラ等で定期実行する場合は、```ChromeforTesting.exe```というプロセスをkillする処理を入れている。WEBスクレイピング途中でブラウザがクラッシュした場合に、```driver.quit()```しても、ブラウザが閉じなかったことが何度かあったため。

<br><br><br><br>
XCUITest でボタンの名前が分からない時の解決策

# この記事の目的
XCUITestを作成する際、自分で書いたコードであれば自分で設定したaccessibilityIdentifierを用いてボタンを指定し、タップすることができます。
しかし、ライブラリ内のボタンの場合、ボタンのidentifierが分からないことがあります。その際の解決策の一つをまとめておきます。

# 解決策
XCodeのDebugViewHierarchyを使用します。手順は以下の通りです。
1. アプリをビルドする。
1. ビルドしたアプリを操作して、identifierを知りたいボタンが表示されている画面に移動する。
1. Xcode下部のデバッグエリアのバーに表示されている、DebugViewHierarchyボタンを押す。（以下の画像の赤丸箇所）
![DebugViewHierarchy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631508/b5773236-923e-8574-3959-9c44ed90187c.png)

1. identifierを知りたいボタンを選択することで、identifierが確認できます。（以下の画像の赤丸箇所）
![identifier名.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631508/01fc5e27-1c58-1a2a-590a-5c2f50d2621d.png)

# 終わりに
XCUITestの作成でもDebugViewHierarchyが役立つことがわかりました。ボタン以外でも同じ方法でidentifierが分かるかもしれません。
【C言語】ペンデュラムウェーブの糸の長さを数値計算で求めてみた

# 概要
　ペンデュラムウェーブの糸の長さを求めた。そのために楕円方程式を数値計算(シンプソン法)で解いた。

# 動作環境
- Windows10(64bit)

# やりたいこと
　ペンデュラムウェーブの糸の長さを計算したい。ペンデュラムウェーブの周期の表式には楕円方程式が含まれる。そこで数値計算で楕円方程式を解いてペンデュラムウェーブの糸の長さを求める。
 
# ペンデュラムウェーブとは
　ペンデュラムウェーブとは周期を規則的にそろえた振り子を複数並べたもののことである。具体的には振り子を時刻0秒に一斉に話した後、振り子たちはバラバラに運動したり、規則的なタイミングで振れ方が揃ったりを繰り返す。

# プログラム
数値計算ではシンプソン法を用いた。
theta_0で振り出しの角度を指定している。
空気抵抗は無視した。
```c
#include <stdio.h>
#include <math.h>

#被積分関数を定義する
double f(double phi,double theta_0){
return 1.0/(sqrt(1.0-pow(sin(theta_0/2.0),2.0)*pow(sin(phi),2.0)));
}

#シンプソン法で振り子の糸の長さを計算する関数を定義する
double calc_l(double i)
{
const double g = 9.8;　#重力加速度
const double T_c = 60.0; #振り子を振れさせる時間(s)
const double theta_0 = (M_PI/180.0)*50.0; #振り子の振出しの角度
const double phi_start = 0.0;
const double phi_finish = M_PI/2.0;
const double m = 10000.0;　
const double h = (phi_finish - phi_start) / m;　#刻み幅
int j = 0;
double sum = 0.0;

for (j = 0; j < m; j++) {
	double phi = phi_start + j * h;
	sum += (h / 6.0) * (f(phi,theta_0) + 4.0 * f(phi+h/2.0,theta_0) + f(phi + h,theta_0));
}
return (g*pow(T_c,2.0))/(16.0*pow(sum,2.0)*pow(i,2.0));
}

int main(){
int i,l;　#i:60sの間に振り子が往復する回数　l:iに対応した糸の長さ
int i_max = 100;
double array_i[i_max];
double array_l[i_max];
for (i=1;i<=i_max;i++){
    array_i[i-1]=(double)i;
    array_l[i-1]=calc_l((double)i);
}
FILE *fp;　#計算結果をtxtファイルに書き出す
fp = fopen("data_c25_50.txt","w");
for (int l = 0; l <= i_max-1; l++)
{
fprintf(fp,"%f %f\n",array_i[l],array_l[l]);
}
fclose(fp);
return 0;
}

```
Provisional headers are shown

## 事象　Provisional headers are shown
HTMLで作成したUIからtypescriptを利用して`localhost:8080`を呼び出したとき、ローカルサーバーに接続できない。
Chromeの「検証」から「Network」を確認すると**CORS error**と表示されています。
![CorsError.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634828/93b4afc9-38f4-dae4-4ea5-3b1feeb1fe06.png)

[Headers]にある[Request Headers]を確認すると**Provisional headers are shown**と表示されています。
日本語では「暫定ヘッダーが表示されます」となります。
![Provisional.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634828/40f16331-6577-a00b-6dca-564e32caedd9.png)

## 環境
python: 3.10.11
Node: 16.14.2
Framework: Flask

## 原因　ブラウザのセキュリティ上の理由
このエラーメッセージは、ブラウザが同一オリジンポリシー（Same Origin Policy）に従っているため、異なるオリジン（origin）からのリクエストをブロックしていることを示しています。ブラウザのセキュリティ上の理由から、デフォルトでは異なるオリジンからのリクエストは許可されません。

## 解決策 Flask-CORSをインストール
これを解決するためには、PythonのFlaskサーバーでCORS（Cross-Origin Resource Sharing）を設定する必要があります。Flask-CORSという拡張機能を使用すると、簡単にCORSを設定できます。

まず、Flask-CORSをインストールします。
```:bush
pip install flask-cors
```

次に、FlaskアプリケーションでCORSを有効にします。

```python:app.py
from flask import Flask, request, jsonify

# Flask-CORSをインポート
from flask_cors import CORS 

app = Flask(__name__)

# CORSを有効にする
CORS(app)  

# ... 以降のコードはそのまま ...

if __name__ == '__main__':
    app.run(host='localhost', port=8080)
```

これにより、FlaskアプリケーションにCORSが有効になり、異なるオリジンからのリクエストを許可するようになります。ただし、セキュリティ上の理由から、本番環境ではオープンなCORS設定を行うことには注意が必要です。必要なエンドポイントに対してのみ適用し、信頼できるオリジンからのアクセスのみを許可するように設定することが推奨されます。

## 他にも　
### Request URLを誤っている
Requset URLが間違っている場合も同じエラーが表示されるようです。
#### 解決策　正しいURLを入力
これは正しURLを入力することで解決します。
【小ネタ】 Werner 先生「メモリは11まで」の元ネタ紹介

# The knobs always go to 11.

1人で「ふふふ」ってなったのだけども、会場内はほぼスルーされてしまったシーンがある

FRUGAL アーキテクチャの法則5番目が紹介され、「Tunable Architecture」というスライドが出たときだ

https://youtu.be/UTRBVPvzt9w?si=HPZ8fGhRg0hARnQ9&t=3046


さすがに Werner 先生も「ジョークを言った時くらいは、笑ってくれよ」って言ってましたが、
ジョークが高騰すぎて伝わっていなかったようなので、ちょっとご紹介

# アンプのメモリは普通は10まで

元ネタとなっているのは、映画「This is Spinal Tap」
以下にその予告編を

https://youtu.be/A-FducsaVww?si=f-c_w0Remrf53BK2

Spinal Tap は1984年公開の映画で
架空のバンド「Spinal Tap」を追いかけたフェイクドキュメンタリー映画で
監督は「スタンド・バイ・ミー」のロブ・ライナー。彼のデビュー作品でもある

この予告編の一番最後のシーンが、この Keynote の元ネタ
マーシャルのアンプのメモリをみて「メモリが11まである。10よりでかい。爆音だ」ってところですね

”up to eleven”とかでググると色々出てくるのでぜひ

Werner 先生も「You Must have watched "Spinal Tap"」と言っているので、
来年またこのネタが擦られた時に大きな声で笑えるよう、エンジニアの皆さんはチェックしておきましょう。
【React】JSXって何ですか？

# はじめに
`React`を学習している中で、改めて`JSX`の仕組みについて少しまとめてみました。

https://react.dev/reference/react


# JSXとは?
`JSX`は`React`で使われる記法です。下記のコードを参照すると、`<h1>Hello World!</h1>`が`Greet`関数の中に指定されています。
このように`Javascript`の中に`HTML`が書かれている記法です。
また、この書き方はあくまで**書き方の一つ**の為、今今回は裏側の仕組みを簡単にみていきます。

```jsx:sample.jsx
import React from 'react';

export default function Greet() {
  return <h1>Hello World!</h1>;
}
```

# Reactの仕組み

`React.createElement`は、`React`要素を作成するための関数です。**これは、`JSX`がコンパイルされるときに、`JSX`要素が変換される関数でもあります。**

例えば、上記のGreet関数は、JSXがコンパイルされると以下のようになります。

```jsx:sample.jsx
import React from 'react';

export default function Greet() {
  return React.createElement('h1', null, 'Hello World!');
}
```

`React.createElement`関数は3つの引数を取ります。

`type`: これは文字列（組み込みコンポーネントの場合）または関数（ユーザー定義コンポーネントの場合）です。上記の例では、'h1'がタイプです。
`props`: これはコンポーネントに渡すプロパティのオブジェクトです。上記の例では、nullがプロパティです。
`children`: これはコンポーネントの子要素です。上記の例では、'Hello World!'が子要素です。

したがって、`JSX`は実際には`React.createElement`呼び出しに`シンタックスシュガー（糖衣構文）`を提供しています。これにより、コードは読みやすく、理解しやすくなります。


# レンダリングの仕組み
先ほど書いたコードでは、`React`要素は作成されますが、**画面に描画されることまではされません。**
```jsx:sample.jsx
import React from 'react';

export default function Greet() {
  return React.createElement('h1', null, 'Hello World!');
}
```

描画されるには、`React18`以降では、`ReactDOM.createRoot`を使って表示させることができます。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>React App</title>
</head>
<body>
  <div id="root"></div>
  <script src="index.js"></script>
</body>
</html>
```

```jsx:index.js
import React from 'react';
import ReactDOM from 'react-dom';

export default function Greet() {
  return React.createElement('h1', null, 'Hello World!');
}

const container = document.getElementById('root');
ReactDOM.createRoot(container).render(<Greet />);
```

`Next.js`では、`ReactDOM.render`という書き方は見られません。これはNext.jsは自動的にページをレンダリングできるような**ファイルシステムベースのルーティング**を提供しているためです。

したがって、`Next.js`アプリケーションでは、`ReactDOM.render`を直接呼び出す必要はありません。代わりに、各ページコンポーネントを`export default`するだけで、`Next.js`が適切にレンダリングを行います。

# まとめ
1. `JSX`とは'React要素'を作成する記法(シンタックスシュガー)の一つである
2. `JSX`はあくまで**React要素を作成する**為のものであり、画面に描画はされない
3. 描画する為には、`ReactDOM.createRoot`を用いる必要がある
4. `Next.js`はその辺りをよしなにやってくれる
私的Linuxで覚えておくべきなコマンド

本記事は、[めんどい太郎の Advent Calendar 2023](https://qiita.com/advent-calendar/2023/mendoitarou_first_calendar) 6日目の記事です。

# はじめに

この記事は初心者が書いています。

今回は私がLinuxでこれは覚えておくべきだと思っているコマンドを紹介します。

といっても、Linux初心者なのでよく見るコマンドばかりかもしれません。

# 検索

``ls``などで絞り込んで表示させたいときは``grep``を使います。

以下が例です。

```Shell
$ ls
0.txt  10.txt  1.txt  2.txt  3.txt  4.txt  5.txt  6.txt  7.txt  8.txt  9.txt
$ ls | grep 2
2.txt
```

こんな感じで使えます。

普通にテキストファイルの中身を検索したいときは

``grep {検索したいもの} {対象ファイル}``とすればOKです。

正規表現も使えます。

下の記事に詳しく書かれてあります。

https://tech-blog.rakus.co.jp/entry/20220912/grep

# 複数動作

``screen``を使うことで、シェルを複数扱えます。

マイクラなどのサーバーをSSHで動かすときに便利です。

``screen``と打つと、別のシェルが立ち上がります。

ここで、サーバーなどを起動し``Ctrl+a``を押して``d``を押すと元のシェルに帰ってきます。

戻るときには``screen -ls``で起動してるシェルの一覧を確認し、``screen -r {id}``でシェルを開きます。

詳しくはこの記事を見ると良いです。

https://qiita.com/hnishi/items/3190f2901f88e2594a5f

# 監視

``top``で現在動いているコマンドとかが見れます。

便利。

そして、``top``コマンドを実行中に``1``を押すとCPUの情報がコア別で表示されます。

CPUの各コアがどのぐらい動いているか、また、どのコマンドで使用されているかがわかるので非常に便利です。

# 通信

## 疎通確認

``ping``とかはよく使います。

``google.com``とかに``ping``すれば自分がインターネットに繋がっているか簡易的に確認できます。

また、自分の建てたサーバーに``ping``すればサーバーに繋がるか簡易的に確認できます。

## 名前解決

``nslookup``や``dig``もたまに使います。

Chromebookには標準で入っていないので、インストールする必要があります。

先ほど紹介した``grep``を使って、パッケージを探せばすぐ見つかります。

``nslookup``や``dig``は名前解決正しく行われているか試すときに便利です。

ドメインのDNS設定を変更したときや、自分でDNSサーバを建てたときなどに使うことがあります。

## ファイル取得

インターネットからファイルを取得する際には、``wget``を使います。

``wget {URL}``でファイルを取得できます。

## APIとか

``curl``でAPIにアクセスしたりすることがあります。

オプションで``GET``や``POST``、``IPv4``や``IPv6``を選択したりheaderを指定したりもできます。

``curl``はできることが多いので便利です。

``curl``でもファイルの取得は可能です。

というか、``curl``使ってる人のほうが多い印象です。

# ファイル

## 圧縮ファイル

圧縮ファイルを解凍したり作成したりするときには、7zをよく使います。

``7z x archive.7z```

こんな感じで使います。

詳しくはこの記事を見ることをおすすめします。

https://qiita.com/robozushi10/items/b334357244739d47f39e

# 最後に

この記事は備忘録のようなもので、そのうち更新するかもしれないです。
組込エンジニアとWEBエンジニアは別な職業だと思った

# はじめに

私自身新卒後は組み込みエンジニアとして経験を積みました。
紆余曲折有り、現在Webエンジニア（業務系アプリケーションを構築する中でWebを選択しているだけですが）として働いております。
転職活動をする中で組み込みの開発もWebの開発もどちらも面接等々行ったのですが、あれ？と思うことが結構ありました。
これからどちらの道に進もうか？と思っている方の参考にでもなれば幸いです。

# カッチカチの組み込みエンジニア

もちろん企業によるのかもしれませんが、かなり細かい部分まで気を配っていくのが組み込みエンジニアであろうと思います。
そこには理由があって組み込み特にも電源周りの開発は発火の恐れを気を配らなければなりませんし、音を出すようなものであれば突然の大音量が出てしまったなどにも気を配らなければなりません。
アメリカであれば簡単に訴訟問題へと発展する案件でしょう。
こういったところからかなり細かく開発規定を決める必要がありますし、レビューも相当に厳しく行う必要があります。

もっと頭を悩ませるのはメモリ系のバグです。
チップの中に入る容量は限られていますし、ましてやリークなど話になりません。
実機でデバッグしていく必要もあり、時にはデバッグ用の線だしなども行います。皆さんオシロスコープとか学校でやりましたよね？
あんなのどこで使うんだよ？と思うかもしれませんがめっちゃくちゃ使います。


# WEBエンジニアは別な悩みがある

EC、決済を行う、資金移動させる、個人情報を管理するなどお金であったり、法的に気をつけるべき部分には神経を使います。
一般的な攻撃手段に対する防衛策を講じ、脆弱性があったら対策パッチを当てていくなど常に対応が必要です。
ただ、昨今のIoT機器についてもこれは共通かもしれません。

# キャリアとしてのおすすめ

これから技術者の基礎力を高めたい！という方は組込みエンジニアを経験すると良いと思います。
幅広い知識を得たいという方はWEB・・・といいたいですがWEBだけではなくデータベース、インフラ、ネットワーク系の知識も合わせて経験できると良いと思います。
プロジェクトの学びを捨てることは大きな損失であるをChart.jsで描く

# 概要
別記事で
[「プロジェクトの学びを捨てることは大きな損失である」](https://note.com/dyamashita/n/n8f3f760bc761?sub_rt=share_pb)
を投稿しました。

その記事ではプロジェクトの損益について下記の３つの式を記載しています。

`損益 = 価値 − 投下資本 × ( 1 + 学習コスト率 )`

`価値 = 投下資本 × 価値創造率 × 成功率成`

`成功率 = 初期成功率 ×( 1+ 学習改善率 × 回数 )`

これらをChart.jsを使ってインタラクティブに計算するようにしました。

# やったこと
実際に作ったページのキャプチャです。
![スクリーンショット 2023-12-04 19.17.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20217/0f9a87ef-74ec-218d-a927-e7f6df834f8b.png)

こちらのサイトから閲覧できます。
https://dyson-yamashita.github.io/project-learn-chart/

[Chart.js](https://www.chartjs.org/)はJavascriptで様々はグラフを
描くことができ、Webページに埋め込むことができるライブラリです。

```
      const draw = function () {
        let context = document.querySelector("#chart").getContext('2d')
        const datasets = createDatasets()
        window.chart=new Chart(context, {
          type: 'line',
          data: {
            labels: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'],
            datasets: datasets,
          },
          options: {
            responsive: false,
          }
        })
      }
      ...
      <body>
      <canvas id="chart" width="600" height="400"></canvas>
```
こんな感じでcanvas上に記述することができます。
今回はとりあえず動くものとして、CDNからchart.jsを取得して
見た目は[Tailwind](https://tailwindcss.com/)を使って
classで指定しています。

ソースコードはこちらで公開しております。
https://github.com/dyson-yamashita/project-learn-chart
よければ、グラフで遊んでください。
以上、プロジェクトの学びを捨てることは大きな損失であるをChart.jsで描く でした。
BenQ GW2790QT をレビュー！

# やりたいこと
以下のキャンペーンに当選し、BenQ のモニター [GW2790QT](https://x.gd/jGpY3) を BenQ 様、Qiita 様からいただいたので、レビュー記事を書きます！

素敵なモニターをいただき、本当にありがとうございます！

https://zine.qiita.com/topics/202311-benq-review/

# GW2790QT
詳細は上記リンクに書いてありますが、主な機能をかいつまんで紹介します。

* リモートワークなどで長時間画面を見ることに対してのアイケア技術を搭載
    * B.I. Gen2 (ブライトネスインテリジェンス） 
    * フリッカーフリー
    * ブルーライト軽減プラス
* ノイズキャンセリングマイクの搭載
* ノイズフィルタースピーカーの搭載
* USB Type-C 1本で映像出力と給電が可能
* 高さの調整やスウィーベルが可能
* 用途に応じた画面モード切り替え

デジタル化が進んだ現代では、ディスプレイを長時間見ることが日常になっています。特にエンジニアは毎日ディスプレイとにらめっこをしてデジタル化のために開発を推進していることと思います。
私もそんなエンジニアの端くれなので、今回はエンジニア目線で GW2790QT の使い心地をレビューしていきたいと思います！

# デスク風景
デスクに配置してみました。たまたま白系のキーボードとトラックボールを持っていたので、白で統一してみました (壁にかかっているものはテニスラケットです:tennis:)。
普段使っているモニターは黒系なので新鮮でしたし、オシャレに感じました！

![20231204_090835.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1743460/81a19ee8-f027-6bf5-2acd-7d85f488851c.jpeg)

![20231204_090854.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1743460/d9e5ebb8-d7b2-90ab-a8a2-39c4c75bc049.jpeg)

# Good！
* Type-C ケーブル1本で済む！
    * 最近のモニターでは増えてきていますが、ケーブル1本で映像出力と給電ができるのは便利です
* B.I. Gen2 で動的に最適な輝度に調整してくれる！
    * 長時間作業する中で、環境光が変化しても輝度を最適に調整してくれるので目が疲れにくい
    * 環境光センサは画面下部に搭載されています
        * 上記写真だと下部ベゼル中央部の黒い箇所
* ノイズキャンセリングマイク！
    * ミーティング中に周囲がうるさくてもクリアに声を届けてくれる
    * 実際に、Zoom や Teams でのミーティング時に相手に確認してみましたが、けっこうクリアに聞こえているみたいです
* ノイズフィルタースピーカー！
    * ノイズをかなりフィルタリングしてくれて、雑音なく相手の声を聞くことができます
* 画面モード （**最推しポイント！**）
    * コーディングモードにするとコード内のハイライトされている部分が鮮やかに表示されるので、だいぶ見やすい
    * 左がノーマルモード、右がコーディングモードです (コーディングモードはくっきりと表示されています)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1743460/61d230d6-2372-a809-94b0-e344ef6278c9.png)

* USB ハブ搭載！
    * 画面左側に USB Type-Aのポートが2つとヘッドホン端子が1つあるので何かと便利
    * ただし、Type-C 接続時のみ利用可
* 細かいところに親切設計
    * スタンド上部に持ち運びしやすいように取っ手のような部分があったり、画面をチルトさせやすいように出っ張りがあったりと細かいところに親切設計を感じられます

# Not Good…
* ノイズキャンセリングマイクは Type-C 接続時のみしか使えない
    * これはしょうがない部分かもしれないですが、複数 PC を Type-C、HDMI　で接続している時に HDMI で接続している PC ではノイズキャンセリングマイクを使用できません
* ノイズフィルタースピーカーのフィルタリング度を強くすると相手の声もフィルタリングしてしまう時がある
    * このあたりは調整次第でどうにでもなりますが、最初に使った際に強になっていて何も聞こえず焦りました…
* KVM 機能が無い
    * 個人的に一番欲しい機能 (普段使っているディスプレイにはある機能)
    * 複数の PC を使い分ける時にデバイスの接続先を切り替えるのは割りと手間なので入力を切り替えてデバイスも同時に切り替わるのは便利
* Type-C の入力端子が1つのみ
    * これも複数の PC を使い分ける際の話ですが、Type-C ケーブル1本で映像出力と給電できるので複数 PC を使う際もそれぞれ Type-C で接続できれば便利だなーと思います
    * 他ディスプレイでも複数の Type-C 端子を備えているものは無い気がしていますが…
* 下側のベゼルが太い
    * 本体下部にボタン類がある都合上なのかもしれませんが、下部のベゼルが太いです
    * 他3辺は狭いですが、下部ベゼルが太いことでやや野暮ったい印象です
* 画面モードの切り替えは手動
    * これは難しいと思いますが、いちいち手動で切り替えるのが面倒でした
    * 別途アプリケーションをインストールして、登録したアプリケーションのウィンドウがアクティブになった際に自動的にモードを切り替えるなどできると嬉しいなと思います
    * 頻繁に切り替える場合は逆に邪魔かもしれませんが…
* 価格面
    * 今回はプレゼントという形でいただきましたが、価格は同じ解像度の他ディスプレイと比べるとお高めです
    * 正直、自分で購入するかと言われると微妙なところ…
    * 機能面は非常に充実しているので価格以上の価値はあると思います

# 総評
総合的に見て、非常に良いディスプレイだと思います。
特にアイケア機能が充実していて、普段使っているディスプレイを使った際より目が疲れにくい気がします。また、画面モードによって用途にあった輝度や彩度にしてくれるのは非常に便利でした。
リモートワークの頻度も会社によっては下がっているかもしれませんが、PC で作業する際にはやはり良いディスプレイを使いたいものです。自宅での作業ではもちろん、会社でもこういったディスプレイを用意してもらえると目の疲れを考慮しつつ作業でき生産性も向上するかもしれませんね！

BenQ 様、Qiita 様
改めて、今回このようなディスプレイをいただき本当にありがとうございました！
本でPower Automateを勉強してみた

このブログは「Microsoft Power Automate Advent Calendar 2023」の４日目 の記事です。<br>
[≪ 前日の記事はこちら](https://zezeze.hateblo.jp/entry/2023/12/03/065618 "Microsoft Power Automate Advent Calendar 2023 ３日目の記事")
[≫ 明日の記事はこちら](https://qiita.com/advent-calendar/2023/powerautomate "Microsoft Power Automate Advent Calendar 2023 ５日目の記事")

https://qiita.com/advent-calendar/2023/powerautomate


# はじめに
この記事はPower Automate初心者が勉強した内容をまとめたものです。
チャレンジしてみようと思われる方のご参考になれば幸いです。


# 今回は本で勉強してみた
昨年は動画で勉強しましたので、今年は本で勉強してみました！
使用した本はこちら！

https://book.impress.co.jp/books/1122101184


# 感想と学んだこと
まず、基本的なところから体系的に学べたことがよかったです。
また、分からなくてもとりあえず手を動かしてみましょう、の精神で進めてくれるのはありがたかったです。
自分が手を動かして失敗して覚える派だったので、書籍の図解も分かりやすく進めやすかったです。
自分のペースでじっくり進めたい方におすすめですね！<br>
また、アウトプットも「基本編」「活用編」「応用編」と段階を踏んで進めてくださっているので、挫折せずに進めることができました。各章の内容も、難易度が簡単なものから難しいものという形で構成してくださっているので助かります！<br>
また、ある程度テンプレートで思い通りのものが作れそうですが、細かい自動化については応用編のお作法を覚えないと厳しいことも学べました。式や関数の使い方もよく分からないな～と思っていたので、まとめられていて助かりました！
最後に運用方法とエラー対処についても解説があり、至れり尽くせりでした。

私にとっては、少しレベルアップできたと実感できる一冊でございました👍


# 勉強を通じて感じたワクワクポイント✨
やはり通知系は人気だな～と思いました。
以前自分でTwitterのツイートを決まった時間に取得するテンプレートを設定したころがあるのですが、ちゃんと時間通りに動作するのはワクワクしますね✨
そういう意味では、通知関係は動いたかどうかが視覚的に分かりやすく、自動化の魅力を伝えやすい題材だなと感じました。<br>
あと、トリガーをいろいろ設定できるのも魅力的と感じました。手動はもちろんのこと、時間や処理を起点に自分の思い通りに処理が実行できるのもいいですよね😊
計画通りに処理が完了すると思わずニヤッとしてしまいます！<br>


# まとめ
今回勉強してみて、以下のことが学べました。

1. Power Automateは、コネクタを組合わせて自動化すればするほど楽しくなる！
1. 通知系フローやトリガーはワクワクできる✨
1. でも自分はまだまだ勉強不足なので本の内容を再復習したい💪

以上、参考になれば幸いです。
データパイプラインのテストってどうやるの？

# やりたいこと
Advent Calendar に参加するので、テストについて疑問に思っていたことを書いてみます。
データウェアハウスなどのデータ基盤にデータを Ingest する際に、何らかの ETL ツールでパイプラインを作成して行うことが一般的だと思いますが、その際のパイプラインのテストってどうやるのがいいのかという内容と、こういうテストツールが欲しいという内容です。

# 経緯
以前、Azure 上でデータ基盤を構築したことがありました。その際も Azure で提供されている ETL サービスを使っていたのですが、それが、GUI で提供されているもの ([Azure Data Factory](https://learn.microsoft.com/ja-jp/azure/data-factory/introduction), [Azure Synapse Analytics](https://learn.microsoft.com/ja-jp/azure/synapse-analytics/overview-what-is) など) で、処理ごとにブロックを配置して ETL パイプラインを組み上げていくものです。
GUI で開発できるのは視覚的に分かりやすく作成しやすい反面、細かい処理などを行うにはやや手間がかかります。特に、作成したパイプラインのテストを行う際は、実際にデバッグモードとして手動で実行して確認する必要があり、手動で実行するので CI/CD のパイプライン上で実行することもできず、どうしたものかという状況でした。

:::note info
手動実行を外部から呼び出す方法やテストを自動化できる方法があるのかもしれませんが今もその方法については分からないので、ご存知の方がいればコメントいただけると嬉しいです！
:::

# 一般的なテストだと
一般的なテストだとそれぞれの言語のテストフレームワークで単体テストを行い、さらにはそのテストを自動化して、CI/CD に組み込むということが多いと思いますが、上記のパイプラインだとそういったことができず、テストにそれなりに時間がかかってしまっていました。

一応、上記のサービス上でパイプラインの各処理をコードで実行させることはでき ([Azure Databricks](https://learn.microsoft.com/ja-jp/azure/databricks/introduction/) の Notebook や [Azure Functions](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-overview?pivots=programming-language-python) を呼び出す形)、そのコードを単体テストしたり全体の処理をテストすることはできるのですが、視覚的に分かりやすいというメリットを潰してしまいます。

# こういうテストツールが欲しい
上記のような状況のパイプラインを自動テストできるようなツールがないのかなーとは常々思っています。単純にパイプラインの Input と Output を定義して、実行結果がその Output になっているかということだけでも自動化できるとだいぶ楽になるだろうなと。できればパイプライン内の各処理についても同様に Output のチェックができるとなお嬉しいですね！

ただ、このケースだと 3rd Party のテストツールというよりは、Azure などのサービスプロバイダー側で何らか用意されるというのが現実的なのかなとは思いますが…

# ということで
以前からどうやるのが良いのか分かっていない、GUI で提供されるデータパイプラインのテスト (特に自動化) について思うことを書いてみました。ニーズのありそうな機能ですが、提供されていないということは何らか実現が難しい理由があるのでしょうか？:thinking:
詳しい方がいれば教えていただきたいです！


以上です。
Cluster Lobby - もっとも多くの人が行き交うメタバースを目指して

[クラスター株式会社](https://corp.cluster.mu/])でコミュニティーマネージャーとして、さまざまな人たちが安心してすごしそれぞれの形の創作活動や表現を実現できるように、ロビーの運営を行ったりイベントなどの施策にたずさわっているso1_こと北村聡一です。

クラスター株式会社の外側では、特定非営利活動法人西荻ぷれま委員会というNPO法人の代表を務めており、現実世界のコミュニティと、メタバースのコミュニティと、両方にたずさわりながら人々の関わり合いについて考えて過ごしています。

[Cluster Lobby](https://cluster.mu/w/ac642699-be79-4fc5-abee-ae1c51c5ec7a)は、非常に多くの人たちがおとずれるメタバース空間の入口となるワールドです。同時刻に滞在する人数も多くいますし、また、さまざまな国の人、さまざまな年齢の人が利用します。

今日はそんなCluster Lobbyではどんなことに気をつけているのか、その一部をおはなしします。

# 軽快さ
多くの人たちにつかってもらえる、素敵なワールドにしたい、かっこいい見た目や、楽しいものを増やしたい。もちろんそのように考えて作るのですが、一方でさまざまなネットワーク環境、デバイスを利用される方がいる中で多くの人たちが快適に利用できるように厳しい軽快さが求められます。

メタバース空間に滞在する際の軽快さは、「ワールド」「アバター」「利用状況」に影響されます。さまざまな、たくさんの人たちに利用してもらいたいと考えているCluster Lobbyでは、「アバター」や「利用状況」に関して、なるべく好きなアバターで表現して欲しい、多くの人にただいるだけでなく、喋ったり動いたりしてコミュニケーションをとって欲しいと考えるため、「ワールド」について限界まで軽くするという一択になります。

どういう要素があるのかなど書いてみようかとも思いましたが、ここはプロが様々な工夫を凝らしている世界で、半端な知識で書くことが誤解を招きかねないため、割愛することにします。

素敵にしたいのに、軽くしないといけない。そんな矛盾したことをなにが体験への効果を持つのか1つ1つの取捨選択と、コンピューターの処理への知識と技術から軽快さは作られていきます。

# 言語
clusterは現在でも、たくさんの言語を話す人たちが利用しています。まだ、言語になれない年齢の人も利用しています。そしてこれは、今後もっともっと多くの人たちに利用していただきたいと考えています。

このため、Cluster Lobbyでは文字のような言語での表現をなるべく少なくするように気をつけています。

現在のclusterでは言語ごとのリソースの出しわけができて、言語ごとに異なった表現をすることができるのですが、異なる言語を使う人が同じ場を楽しめるようにと考えると言語への依存は少なく、より伝わりやすい表現をという選択肢を考慮することになります。

自動翻訳や、AIを介したコミュニケーションなど、言語に関連する技術がもっともっと向上していくと、ここについては全く異なる手段が用意されて行くのかもしれません。楽しみです。

# 安心感
clusterのロビーには、たくさんの「初めての人」が集まります。多様なひとたちが安心できる場所ということを考える時に、常に意識するのは「初めての人」になります。

安心感という感覚には、「変わらないこと」だったり「相手のルールがわかっていること」だったりが影響を及ぼします。誰にも邪魔されない自分だけの場所だったり、顔馴染みの相手がいる場所は安心感がありませんか。

でも、Cluster Lobbyという場所は「変わり続ける場所」であり「さまざまなルールの人がおとずれる場所」です。

そこで、様々な「初めての人」とコミュニケーションし、一人一人異なる「初めての人」を少しずつ知っていきながらどんなことに不安になるかを見つけて、不安材料を少なくするように検討をしていきます。

Cluster Lobbyで動いているスタッフは、異なる背景の人材がつどっていて、それぞれの違う視点からどのようにすると「初めての人」の安心を作れるかを考え、お互いの考えや表現を交換しながら安心できるCluster Lobby作りに務めています。

# 終わりに
「ロビーについて何か」ということで書き始めた本稿ですが、なんてことないことを延々と書いてしまったかなーという気持ちにもなりました。。

多くの人がのびのびすごせる安心を作ることを考えることは、わりと当たり前なことの積み重ねなのかもしれません。

一つずつ当たり前のようなことが、時に矛盾するかのように立ち塞がってきます。バランスをとりながら、魔法のように安心できる場所を作れる日まで、延々と考え続けていきたいとおもいます。
コラボフロー×LINE WORKSのコラボレーション！

また寒い冬がやってきました。
春夏秋冬あるのはいいけど、ほんとせわしないですね。
洋服が4種類もいるのはなかなか大変です。

さて、4日目の本日は、コラボフローをもっと便利に身近に使ってもらえる方法を記事にします！

コラボフロー＝申請・承認の電子化と思われがちで、なんか承認ってかなり大そうな話だな・・・・
そんな風に感じる方もいらっしゃるのではないでしょうか？！

実はコラボフローは承認行為以外にも使っていただけ、もっと身近に使ってもらえる方法がございます！

皆様おなじみ、LINEのビジネス版**LINE WORKS!!!**
本日はLINE WORKSとのコラボレーションについて紹介します！



## LINE WORKS連携でできること！
・LINE WORKSのコラボフロー専用のトークチャットから、申請したいコラボフローの文書を呼び出す
・コラボフローの申請書に関する通知（承認依頼や確認依頼）を、LINE WORKSのコラボフロー専用トークチャットで受け取る
![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632132/bf853dde-1db1-0e69-96fe-3310f4175a51.png)



## メリット！
連携することで何がいいの？なのですが、
・2つのバラバラのシステムを使っているように見えるが、入り口をLINE WORKS　1つにできる
・会社に戻らなくしても、外出先から紙業務の処理ができる

最近、会社に色々なシステムが入ってきて、いつどんなときに、どのシステムを使えばいいのかちょっと混乱する・・・なんてことないでしょうか。
LINE WORKSを使えば、入り口はすべてLINE WORKSにすることができ、システムに不慣れな方でも、しっかり使っていただけます！

また外出が多くて、会社に戻ってから大量の紙業務の処理をしなければいけない・・・そんなときも、外出先からお手持ちのスマホで簡単に処理が可能になるので、空いた時間を別のことに使っていただくこともできます！


## どんな業務に使える？
では実際どんなシーンで使えるかをご紹介します！

### ・事故報告書
あまり頻発するのはよくないですが、
緊急事態発生時にその場で写真をスマホでとって添付し、報告書を出す
なんてこともできます。

### ・直行直帰申請
外出先から会社に戻る予定ではあったが、前後の予定の関係で急遽現場に直行したり直帰したり、そんなときもスマホから申請することができます！



# まとめ
コラボフローは「社内」での稟議書の用途が多いですが、その他承認とまでは言わずとも報告書関連でも使用していただけます。
その際にビジネスチャットツールのLINE WORKSと組み合わせることでもっと身近に使っていただけるので、是非ご参考にいただけますと嬉しいです！
「//このコメントを消したら動かない」は大体Shift_JISの2バイト目が原因で発生する

## TL;DR

Shift_JISにしただけでコンパイラが通らなくなる恐ろしい事件とその回避法について。

- \ (¥)のASCIIコードは0x5c
- 表、能は良くない
- UTF-8は神

## 2023/12/06追記

誤りがあったので訂正します。こんな読まれると思ってなかったので正直ちょっとびっくりしていますが、いろいろコメントありがとうございました。（ツイート等全て拝見しました。）

- Shift_JISが悪いわけではない（デフォルトのエンコーディング設定の問題）→追記しました
- UTF-8にはUTF-FSSという仕様でこの問題が回避されている→マジでタメになる知識ありがとうございます
- OSによってデフォルトのエンコーディング設定が異なるせいで、デフォルト環境での動作がOSにより異なる→なるほど？（調査中）
- CRLFとLF問題では→なるほど？（調査中）
- そんな問題何を今更→UTF-8が出てから生まれたからです。

## \を改行とみなすかどうか

C言語のコンパイラは\が行末に来ると改行を無視します。

``` cpp
int main(void) {
    //この行はコメントだよー \
    この行もコメント
    この行はコメントではない
    return 0;
}
```

例えば、このプログラムはエラーになるのでダメです。

``` cpp
int main(void) {
    //うわー \
    if (1) {
    }
    return 0;
}
```

これは`if(1) {`がコメントと解釈されると、それに対応する中括弧が対応しなくなるためです。

## 本題 Shift_JISのトラップ

ここからが本題です。

``` cpp
int main(void) {
    //あいうえお
    if (1) {
    }
    return 0;
}
```

このプログラムは問題なくコンパイルできます。（そりゃぁそう）

``` cpp
int main(void) {
    //プログラムの才能
    if (1) {
    }
    return 0;
}
```

しかしこちら、Shift_JISで保存してコンパイルすると、エラーが起こることがあります。は？

![アートボード 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628782/e5fbbc29-71a4-ba44-334c-ff8e3bff9e4b.png)

\ (¥)のASCIIコードは0x5cなので、エンコーディングの設定が間違っているとコンパイラが能の2バイト目を\と解釈してしまいます。そうすると`if(1) {`が無視されてエラーとなります。

他にもこのような文字は存在していて、全部書くと書ききれないのですがよく使いそうなものだと

-	ソ
-	噂
-	欺
-	圭
-	構
-	十
-	申
-	貼
-	能
-	表
-	暴
-	予

です。表・能・欺とかは割と文末に来ることが多いので注意です。

これらは下位バイトが5cなのでShift_JISでプログラミングするときに行末にあってはいけません。ダメ文字[^1]と一部界隈はよばれているそうです。

## 結局あのコメントはなんだったのか

``` cpp
int main(void) {
    //プログラムの才能
    //このコメントを消したらなぜか動かない
    if (1) {
    }
    return 0;
}
```

先ほどの説明を踏まえるとこのコメントを説明できます。能の次の行がコメント（又は空白行）だと\と解釈されても次の行がプログラム的に意味を持たないため問題なくコンパイルできます。

## 対策

- ダメ文字を使わない
- Shift_JISを使わない
- 正しくエンコーディング設定をする

ちなみに先ほどの能が文末にくるプログラムは、UTF-8ではUTF-FSSにより下位バイトが5cになることはない[^2]ので（流石！！）問題なくコンパイルできます。

コンパイル時にエンコーディングを正しく設定するとこの問題は発生しませんが、特別な理由でもない限りUTF-8で保存するのが無難だと思います。

## Shift_JISの名誉のために

Shift_JISさん悪く言ってごめんなさい。確かにバイト数が少なく済むのはいいと思うのでがんばってね。~~俺は使わないけど。~~

## まとめ

Shift_JISやめましょう

## 参考文献

1. 文字コード表 シフトJIS(Shift_JIS) http://charset.7jp.net/sjis.html

[^1]: https://ja.wikipedia.org/wiki/Shift_JIS#2バイト目が5C等になりうることによる問題
[^2]: https://ja.wikipedia.org/wiki/UTF-8
フレームワークを改修した話（Ethna）

みなさん、こんにちは！

長く開発をやっていると、使用した技術がいつのまにか古くなっている、というのがよくあります。
言語のバージョンもそうですが、フレームワークも同じです。

今回は、フレームワークが古くなった時の体験談です。

# 背景
過去に、とあるショッピングカートの開発を担当してました。
当時Ethnaというフレームワークを利用していたのですが、入社して3年ほど経ったときに、フレームワークの開発がストップしているのが発覚。

PHPのバージョンはどんどん上がっていき、フレームワークのPHPバージョンはもうすぐEOL。
さあ、どうする？？という場面に直面し、色々と調査することに。

# 調査内容
## 他のフレームワークを調査する
当時の状況から、候補となったのは、以下の3つでした。
・CakePHP
・FuelPHP
・Zend Framework

使いやすさから考えると、一旦、CakePHPがいいのではないか、という結論に。

## 開発工数を見積もる
当然ですが、作り直した場合に、どのくらいのコストがかかるのか、という調査をします。
担当は私一人の前提で、機能数や画面数から算出した工数とメリット、デメリットは

**開発工数：** 12ヶ月
**メリット：** 今後もフレームワーク側でPHPのバージョンアップへの対応を見込める
**デメリット：** コストがかかる

それなりの規模のサービスだったので、標準的な開発工数でした。

## 改修した場合の工数を見積もる
正直、あまりやりたくない対応内容ですね。
PHPで作られているので改修はできるのですが、中身をよく理解していない状態で手を出すと、どこにリスクが潜んでいるか分かりません。

以下の手順で調査しました。
1. 最新のPHPバージョンとの差分をChangeLogからリストアップ
2. 廃止や仕様変更になっている関数をgrepで抽出
3. 2を利用している機能（影響範囲）を調査
4. フレームワークの改修箇所と影響範囲から、工数を算出

その結果、算出した工数とメリット、デメリットは

**開発工数：** 3ヶ月
**メリット：** コストがかからない
**デメリット：** 今後もPHPのバージョンアップに合わせて同様の改修が必要になる

# 結論
上記2パターンを上司に提出し、出た結論。

**「フレームワークを改修する」**

なるほど、そうなりますよね。

ただし、これには、単純にコストだけではなく、それなりの理由があります。

## 理由
**1. できるだけ低コストにしたい**
これは、営利企業である以上、仕方がないです。
何をやるにも人件費がかかるので、費用対効果を考えると、コストがかからない方が望ましいです。

**2. 今後伸ばしたいサービスではなかった**
ユーザーもいて、黒字のサービス。
しかし、主力サービスではありませんでした。
競合も多く出てきた中で、このサービスにどのくらいの人件費を使うべきか、という判断が必要になります。

**3. 費用対効果を考えると、フレームワークの改修がベター**
エンジニア的には、作り直した方がやりがいもあり、充実感があります。
しかし、一つの企業として考えた場合、優先すべきは費用対効果です。
作り直しても利益の増大を見込めないため、フレームワークの改修、という結論に至ります。

（※ここは多くの企業で、エンジニアと経営陣との違いが出る部分です。）

# 改修で苦労した点
PHPのバージョンアップに伴い、どうしても仕様の変更内容が理解できない関数がありました。
その理解できなかった関数というのは、

`pack()/unpack()関数`

です。

ChangeLogだけでなく、PHPのソースコード（C言語）も確認したのですが、いまいち理解できず。
しかし、これを利用している機能があったため、どうにかしなければいけません。

## どうやってカバーしたのか
方法としては、かなり単純です。

- **この関数を通るリクエストを洗い出し、ログから全パターンテストを実施**

テストパターンの抽出が大変でしたが、PHPのバージョンアップ前とバージョンアップ後で結果を比較し、全く差分が無いことを確認しました。

もし一つでも差分があればもっと踏み込んだ調査が必要だったので、助かりました。

このようにして、無事にPHPのバージョンアップを行うことができました:smile:

# まとめ
割とレアなケースかと思いますが、いかがでしたでしょうか。
開発者といえど、ある程度の費用対効果は考える必要があります。

私自身、やってみたいことは色々とありますが、それらは全てプライベートでやってます:slight_smile:

そこで力をつけて、チャンスがあれば仕事として取り組む、という意識でいた方が、色々とうまくいくのではないでしょうか。

技術は日々進歩していきますが、まずはしっかりと自己研鑽を行ない、チャンスが来たときに、いつでも掴める準備をしましょう！
cloudfront + s3 で react で spa を作成したときのページ遷移


cloudfront でエラーページ 404 を設定する必要がある。react-router-dom を使っている。
CloudFront > ディストリビューション > {DistributionID} でエラーページのタブから設定ができる。これをしておかないと、そんなページがないよ、となってしまう。

![err404.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/64b0c484-10e2-8de6-14a0-ec3eb6d0c63e.png)

参考ページ。

https://stackoverflow.com/questions/70850620/404-errors-on-path-requests-to-react-app-on-aws-s3-using-react-router-dom
人間を作ったよ！！！

## はじめに
クソアプリ [Advent Calendar 2023](https://qiita.com/advent-calendar/2023/kuso-app) カレンダー2 の9日目の記事です。

## 人間

今年は人間（うんちせいぞうき）を作りました

https://www.unchi-seizouki.com/

普段ウンチを使いたいときに自分の気に入ったウンチが見つからないことが多かったので手軽に作れるようにしたいと思い、人間を作りました

作ったウンチはSVGとしてDLできるようにしているのでご自由に利用してください。

## 利用した技術
#### いつもの
- next 
- emotion

#### 状態管理
- jotai

#### 色のピッカー
- react-color

#### SVGモーフィング
- react-spring
- flubber

作ってる途中でrecoilが保守されないらしいと聞いたのでjotaiに乗り換えてみました
jotaiは結構使いやすいのでオススメです。

## こだわった点
### SVGモーフィング
モーフィング
ある画像から別の画像へ、連続的に変形させる表現らしいです。
どうしてもうんちをぬるぬる変化させたかったのでモーフィングさせてみました。

- モーフィングなし

![モーフィングなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390321/2c3a9f04-53be-e1e9-779e-a1b66997ea4d.gif)

- モーフィングあり

![モーフィングあり.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390321/9b800957-4413-3f22-8fdc-c4b58cd43416.gif)

モーフィングある方が可愛いですよね！

``` ts
type Props = {
  unchi: () => string;
};
function SVGMorphing({ unchi }: Props) {
  const [color] = useAtom(colorAtom);
  const animationProps = useSpring({
    from: { x: 0 },
    to: {
      x: 1,
    },
    config: {
      tension: 150, // テンションを調整
      friction: 10, // 摩擦を調整
    },
    reset: true,
  });

  return (
    <svg viewBox="0.00 0.00 150.00 150.00" id="dl-svg" css={Canvas}>
      <animated.path d={animationProps.x.to(unchi)} fill={color} />
      <MayuSvg></MayuSvg>
      <EyeSvg></EyeSvg>
      <MouseSvg></MouseSvg>
      <ItemSvg></ItemSvg>
    </svg>
  );
}
```

SVGMorphingの呼び出し側はこんな感じ

``` ts
  const [widthIndex, setWidthIndex] = useState(0);
  const [heightIndex, setHeightIndex] = useState(0);
  const [interpolators, setInterpolators] = useState({
    unchi: () => unchi[heightIndex][widthIndex],
  });

  return (
    <div>
      <SVGMorphing unchi={interpolators.unchi}></SVGMorphing>
      (中略)
    </div>
  );

```



## 妥協したところ

本当はURLにパラメーターを渡して動的OGPを作りたかったのですが
~~パーツの位置や大きさなどを設定するのが難しくて諦めました...~~
と思ったけど時間ができたので実装しました

がvercelの無料枠だとできないみたいです


```
Error: The Edge Function "api/og" size is 1.07 MB and your plan size limit is 1 MB. Learn More: https://vercel.link/edge-function-size
```

SVG使いまくってるからこれ以上減らすところがなく...
残念ながら諦めました。石油王だったらProプランにできたのに...

ちなみにNextの機能に乗ったらかなり簡単に動的OGPに対応できるので開発体験は良かったです。


## あとがき
「自分なんてうんちせいぞうきだよ～」って自虐する人は是非SVGでDLできるようになってください。
技術書典に寄稿した感想などをざっくばらんに書いてみる

超久しぶりに投稿します。今回はCode Polarisという女性エンジニアコミュニティで、合同誌に寄稿した感想などざっくばらんに書いていこうかと思います。

## 合同誌に寄稿しようと思った理由
技術書典に参加しようというのを提案してくださった方がいて、それを見て「なんとなく面白そう！」と思い、勢いで始めました。あと、コミュニティに参加したものの、特に何かする訳でもなく見る専だったので何か交流を深めたい！という思いも少しありました。

## アウトプットすることのメリット
#### 理解が深まる
アウトプットを通じて自分の中で曖昧だった部分を再確認したり、初心者に分かりやすく説明するための言語化を試みたりすることで、言語への理解が格段に深まりました。

ちなみに技術書典15ではGoについて寄稿したのですが、4月から初めてGoを書き始めたばかりで理解が浅く執筆に苦戦しました。
例えばgo.modの役割やエラーハンドリング方法など、初めての人にどう書けば伝わるかなど改めて調べ直したりを繰り返していました。この経験を通じて理解がかなり深まったと感じています。


*「教えることは二度学ぶことである」* というとある哲学者の言葉がありますが、まさにその通りだなと実感させられました。

#### 実は結構アウトプット好きだった
これまでアウトプットの経験はほとんどありませんでしたが、記事を執筆してみて、意外と楽しいことに気づきました。今後も機会があれば、また寄稿したいと思いますし、LTなど話す方のアウトプットにも挑戦してみたいです。

## 締切との戦いは今後も課題
ただ、原稿につきものなのが締切です・・・。日々の仕事とプライベート（子育て）が忙しく、執筆時間を確保するのが大きな課題でした。休日夫に子供を任せたり、思うように文章が進まない時はChatGPTに助けを求めたりしていました。これは今後も続く大きな課題です。。。（どう解決しようかなぁ）

## 最後に宣伝
Code Polarisで技術書典14、15で頒布した合同誌です！
https://techbookfest.org/product/t5yrq2S40rRArJWuf1swPz?productVariantID=5WkbJxvfF2RsvvyKN9qfut
https://techbookfest.org/product/b4z1CZcTcfh0TuVfAFt3j8?productVariantID=9A7htvSp3ZB6Z50FbAgFDL
Githubでプルリクを作成したらGCPにレビュー環境を自動的に作成する

フロントエンドのレビューで動作確認するのが、ちょっと面倒だったけど、GCPのお陰で、レビューの手間が減った話

# はじめに
恐らくフロントエンドのレビューってこんな感じだと思う。
1. github上で、コードチェック
1. 現在作業中のコード変更分をstashなどに退避する
1. レビューするブランチにswitchする
1. 動作確認
1. レビュー終わったら作業中のブランチにswitchしstashから戻す

この２〜５が意外に面倒なんですよね。

しかも、今の現場がそうだけど、1日に、４、５回もレビューする時は、この２〜５の作業がバカにならない。

しかーし、GCPを使えばこんなことをしなくて良くなる

# GCPで解決
題名の通りのことをできれば、２〜５の作業をしなくて済む
1. プルリクエストを作成
1. githubにpush
1. mainブランチに対してプルリクエストを作成
1. プルリクエストが作成されたら、GCPにアプリをデプロイ

これができれば、レビューするときの動作確認はGCP上のアプリに対してすれば良いので、ローカルの作業をいちいち退避する必要がない！

# 参考資料
ベースは下記を参考にした。

https://shashankvivek-7.medium.com/continuous-deployment-of-angular-app-on-google-app-engine-with-git-c83d4e14e84

# やってみる
## GCP側
参考資料に記載の通りに、GCPにプロジェクトを作成し、Cloud Buildの設定をする。

その後も、IAMやロールを設定する

## アプリ側
### app.yaml作成する
基本、参考資料の通りです。

一応、コード載せておきますね。
```yaml
runtime: python27
api_version: 1
threadsafe: yes

handlers:
  - url: /
    static_files: dist/apps/myorg/index.html
    upload: dist/apps/myorg/index.html
  - url: /
    static_dir: dist/apps/myorg

skip_files:
  - e2e/
  - node_modules/
  - src/
  - ^(.*/)?\..*$
  - ^(.*/)?.*\.json$
  - ^(.*/)?.*\.md$
  - ^(.*/)?.*\.yaml$
  - ^LICENSE

```

### cloudbuild.yaml作成する
こちらも参考資料を元にしましたが、少し変更してます。
```yaml
steps:
  - name: 'gcr.io/cloud-builders/docker'
    args:
    - 'build'
    - '--build-arg=NODE_VERSION=18.10.0'
    - '--tag=gcr.io/17551150001/yarn:node-18.10.0'
    - '.'

  # Install node packages
  - name: 'gcr.io/17551150001/yarn:node-18.10.0'
    args: [ 'install' ]

  # Build productive files
  - name: 'gcr.io/17551150001/yarn:node-18.10.0'
    args: [ 'run', 'build', '--prod' ]

  # Deploy to google cloud app egnine
  - name: 'gcr.io/cloud-builders/gcloud'
    args: ['app', 'deploy', '--version=${_PR_NUMBER}', '--no-promote']
```

ポイントとしては、gcloudコマンドの下記2つ
1. '--version=${_PR_NUMBER}' でgithubのプルリク番号
1. '--no-promote'でユニークなURL

## プルリク作成してみる
これで、プルリク作成すると、参考資料のとおり、失敗するので、`gcloud app create`コマンドを実行。

ちょっとうろ覚えだけど、自分は試行錯誤で色々プロジェクト作成してて、プロジェクトを指定してこのコマンドを実行した気がする（うろ覚えですいません）

参考資料のとおり、Retryしてみたけど、まだ失敗。。。
permissionエラーだったので、下記を参考に解消。

https://twitter.com/beltway7/status/1728762639902445789

で、再びリトライすると・・・

## ビルド成功
はい、ビルド成功！！
![Screenshot_2023-12-04_at_18_53_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89497/8e9b2495-c35a-f33a-498a-fc2ff80dda8f.png)

赤線のURLに接続するとちゃんと画面が表示されました。

# 最後に
これは、本当に便利！！
もう、レビューのために、コード退避したり、ブランチ切り替えなくて良くなる！！

まだ少し、課題があって、今後対応予定。
- github側に接続URLを表示したい（今はGCP見に行かなきゃいけない）
- 古いバージョンは自動的に削除したい（現状、残り続けるはず、お金が勿体無い）
FIT(Failures In Time)という指標を用いて自社デバイスの品質を可視化したお話

この記事は[株式会社ビットキー Advent Calendar 2023 ](https://qiita.com/advent-calendar/2023/bitkey) 6日目の記事です。
ハードウェア製品の品質保証（HWQA)を担当をしている高石 [(@ksk_taka)](https://twitter.com/ksk_taka)が執筆します。
※昨年までファームウェアのチームマネージャを担当していましたが、現在は主に品質可視化・改善を主業務としています。

# はじめに

ビットキーではbitlock MINIなどのスマートロック製品をはじめとした種々のハードウェアデバイスを市場に提供しています。

筆者が入社したのは2019年10月で、その時点で複数の製品を市場に投下していました。更に2021年には新機種を投入し、現在もなおシェア拡大を目指しています。

市場に提供するデバイスの種類や台数が急速に増えている中で、社内でも「発売済の製品がどの程度の品質なのか」という指標を可視化する重要性が非常に高まって来ました。

品質可視化をする上で、今回着目したのがFIT（Failures In Time）という指標です。

# FITの定義と、FITを利用するメリット

## FITの定義
FITは特に電子部品業界でよく使われる指標で、製品が単位時間あたりにどの程度故障をするのか、を表す指標です。
機種ごとのFITの値が算出できれば、「どの製品をどのくらいの期間利用した場合にどの程度故障するのか」を容易に把握することができるようになります。

具体的にはFITの値は以下の計算方法で算出できます。

```math
FIT = (故障件数  \div 稼働時間) \times 10 ^ 9
```

## FITを利用するメリット
FITという指標を導入することにより、以下が見込めます。
- 複数存在する機種について共通の品質指標で見れる・語れる様になる
- 業務の優先順位付けが容易になる
- （FITという概念を社内認知してもらえば）技術者以外とも品質に関するコミュニケーションがしやすくなる

# 実際のFITの算出方法

上述した計算方法の通り、機種ごとに**累計の稼働時間**と**故障件数** が分かれば、それぞれの機種におけるFIT値が算出できることになります。

### 機種ごとの累計駆動時間の算出
ビットキーが扱っているデバイスは、ほぼ全てBLE機能を搭載しています。「利用開始する際にスマートフォンアプリから初期設定をする」ということが必須になっており、その利用開始期日はログとしてサーバーに記録されています。

この「利用開始日」から現在までの時間（＝稼働時間）を機種ごとに集計すれば、**機種ごとの累計駆動時間**が算出することができます。


### 機種ごとの故障件数の算出
**故障件数**を割り出す為には、そもそもの**故障**について定義をする必要があります。

理想を言えば機種ごとに「故障」を厳密に定義した上で故障の件数が出せれば良いのですが、まずは手っ取り早く現状を可視化したかったため、いささか乱暴ではありますが以下の様な定義をしました。

#### 故障の定義
```math
故障数 = 市場からの問い合わせ発生件数
```

#### 問い合わせ発生件数の集計方法
故障について定義ができたので、次は**故障数の集計方法**を考えます。
ビットキーでは、市場にリリースしたプロダクト（ハードウェア製品／ソフトウェアサービス問わず）についての問い合わせ対応を、**dev_前衛**と呼ばれるSlackのチャンネルに集約しています。

参考：[製品改善を最前線で。我ら「dev前衛」](https://qiita.com/kodai_seto/items/f8879f4857a19f942205 "製品改善を最前線で。我ら「dev前衛」")


このdev_前衛チャンネルに投稿されているもののうち、ハードウェアデバイスに関する問い合わせを機種ごとに集計することにしました（集計方法も工夫しているのでこちらはまた別途）


# デバイスごとに算出したFIT値の管理方法
上述までの方法で、**機種ごとの特定期日におけるFIT値**は算出できるようになりました。

ただスポットで現在の品質を可視化するだけではせっかくFIT値を算出した意味が薄いので、現在は以下のような運用をしています

- 機種ごとに月次でFIT値を算出
- 月次FIT値の推移をグラフ化
- FIT値の高い（＝問い合わせ数＝故障数が多い）機種から順に、不具合の対策を実施

上記の様にすることで、機種ごとの品質を可視化するだけでなく、その品質の変化推移も容易に確認することができるようになりました。



### 実際の可視化イメージ（サンプルデータであり実態とは異なります）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323105/a61c2e49-d853-b452-ad01-9d1502973095.png)


# 終わりに
上記の様に機種ごとのFITをまとめることで、機種ごとの品質の可視化ができ、優先順位の決定なども非常にしやすくなりました。

今回の説明では割愛していますが、実際には更にこのFITを細分化して、「機種・事象ごとのFIT値」を算出した上で、どの課題から解決していくかの意思決定に繋げています。

今後は更に、以下の様な検討を進めて行く予定です。
1. 「どの機種のどの不具合が発生したときにどの程度のコストが発生するのか」の算出・整理する
1. その不具合を対策する場合、どの程度コストが掛かるのか、の算出・整理する
1. 「1」「2」を踏まえ、費用対効果が最大となる選択肢はどれか、を意思決定できる状態にする


7日目の株式会社ビットキー Advent Calendar 2023 は @arasan01 が担当します！
Puppeteerでpage.waitForTimeout' is deprecated.


PuppeteerでwaitForTimeoutが非推奨(deprecated)になってました。

- Puppeteer v21.5.2
- Node.js v21.2.0

の環境です。

## "node:timers/promises"を使うように

こちらにあるように`.waitForTimeout()`は公式の`setTimeout()`を使いましょう的な感じでした。

https://stackoverflow.com/questions/77078345/how-to-fix-issue-that-deprecated-page-waitfortimeout-method-usage


```js
const setTimeout = require("node:timers/promises").setTimeout;
//import {setTimeout} from "node:timers/promises";

// ...
await setTimeout(3000);
```

とすればOKです。

## なるべく時間で待つのは使わない方がよい

Stack Over Flowであった内容はこんな感じで

> The best solution is not to use it, because arbitrary sleeps are slow and unreliable. Prefer event-driven predicates like waitForSelector, waitForFunction, waitForResponse, etc. See this post for details.
> 任意のスリープは遅く、信頼できないので、最良の解決策は、それを使わないことである。waitForSelector、waitForFunction、waitForResponseなどのようなイベント駆動述語を好む。詳細については、この投稿を参照して下さい。
> https://stackoverflow.com/questions/77078345/how-to-fix-issue-that-deprecated-page-waitfortimeout-method-usage

公式GitHubだとこんな感じ

> 一般的には、秒数を指定して待つのではなく、Frame.waitForSelector()、Frame.waitForXPath()、またはFrame.waitForFunction()を使って、欲しい条件を正確に待つことをお勧めします。
> It's generally recommended to not wait for a number of seconds, but instead use Frame.waitForSelector(), Frame.waitForXPath() or Frame.waitForFunction() to wait for exactly the conditions you want.
> https://github.com/puppeteer/puppeteer/blob/puppeteer-v21.5.2/docs/api/puppeteer.page.waitfortimeout.md#remarks


- .waitForSelector()
- .waitForXPath()
- .waitForFunction()

などを使いましょう、そもそも秒数指定はやめてねって感じでした。

確かに何秒待ったかは関係なく欲しい状態になっているかが重要ですよね。

とはいえ難しい場合もあるのでその時は`setTimeout()`使いましょう的な解釈かなと思いました。
"ホンダナ"で買った本

この記事は カオナビ Advent Calendar 2023 (シリーズ2) 6日目です。

https://qiita.com/advent-calendar/2023/kaonavi

# はじめに

カオナビでは「ホンダナ」という、月に1冊好きな本を購入できる制度が2023年5月から開始されました。
私は、ほぼ毎月1冊購入しています。
私的ルールとして「次の本を買うまでになるべく今月買った本を読むぞ！」を目標にしていました。(あくまでも目標)

年末なのでこの半年くらいで買った本をまとめておこうと思います。

# 買った本

| 月 | 本の名前 | 読書ステータス |
|:-----------:|:------------|:------------|
| 5月 | Clean Architecture 達人に学ぶソフトウェアの構造と設計 | 読んだ  |
| 6月 | ちょうぜつソフトウェア設計入門ーーPHPで理解するオブジェクト指向の活用  | 目次はみた |
| 7月 | みんなでアジャイル　変化に対応できる顧客中心組織のつくりかた        | パラパラ気になるところを読んでる         |
| 8月 | オブジェクト設計スタイルガイド        |     半分読んだ     |
| 9月 | プロダクトマネージャーのしごと 第2版        | パラパラ気になるところを読んでる  |
| 10月 | 現場で役立つシステム設計の原則　変更を楽で安全にするオブジェクト指向の実践技法 | 読んだ |
| 11月 | (11月購入なし)        |          |
| 12月 | 達人が教えるWebパフォーマンスチューニング 〜ISUCONから学ぶ高速化の実践 | まだ届いていない  |

思っていたより読んでいました。

# 本の読み方

読んでいる本の内容をA3ノートに、1冊1ページにまとめています。

始めたきっかけは弊社のエキスパート富所さん(@hanhan1978)の読書術を聞いたことです。
富所さんのブログ記事はたぶん[これ](https://blog.hanhans.net/2021/02/26/how-to-read-a-book/)です。


ちなみに私のメモはこんな感じです。（字が汚い）

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213395/ff201c42-464b-e3ea-3df7-18a85da8c851.jpeg">

まとめるときにやっていることは以下のようなことです。
- 目についた単語を書き出して関連をつける
- 青字で自分の言葉で理解した内容を書く
- （絵があったほうがわかりやすい場合は絵を描く）


# 買った本で振り返る1年の心の動き

選んだ本からその時業務に対してどのようなことを思っていたかが振り返ることができるな、と思いました。
私はこの半年以下のことを思っていたようです。

- 設計をちゃんとやるには、Clean Architecture、オブジェクト指向の学び直しが必要だ。
- アジャイルってなんのためなんだろう。
- プロダクトマネージャってどんな仕事なんだろう。
- 会社で、ISUCONサークル入ったから勉強するぞ。

一貫性がないようですが、機能開発にはさまざまな知識が必要です。
それぞれの知識を少しづつでも深めていくことで、ユーザーにとって価値ある製品を提供していきたいと思います。

来年も本を買っていこうと思います。


#

https://corp.kaonavi.jp/recruit/recruitment/
Jetpack ComposeのHorizontalPager上でLazyColumnを動かす時に、横スワイプの効き具合を調整する方法

# はじめに
この記事は[NTTテクノクロス Advent Calendar 2023](https://qiita.com/advent-calendar/2023/ntt-tx)の12日目です。

こんにちは、NTTテクノクロスの笠松と申します。 普段はAndroid/iOSアプリの開発に携わっています。

[`Jetpack Compose`](https://developer.android.com/jetpack/compose)はAndroidのネイティブUIを構築するための最新のツールキットです。2021年7月28日にこのツールキットが安定版リリースとなっており、使用しているチームも多いのではないでしょうか。

この記事ではこの`Jetpack Compose`に関するTipsを紹介します。とてもニッチなケースですが、ご覧ください。

# 本記事で紹介するTips

本記事では以下のように縦スワイプと横スワイプが混在するケースを考えます。

+ `HorizontalPager`により横スワイプで画面を切り替えることができる
+ `LazyColumn`により縦スワイプでアイテムの一覧を見ることができる

![capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629559/2b168e2e-2e99-d048-b348-55bef31b7999.png)

この時に、縦スワイプが優先されて、横スワイプによるページ切り替えがスムーズにできない時があります。この記事では縦スワイプと横スワイプの効き具合を調整して、両スワイプの体験を改善する方法を紹介します。

# touchSlopについて

`Jetpack Compose`ではどれくらいスワイプしたらスクロールとみなすかを示す`touchSlop`という値が用意されています。

`Jetpack Compose`

```kotlin
package androidx.compose.ui.platform

class AndroidViewConfiguration(
    private val viewConfiguration: android.view.ViewConfiguration
) : ViewConfiguration {
    //...
    override val touchSlop: Float
        get() = viewConfiguration.scaledTouchSlop.toFloat()
}
```

今回は`LazyColumn`の`touchSlop`を調整して、縦スクロールの効き具合を調整します。

# Jetpack ComposeにおけるtouchSlopの指定方法

この記事では`touchSlop`を`CompositionLocal`を使って指定します。
`CompositionLocal`はComposeのUIツリーの特定のノードで値を設定し、その値を暗黙的に子孫のノードでも使用できるようにする仕組みです。

具体的には以下のソースコードのように`CompositionLocalProvider`を使用して、`LocalViewConfiguration`に`CustomViewConfiguration`を指定します。

```kotlin
CompositionLocalProvider(
    LocalViewConfiguration provides CustomViewConfiguration(
        viewConfiguration = AndroidViewConfiguration(
            android.view.ViewConfiguration.get(LocalContext.current),
        ),
        touchSlopRatio = 2.5f,
    )
) {
    LazyColumn(
        modifier = Modifier.fillMaxSize()
    ) {
        items(200) {
            //コンテンツ
        }
    }
}
```

`CustomViewConfiguration`は基本的にはデフォルトの動作と同様に`AndroidViewConfiguration`を使用し、`touchSlop`のみ`override`します。

```kotlin
data class CustomViewConfiguration(
    private val viewConfiguration: ViewConfiguration,
    private val touchSlopRatio: Float,
) : ViewConfiguration by viewConfiguration {
    override val touchSlop: Float = viewConfiguration.touchSlop * touchSlopRatio
}
```

`touchSlop`に大きい値を指定すると、縦スワイプと判定されるまでのスワイプの量が大きくなるため、HorizontalPagerの横スワイプが優先されるようになります。

# 終わりに

この記事で紹介した`touchSlop`による調整は`HorizontalPager`の代わりに`Android View`の`ViewPager2`を使用している場合でも機能します。また、純粋にスワイプの感度の調整としても有効です。

前述の通り、`CompositionLocal`の設定はComposeのUIツリーの子孫のノードでも有効になる点に注意してください。

シリーズ1の13日目は[@tana0610さん](https://qiita.com/tana0610)が「UnrealEngine」について書いてくださいます。

明日もぜひご覧ください:-)
Pythonで「オブジェクトが同一かどうかの比較する(== 演算子と is 演算子の違い)」の動作を確認してみた

# 概要

Pythonで「オブジェクトが同一かどうかの比較する(== 演算子と is 演算子の違い)」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/python/if/index5.html

# 実装

以下のファイルを作成しました。
```sample.py
list1 = [1, 2, 3]
list2 = [1, 2, 3]
print(list1 == list2)
print(list1 is list2)

list1 = [1, 2, 3]
list2 = list1
print(list1 == list2)
print(list1 is list2)

str1 = "Apple"
str2 = "Apple"
print(str1 == str2)
print(str1 is str2)

list1 = [1, 2, 3]
list2 = [1, 2, 3]
print(id(list1))
print(id(list2))

list1 = [1, 2, 3]
list2 = list1
print(id(list1))
print(id(list2))

num1 = 10
num2 = 10
print(id(num1))
print(id(num2))
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
True
False
True
True
True
True
140512374329088
140512374251008
140512372795648
140512372795648
140512375439888
140512375439888
```

# まとめ

何かの役に立てばと。
Python と Pillow を利用した正多角形の描画

# Python と Pillow を利用した正多角形の描画

## 開発環境

- Visual Studio Code (Version: 1.84.2)
- Python 3.12.0
- Pillow 10.1.0

## コード

```python
import math
from PIL import Image, ImageDraw

# 定数
VERTEX_COUNT = 5  # 頂点の数
LINE_WIDTH = 1  # 辺の太さ
RADIUS = 96  # 外接円の半径(各頂点の中心からの距離)
IMAGE_WIDTH = 256  # 画像の横幅
IMAGE_HEIGHT = 256  # 画像の縦幅

# 色
COLOR_BLACK = (0, 0, 0)
COLOR_WHITE = (255, 255, 255)
COLOR_YELLOW = (255, 255, 0)

# 色の指定
BACKGROUND_COLOR = COLOR_WHITE  # 背景の色
EDGE_COLOR = COLOR_BLACK  # 辺の色
FILL_COLOR = COLOR_YELLOW  # 内部の領域の色

img = Image.new(mode="RGB", size=(IMAGE_WIDTH, IMAGE_HEIGHT), color=BACKGROUND_COLOR)
draw = ImageDraw.Draw(img)
origin_offset_x = IMAGE_WIDTH // 2  # 中心のX座標
origin_offset_y = IMAGE_HEIGHT // 2  # 中心のY座標

delta = 2.0 * math.pi / VERTEX_COUNT
vertices = []
for i in range(VERTEX_COUNT):
    vertices.append(
        (
            int(origin_offset_x + RADIUS * math.cos(delta * i)),
            int(origin_offset_y + RADIUS * math.sin(delta * i)),
        )
    )

draw.polygon(vertices, outline=EDGE_COLOR, fill=FILL_COLOR)
img.save("output.png")
```

## 出力された画像
- VERTEX_COUNT = 5の場合

![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611466/555e193b-2a0d-f5d9-1421-27fdea1b4ad7.png)

- VERTEX_COUNT = 12の場合

![output (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611466/5a6a46eb-ab69-cba1-760a-7f14d734cc01.png)


## 参考資料

- [Pillow (PIL Fork) 10.1.0 documentation](https://pillow.readthedocs.io/en/stable/)
- [Python 3.12.0 documentation](https://docs.python.org/3/)
- [Python, Pillow で円や四角、直線などの図形を描画(note.nkmk.me)](https://note.nkmk.me/python-pillow-imagedraw/)
screenWidthDpをpxに変換すると正確な値が取れません。

## 結論
画面幅をpxの単位で欲しいときは、Configuration.screenWidthDpをpxに変換すると正確な値が取れません。
BoxWithConstraintsScope.maxWidthにtoPxをかけたもの、またはResources.getSystem().displayMetrics.widthを使いましょう。

## 前提知識
dp、px、dpiの知識がある方がより理解しやすいので、以下の記事などをみてみるといいかもしれません。
https://qiita.com/nein37/items/0a92556a80c6c14503b2

## screenWidthDpについて
dp単位で表示可能な画面領域の幅のことです。(WindowInsetを除いた値)
取得方法は以下の二つです。

Resources.getSystem().configuration.screenWidthDp
LocalConfiguration.current.screenWidthDp

## 何が落とし穴？
screenWidhDpはFloatではなく、Intで保存されている点に気を付ける必要があります。
(BoxWithConstraintsScope.maxWidthはFloat)

Intなので、不動小数点のない数値である必要があります。ここでDPを求める式をみてみると、画面幅(px) * 160 /  dpiになっていますが、割り切れなさそうですよね、、？？

実際、Pixel6では
横幅 → 1080px  
dpi →  420 

で、先ほどの計算式に当てはめてみると
1080 * 160 / 420 = 411.4285

となり、割り切れておらず、小数点以下にも数字が漏れていることがわかります。
ですがScreenWidthDpはIntのため、端数が切り落とされ411で保存されてしまいます。


## screenWidthDpをもとにpxを作ると？
では実際にscreenWidthDpをもとにpxを作ってみましょう。
取得元によって、方法は分かれます。LocalConfigurationから取得している場合は、Composableのスコープの中なのでtoPX()が使えるので、以下のようにすると取得できます。
LocalConfiguration.current.screenWidthDp.dp.toPx()

Resourcesから取得している場合は、公式Documentに掲載されている公式を変形させて以下のように計算すると取得できます。
Resources.getSystem().configuration.screenWidthDp　
*
resources.displayMetrics.densityDpi / 160


結果は1078.875となり、本来の1080とずれてしまっていることがわかります。
1/1000 px程度の微量な差分ではあり、ユーザーに対して大きな影響を与えるものではありませんが、正確な方法ではないことは確かです。

## 改めて
px単位で正確な画面横幅を知りたいときは、
Resources.getSystem().displayMetrics.widthPixels
BoxWithConstraintsScope.maxWidthをpxに変換
を使うと良さそうです。
OCI（Oracle Cloud Infrastructure）のコンソール画面の見方

# はじめに
OCIのコンソール画面が分かりにくい！使いたいリソースがどこにあるか分からない！画面の見方が分からない！・・・特にOCIを初めて操作する時にはよくありますよね。
今回はOCIを始めたばかりの方に、***リソースの詳細ではなく、どこに何があるのか***に焦点を当てて説明をします。
この記事のイメージとしては***ショッピングモールの館内地図***を想像してください。


:::note warn
2023年12月時点のコンソール画面です。最新の画面は変わっている可能性があります。
:::

# 目次

[1.ホーム画面の見方](#ホーム画面の見方)
[2.リソースの詳細画面の見方](#リソースの詳細画面の見方)
[3.終わりに](#終わりに)

# ホーム画面の見方
まずはログイン後のホーム画面を見てください。これが基本画面です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1899411/5447c643-be9d-ea4d-f295-0001dd66a199.png)

・・・初心者の方はどこを見ればいいのかここで迷われると思います。
まずは以下の2つの箇所に着目してください。この2つの箇所はどこの画面に行っても表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1899411/1a957855-5daf-ef69-81b3-172259b47637.png)





### ①ナビゲーション・バー
ナビゲーション・バーは上部にある黒っぽい帯です。よく使う項目をまとめました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1899411/7849857a-c2c3-9f07-233b-625fe3886c4f.png)




### ②ナビゲーション・メニュー
まずはナビゲーションメニューを開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1899411/650707d5-2b37-e5a4-cd8e-b9ab4bd02b99.png)

ナビゲーション・メニューではほとんどのリソースにアクセスできます。ここでは3つの箇所に着目してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1899411/beb90535-ddf6-784d-f6ee-16d3628b497d.png)


大項目、中項目、小項目となって配置されています。
<br>

リソースの関係性を整理するために、皆さんに思い浮かべて欲しい頭の中のイメージは以下になります。例えばコンピュートの場合は、、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1899411/55cf86c2-2cfa-1e8a-08fc-16e7842aeb25.png)

このようにまずは包含関係を意識しながらイメージしていきましょう。

# リソースの詳細画面の見方
次にリソースの詳細画面をみます。***詳細画面はほとんど同じような配置になっている***ので、例としてインスタンスを見ていきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1899411/2b81d975-ad6e-8bdf-1131-2f270c848195.png)


ここで情報を整理して案内図にすると以下になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1899411/7f386e84-89a7-9f5a-1392-60833317f6f1.png)


- #### ①パンくずリスト
現在位置を視覚化したもの。自分がどこにいるのかが分かります。
- #### ②ステータス
リソースの状態を色で表しています。緑・黄色・赤・灰色などあります。
- ### ③リソースの詳細
リソースの詳細情報を確認したり、リソースの操作を行えます。
- ### ④リソースに関連するサブリソース
リソースに紐づくサブリソースの一覧が表示されます。
例：インスタンスに紐づくVNIC
- ### ⑤サブリソースの詳細
サブリソースについてさらに詳細情報を見ることができます。


<br><br>

サブリソースというものが出てきたので、先ほどの大項目、中項目、小項目のイメージ図にサブリソースを付け加えて全体のイメージを図に表すと以下になります。




![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1899411/9c737bfd-564d-f2a1-20a2-a0766e18fb1c.png)

リソースの全てが綺麗に四階層になっているわけではありませんが、このようにリソースの包含関係や関係性を意識しながらクラウドのリソースを見ていくと整理ができると思います。

# 終わりに
初めてクラウドに触る方はどこに何があるのか迷子になる方というのが多いと思います。
リソースの包含関係を意識していくとどこに何があるのかを早くキャッチアップすることができると思います。
今回の記事が初めてOCIを触る方々のお役に立てれば幸いです。


## 参考情報
OCIチュートリアル その1 - OCIコンソールにアクセスして基本を理解する
https://oracle-japan.github.io/ocitutorials/beginners/getting-started/