OmniAICreator/Qiita-1.07M huggingface dataset:
PlaywrightでJSのコンパイルエラーや実行時エラーを見つける

JSの実行時エラーとかコンパイルエラーの検出をやってみた。

ちなみにconsole.logとかを検出するのはconsoleイベント`page.on('console', (msg) => {})` でできるけど、補足されていない実行時例外なんかはconsoleイベントでは取得できなかった。

こんな感じのHTMLを用意する。

JSには以下の問題点がある。
- constの変数に再代入している
- ボタンを押したらErrorを投げている

```html
<html>
<body>
<p>JSにエラーがあるのでそれを検出します<p>
<script>
    const message = "this is a pen.";
    message = "that is a cholk."
</script>
<button id="raise">例外が起きるよ</button>
<script>
    const el = document.getElementById("raise");
    el.addEventListener('click', () => {
        throw new Error('raise itself.');
    });
</script>
</body>
</html>
```

Playwrightのテスト側のポイントは2つ

- CDPSessionを使う
- `Runtime.enable`を呼び出して、Runtimeドメイン機能を使えるようにする
- `Runtime.exceptionThrown`を指定して、例外イベントを受け取るようにする

参考 : https://chromedevtools.github.io/devtools-protocol/tot/Runtime/#event-exceptionThrown

```ts
import { test, expect } from '@playwright/test';
test('JSのエラーを検出する',async ({page}) => {
  const messages: Array<string> = [];

  const client = await page.context().newCDPSession(page);
  await client.send('Runtime.enable');

  client.on('Runtime.exceptionThrown', payload => {
    messages.push(payload.exceptionDetails.exception?.description || "no description");
  });
  
  await page.goto('/invalid_js.html', { waitUntil: "load"});
  await page.waitForTimeout(2000);

  expect.soft(messages.length).toEqual(1);
  expect.soft(messages[0]).toMatch(/Assignment to constant variable/);

  await page.click('#raise');

  expect.soft(messages.length).toEqual(2);
  expect.soft(messages[1]).toMatch(/itself/);

});
```


const変数への再代入のときのpayloadは以下のようになっている。

```json
{
  "timestamp": 1685954423868.76,
  "exceptionDetails": {
    "exceptionId": 1,
    "text": "Uncaught",
    "lineNumber": 41,
    "columnNumber": 12,
    "scriptId": "4",
    "url": "http://127.0.0.1:4000/invalid_js.html",
    "stackTrace": {
      "callFrames": [
        {
          "functionName": "",
          "scriptId": "4",
          "url": "http://127.0.0.1:4000/invalid_js.html",
          "lineNumber": 41,
          "columnNumber": 12
        }
      ]
    },
    "exception": {
      "type": "object",
      "subtype": "error",
      "className": "TypeError",
      "description": "TypeError: Assignment to constant variable.\n    at http://127.0.0.1:4000/invalid_js.html:42:13",
      "objectId": "3140245142211784158.3.1",
      "preview": {
        "type": "object",
        "subtype": "error",
        "description": "TypeError: Assignment to constant variable.\n    at http://127.0.0.1:4000/invalid_js.html:42:13",
        "overflow": false,
        "properties": [
          {
            "name": "stack",
            "type": "string",
            "value": "TypeError: Assignment to constant variable.\n    at http://127.0.0.1:4000/invalid_js.html:42:13"
          },
          {
            "name": "message",
            "type": "string",
            "value": "Assignment to constant variable."
          }
        ]
      }
    },
    "executionContextId": 3
  }
}
```

## 今後の野望

https://github.com/microsoft/playwright/discussions/11690 とかを参考にうまくFixturesにまとめるとページで一通り操作を行ったときにエラーが出てないことを確認できそう。
AWS ソリューションアーキテクト-アソシエイトを受験した話



<h1>はじめに</h1>

今月の6月4日にAWSソリューションアーキテクトアソシエイト(SAA)を受けて合格できたので、その記録となります
これから受けようかと思っている方に参考になればと思います。

<h1>試験について</h1>

<h2>■ソリューションアーキテクトアソシエイトとは？</h2>
Amazon.comが提供しているクラウドコンピューティングサービAWS Solutions Architect -Associateと呼ばれているAWSの中級レベルの資格とされている

<h2>■合格条件</h２>

試験時間　130時間
設問:65問
出題方式:択一選択問題と複数選択問題

合格スコア:720以上

<h2>■試験内容</h２>

第1分野: セキュアなアーキテクチャ設計　３０％
第２分野: 弾力性に優れたアーキテクチャの設計　26％
第３分野: 高性能アーキテクチャの設計　２４％
第４分野: コストを最適化したアーキテクチャの設計　２０％

<h2>■試験申し込み方法</h２>

https://aws.amazon.com/jp/certification/certification-prep/testing/


<h1>やったこと</h1>

<h2>■　参考書</h２>

aws認定資格 ソリューションアーキテクト-アソシエイトの試験対策から学ぶ 超クラウド入門書
kindle unlimitedで無料で読めるこちらを使用しました。
自分は、この本を一周だけ読みました。

<h2>■　Udemy</h２>

【SAA-C03版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）
https://aws.amazon.com/jp/certification/certification-prep/testing/


模擬試験は6回分試験があったのですが、4回目までやりました。
残り２つは難易度高いものだったので試験に出ないだろうと、スルーしちゃいました、、

上記の模擬試験を３週ほどして、試験日の前日は模擬試験の２番目のやつの解答内容を見返してました。

<h1>試験の感想</h1>

<h2>■　テストセンター</h２>

まず、試験会場（Pearson VUE）のテストセンターへ３０分前に着いて、ギリギリまでUdemyの模擬試験の答えと解説を見てました

<h2>■　試験内容</h２>

模擬試験に出てた内容より少し難しかった印象でした。
自信のない問題は、後で見直すを設定して、どんどん解いていきました。
時間配分としては４０分ぐらいで全問解答終わって、２０分見直し設定した問題を再度解いてました

時間は大分余ってしまい、もう解答に揺らぐことは無いと判断し、テストを終了しました

テスト終了後、合否が出るものだと思ってたのですが、、出ず落ちたのかなと思い焦りましたが、SAAについてはすぐに画面で合否が出ないみたいだったので、メールが来るのをドキドキして待ちました。。

<h1>おわりに</h1>

受験は午前中の頭に受けて、夕方から夜の間にバッチ取得しましたってメールがきて、無事に合格できました！

勉強期間は約２っヶ月ぐらいで、途中ゼルダの新作やロックマンエクゼなどの誘惑に負けて勉強を疎かにしてしまった期間があったので、ダメかなーって自信ありませんでした。。

無事に合格できたので、また違うAWS認定チャレンジしようかと思います！
初めての構造体

# 読んで欲しい人
・同じような問題を解く未来の私
・詳しい方

# 注意
・AtCoderの[abc304_A - First Player](https://atcoder.jp/contests/abc304/tasks/abc304_a)のネタバレあり

# 方針
・年齢が最も小さい人を判定する。
・年齢が最も小さい人の添字を判定する。
・年齢が最も小さい人を起点として並び替える。
要するに・・・
・時計回りに座っている人達の中で年齢が若い人順に並び替える。

# ACしたコード
```c
#include <stdio.h>
int	main(void)
{
	int	n;

	scanf("%d",&n);
	// printf("%d\n",n);

	char s[n][11]; //名前
	int a[n];  //年齢

	// 標準入力から名前と年齢を受け取る
	for (int i = 0; i < n; i++)
	{
		scanf("%s %d",s[i],&a[i]);
		// printf("%s %d\n",s[i],a[i]);
	}
	//  a[0]番目の人とa[i]を比較したいのでa[0]を代入
	int young_age = a[0];
	// 年齢の中で一番若い人の添字も覚えておく
	int young_age_element = 0;
	for (int i = 0; i < n; i++)
	{
		// a[0]番目の人とa[i]を比較して一番年齢が若い人を探す。
		if(young_age >= a[i]){
			young_age = a[i];
			// printf("young_age = %d\n",young_age);
			young_age_element = i;
			// printf("young_age_element = %d\n", young_age_element);
		}
	}
	// printf("young_age_element = %d\n", young_age_element);
	for (int i = 0; i < n; i++)
	{
        // 余りの周期性や規則性を利用する。
        // 参考にした記事あり
		printf("%s\n", s[(young_age_element + i) % n]);
	}
	return (0);
}
```
# ACしたコード2
この問題を構造体にして解いてる人を見つけたのでまねしてみる。
```c
#include <stdio.h>

struct person {
    char name[11];
    int age;
};

int main(void) {
    int n;

    scanf("%d", &n);
    // printf("%d\n", n);

    struct person people[n]; // 配列を用意する

    for (int i = 0; i < n; i++) {
        scanf("%s", people[i].name);
        scanf("%d", &people[i].age);
        // printf("%s ", people[i].name);
        // printf("%d\n", people[i].age);
    }
    // printf("%d\n", people[0].age); // 最初の要素のageを表示

	int most_age = people[0].age; //n人の中の0番目の年齢を代入する
	int most_age_element = 0;//一番若い年齢の人の添字を代入したいから初期値0にしておく
	for (int i = 0; i < n; i++)
	{
		if(most_age >= people[i].age){ //n人の中の0番目の年齢とn人の年齢を比較して一番若い年齢を探す
			// printf("%d\n", people[i].age);
			most_age_element = i; //一番若い年齢の人の添字を探す
			// printf("most_age_element = %d\n", most_age_element);
		}
	}
	// printf("most_age_element = %d\n", most_age_element);
	for (int i = 0; i < n; i++)
	{
		printf("%s\n", people[(most_age_element + i) % n].name);
		// most_age_elementを数字に直してみる
		// printf("%s\n", people[(2 + 0) % 5].name); = 2
		// printf("%s\n", people[(2 + 1) % 5].name); = 3
		// printf("%s\n", people[(2 + 2) % 5].name); = 4
		// printf("%s\n", people[(2 + 3) % 5].name); = 0
		// printf("%s\n", people[(2 + 4) % 5].name); = 1
	}
	return 0;
}
```

# 構造体
・構造体は英語で[structure](https://ja.wikipedia.org/wiki/%E6%A7%8B%E9%80%A0%E4%BD%93)
・structure　はデータの構造を表す概念である。
・struct　は構造体を定義するためのキーワード。

# 構造体を参考にした動画
https://youtu.be/7FHiLrAfdyw

https://youtu.be/uF-RiGlVmvw

https://youtu.be/teIHuhu0xio


# 余りの周期性や規則性を参考にした記事

https://ts0818.hatenablog.com/entry/2019/05/02/175935

https://teratail.com/questions/94191

https://www.waenavi.com/entry/20201202/1606904089

https://wa3.i-3-i.info/word15338.html

https://manabitimes.jp/math/683

https://manabitimes.jp/math/1434
PAY.JP  Checkout 用の コンポーネントを今風？にしてみた

# はじめに

※ この文章はベータ版です。

「PAY.JP Checkout 用の React.js コンポーネントをつくって
みた」にある PAY.JP Checkout 用のReact コンポーネントを
今風？にしてVue.js 3.x や Svelte 5 へ移植してみました。

https://qiita.com/mori-dev@github/items/476a51eb8d76019fb647

## PAY.JP とは？

https://pay.jp

決済代行サービスの1つで、カード決済のみを扱っています。
WEB API 及び WEB APIをラップした(いくつかのプログラミング言語の)SDKを
提供しています。

## PAY.JP Checkout とは？

https://pay.jp/docs/checkout

ポップアップさせたPAY.JPの提供するページで
カード情報を入力すると、JavaScript経由で、
入力したカード情報と一意のワンタイム・トークンを
返してくれる仕組みです。

PAY.JP Checkout を利用すれば、WEBアプリで
カード情報を管理する必要はなく、カード情報と一意の
ワンタイム・トークンを管理するだけで済むので、
開発者は利用者にとってセキュアで利用しやすい決済機能
付きのアプリを開発することが可能になります。

ワンタイム・トークンは、PAY.JPの提供する WEB API or
SDK で 使用します。

(Stripe etc の他の決済代行サービスにも、同等の機能が
あります。)

# Vue.js 3.x Ver.

## TS

https://github.com/asip/nuxt-payjp-checkout-sample-app/blob/main/components/payjp_checkout.vue

## 呼出コード (Nuxt3)

https://github.com/asip/nuxt-payjp-checkout-sample-app/blob/main/pages/index.vue

## 動作サンプル (Nuxt3)

https://github.com/asip/nuxt-payjp-checkout-sample-app

# Svelte5 Ver.

## TS

https://github.com/asip/svelte-payjp-checkout-sample-app/blob/main/src/components/payjp_checkout.svelte

## 呼出コード (SvelteKit2)

https://github.com/asip/svelte-payjp-checkout-sample-app/blob/main/src/routes/%2Bpage.svelte

## 動作サンプル (SvelteKit2)

https://github.com/asip/svelte-payjp-checkout-sample-app

# React Ver.

## 関数コンポーネント

### TS

https://github.com/asip/nextjs-payjp-checkout-sample-app/blob/main/components/payjp_checkout_func_ts.tsx

### 呼出コード(Next.js)

https://github.com/asip/nextjs-payjp-checkout-sample-app/blob/main/app/func/page.tsx

### 呼出コード(Remix)

https://github.com/asip/remix-payjp-checkout-sample-app/blob/main/app/routes/func.tsx

### 呼出コード(React Router v7)

https://github.com/asip/react-router-payjp-checkout-sample-app/blob/main/app/func/payjp_checkout_func.tsx

### JS

https://github.com/asip/nextjs-payjp-checkout-sample-app/blob/main/components/payjp_checkout_func_js.js

## クラス・コンポーネント

### TS

https://github.com/asip/nextjs-payjp-checkout-sample-app/blob/main/components/payjp_checkout_class_ts.tsx

### 呼出コード(Next.js)

https://github.com/asip/nextjs-payjp-checkout-sample-app/blob/main/app/page.tsx

### 呼出コード(Remix)

https://github.com/asip/remix-payjp-checkout-sample-app/blob/main/app/routes/_index.tsx

### 呼出コード(React Router v7)

https://github.com/asip/react-router-payjp-checkout-sample-app/blob/main/app/class/payjp_checkout_class.tsx

### JS

https://github.com/asip/nextjs-payjp-checkout-sample-app/blob/main/components/payjp_checkout_class_js.js

## 動作サンプル (Next.js)

https://github.com/asip/nextjs-payjp-checkout-sample-app

## 動作サンプル (Remix)

https://github.com/asip/remix-payjp-checkout-sample-app

## 動作サンプル (React Router v7)

https://github.com/asip/react-router-payjp-checkout-sample-app

# 元記事からの変更点

* PAY.JP Checkout の変更により、window.alert まわり  
の処理が要らなくなっている、ので、コメントアウト or 削除。

* 変数名etcの変更

* DOMまわりのコードを今風？に変更

* Vue.js 版(TS)を追加

* React版に関数コンポーネントを追加

* Reactのクラス・コンポーネントのライフサイクルメソッド
まわりの変更に伴う変更

* etc

# 注意点

* TypeScript (TS)版の型まわりは適当な感じになってます。

* コンポーネントのアンマウント時の処理にある下記のコードは、
一見必要ないようにみえますが、必要なコードですので、削除しては
いけません。必要な理由は、もと記事に書かれています。

```
window.PayjpCheckout = null
```
Railsてテスト用のデータを大量に作るメモ

FactoryBotで大量のデータを
bulk insertで対応したときのメモ

bulk
```
def regiregi(foo)
  data = []
  foo.each do |uri|
    data.push(FactoryBot.build(:page, foo: foo, created_at: Time.current, updated_at: Time.current))
  end
  GeneralPage.insert_all data.map(&:attributes);0
end
```

↑は属性に必要なデータを引数でわたしているのでループでつくってるが
`;0`はログの出力をしないようにしてる小技みたいなもの

`build_list`でも大体同じ

```
def regiregi(foo)
  data =FactoryBot.build_list(:page, foo.count, created_at: Time.current, updated_at: Time.current)
  GeneralPage.insert_all data.map(&:attributes)
end
```
【Paiza問題集】条件分岐/積の最小化

# Paiza問題集
Pythonで回答

## 条件分岐/積の最小化

### Step01 けた数の測定
```Python
"""
けた数の測定
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__complex_step1

問題
整数Nが与えられます
Nのけた数を出力してください
"""

print(len(str(input())))
```

### Step02 足したり引いたり
```Python
"""
足したり引いたり
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__complex_step2

問題
整数N,A,B(-99≦N,A,B≦100)があります
以下の2つの操作をそれぞれ1回ずつおこなったとき、Nを0にできる場合はYESを、できない場合はNOを出力してください
1.NにAを足す、またはNからAを引く
2.NにBを足す、またはNからBを引く
"""

N, A, B = map(int, input().split())

if N + A + B == 0:
    print("YES")
elif N + A - B == 0:
    print("YES")
elif N - A + B == 0:
    print("YES")
elif N - A - B == 0:
    print("YES")
else:
    print("NO")
```

### Step03 同値判定
```Python
"""
同値判定
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__complex_step3

問題
整数N,2つの数列A,Bが与えられます
1≦i≦Nを満たす整数iのうち、A_iとB_iが等しくなるようなiの個数を求めてください
"""

N = int(input())
A = input().split()
B = input().split()
count = 0

for i in range(N):
    if A[i] == B[i]:
        count += 1

print(count)
```

### Step04 終了判定 
```Python
"""
終了判定 
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__complex_step4
"""

N = int(input())
A = list(map(int, input().split()))
total = 0

for i in range(N):
    if A[i] % 2 != 0:
        break
    total += A[i]

print(total)
```

### Step05 終了判定2
```Python
"""
終了判定2
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__complex_step5

問題
2以上の整数N,Kが与えられます
「Nを2倍した数でNを更新する」という操作を何度か繰り返すことを考えます
このとき, ちょうどある回数MでNの値はK以上になります
この時点で操作の繰り返しを終了することにします
"""

N, K = map(int, input().split())
M = 0

while not N < K:
    N *= 2
    M += 1

print(M)
```

### Step06 池の周回
```Python
"""
池の周回
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__complex_step6
"""

N, K ,T = map(int, input().split())

print("YES" if K*T % N == 0 else "NO")
```

### Step07 崖に落ちるか判定
```Python
"""
崖に落ちるか判定
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__complex_step7
"""

N, K, T = map(int, (input().split()))
print("YES" if K*N<=T+0.1 else "NO")
```

### Step08 タイルの敷き詰め
```Python
"""
タイルの敷き詰め
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__complex_step8
"""

H, W = map(int, (input().split()))

print("YES" if H%2==0 and W%2==0 and (H!=0 and W!=0) else "NO")
```

### Final問題 積の最小化
```Python
"""
積の最小化
https://paiza.jp/works/mondai/conditions_branch/conditions_branch__complex_boss

問題
-1,000≦A≦B≦1,000を満たす2つの整数A,Bが与えられます
A以上B以下である2つの整数X,Yを適当に選んだとき、X*Yの取り得る値の最小値を出力してください
"""

A, B = map(int, input().split())

# AからBの間に0が含まれる
if A <= 0 and B >= 0:
    print(A * B)
# AとBが両方とも正の数
elif A > 0:
    print(A * A)
# AとBが両方とも負の数
else:
    print(B * B)
```
CompTIA Cloud+ 受験、合格までの道のり

「CompTIA Cloud+」という珍しい資格があったので受験した。日本でIT資格といえばIPA試験が有名だが、CompTIAの場合、世界で通用するというお話。そういう触れ込みだが、実際にどうだかはグローバルで活躍してる人に聞いてみたいところではあります。
ちなみにこの資格を取った人は平均年収イッセンマンですとどこか（たしかCompTIA公式）に書いてありましたが、俺はいつになったら・・・。今日から俺も、イッセンマンだ！（気持ちだけ）

# 前提条件
勉強自体は事前にしたが、前提条件としてわたしは以下のようなベース知識があった。

- 10年程度のSIer勤務経験がある
- ITインフラストラクチャーの設計構築、運用経験がある
- AWSを業務で利用する経験が3年以上ある
- AWS認定資格を取得
<br>

こんな感じの人がCompTIA Cloud+ を受験するまでに勉強した期間はだいたい1.5か月弱。
平日60分ぐらい教科書読むor教科書の問題を解く。休日は2-3時間ぐらい学習。毎週これができたとはいえないが、だいたいこんな感じのペースと勉強量。
<br>

# 学習教材
現在受験できるCompTIA Cloud+はCV0-003となり、以下の教材はCV0-002版なので少し古いバージョンとなる。だが、あまり内容に乖離はなかったように思います。

https://www.amazon.co.jp/Get-CompTIA-Cloud-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E6%99%82%E4%BB%A3%E3%81%AE%E5%BF%85%E4%BF%AE%E7%A7%91%E7%9B%AE-%E8%A9%A6%E9%A8%93%E7%95%AA%E5%8F%B7/dp/4798160385/ref=pd_lpo_sccl_2/357-5437700-7946509?pd_rd_w=RMJ6U&content-id=amzn1.sym.d769922e-188a-40cc-a180-3315f856e8d6&pf_rd_p=d769922e-188a-40cc-a180-3315f856e8d6&pf_rd_r=MN8E5BMMDP2GJQX388TJ&pd_rd_wg=MEu2Y&pd_rd_r=eabb4c54-5470-4adb-bde2-7cb996b90933&pd_rd_i=4798160385&psc=1

<br>

以上の教材は教科書なので、問題集が必要であれば以下を購入するのも手だと思います。

https://www.amazon.co.jp/Cloud-%E5%95%8F%E9%A1%8C%E9%9B%86-CV0-002%E5%AF%BE%E5%BF%9C-%E5%AE%9F%E5%8B%99%E3%81%A7%E5%BD%B9%E7%AB%8B%E3%81%A4IT%E8%B3%87%E6%A0%BCCompTIA%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-IT%E8%AC%9B%E5%BA%A7/dp/481328468X/ref=pd_bxgy_sccl_1/357-5437700-7946509?pd_rd_w=LNGM8&content-id=amzn1.sym.bc57a5ab-9f02-4944-8c5c-9e1696e0d32c&pf_rd_p=bc57a5ab-9f02-4944-8c5c-9e1696e0d32c&pf_rd_r=HCA9GHC9Q1DHVEF8RZ54&pd_rd_wg=jqaHs&pd_rd_r=83c92f3e-6c98-4663-aa3b-e8963fa6e3f4&pd_rd_i=481328468X&psc=1

<br>
わたしは問題集を買わなかったですが、合格ラインぎりぎりだったため、問題集を買って勉強すればよかったかな？とも思いました。

法的にグレーというかアウトな気がするのでリンクは書かないですが、JPN試験とかにも問題集がありました。が、どうも問題と答えが合ってない（タダなので信ぴょう性が微妙）感じがしたので、ちゃんと取り組みたければ問題集を買ったほうがいいと思います。

# 感想
クラウド＋というネーミングながら、どちらかといえばサーバの仮想化についての問題も多く、VMware製品などの仮想化を経験していないと難しい問題もある気がしました。言うほどクラウド感がない気もしますが、プライベートクラウド（仮想化）、パブリッククラウド（AWSとかAzure）をぜんぶ含めた広義の意味での「クラウド」の知見を問う、といった扱いなので、オンプレミスしか経験してない方でも解ける問題はけっこうあると思います。

また、受かるとこんな感じの電子証書がもらえます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229539/2e9c59dd-27d6-25ce-c9b9-ec67c9923f04.png)

あとは年収がイッセンマンになればいいんですが、うーん、ダメそうです。
cscの作法 その340

# 概要
cscの作法、調べてみた。
練習問題、やってみた。

# 練習問題
closedxmlでzundokoなxlsxを作れ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/569f8785-80c1-4447-08de-70a6b1851ac8.png)


# サンプルコード

```
using System;
using System.IO;
using ClosedXML.Excel;

namespace App
{
	class Program {
		static void Main(string[] args) {
			var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Book5.xlsx");
			var wb = new XLWorkbook();
			var ws = wb.Worksheets.Add("Sheet1");
			int i = 1;
			int a = 0;
			int b = 0;
			Random r = new Random();
			do
			{
				a = r.Next(2);
				if (a == 0)
				{
					b++;
					ws.Cell(i, 1).Value = "ズン";
					i++;
				}
				else
				{
					b = 0;
					ws.Cell(i, 1).Value = "ドコ";
					i++;
				}
			} while (b < 4);
			ws.Cell(i, 1).Value = "ドコ";
			i++;
			ws.Cell(i, 1).Value = "キ・ヨ・シ！！";
			wb.SaveAs(filePath);
			Console.WriteLine("ok");
		}
	}
}





```

以上。
[selenium] chromedriver バージョンエラー ( This version of ChromeDriver only supports Chrome version XXX 〜 Current browser version is XXX with binary path 〜 )

## 背景
selenium でタイムカード打刻を半自動化しているのですが、たまに下記のエラーを吐きます

```
This version of ChromeDriver only supports Chrome version 112 (Selenium::WebDriver::Error::SessionNotCreatedError) Current browser version is 114.0.5735.90 with binary path /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
```

Chrome ブラウザのバージョンが更新されてしまい chromedriver のバージョンが合わない時になるエラー

chromedriver を更新すれば良いだけですが、毎回ググるのが面倒なので記事として残しておく（完全に自分用）
※ 自動更新が推奨ですが、自分のスクリプトの都合で一旦は手動更新の手順を記します。ゆくゆくは自動更新にしたい

## 手動更新手順
### 1. 必要なバージョンの chromedriver をダウンロード
下記からダウンロード出来ます

https://chromedriver.chromium.org/downloads

今回の例でいうとエラー文にある通り `114.0.5735.90` です

![CleanShot 2023-06-05 at 17.19.51.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542581/7ed9cf8d-3cd9-46f2-12db-59767d08667b.jpeg)

ダウンロードしたら解凍して、実行ファイル( `chromedriver` )をダブルクリック
ターミナルが開き Successfully と出ていたらそのまま閉じます

### 2. `chromedriver` を適切な場所に移動
先ほどダウンロードしたものを移動します

```bash
$ mv ~/Downloads/chromedriver_mac_arm64/chromedriver /usr/local/bin/chromedriver
```

:::note info
#### 移動場所について
chromedriver は基本的に `/usr/local/bin/` にあるはず

which コマンドで確認してみましょう
```bash
$ which cromedriver
# => /usr/local/bin/chromedriver
```
:::


これでエラーがなくなるはずです


## あとがき
自分のタイムカード打刻スクリプトを修正して `webdrivers` Gem を使って自動更新にする記事を書きたい
参考予定：
https://qiita.com/jnchito/items/f9c3be449fd164176efa
AWS DVAの合格体験記



## はじめに
記事の内容はAWS Certified Developer - Associateの合格体験記です。

## 前提
私はすでに去年の7月にAWS SAAを取得したレベルです。
今年になって、ojtの一環としてAWS CDKを使いました。

## 要旨
今年の7月に [AWS Certified Developer - Associate](https://aws.amazon.com/jp/certification/certified-developer-associate/)の資格を取得しました。
この記事では資格取得までの学習方法と感想について書きたいと思います。



## 資格取得に至った経緯
Associateの試験を無料で受験できるバウチャーを持っていたことと、社内でAWSの資格取得を推進する動きもあったので、タイミングもちょうどいいと思い、受験することにしました。


## 学習方法
- 問題集
    - TechStock
- TypeScript CDKを使ってリソース構築
- [TypeScript CDK ハンズオン](https://catalog.workshops.aws/typescript-and-cdk-for-beginner/ja-JP)

また、問題で間違えた箇所については公式ドキュメントをよく読むようにしていました。

## 試験の所感
SAAの試験と同様、試験時間には結構余裕があって焦らず問題を解くことができました。



## 感想
SAAを受けた時は問題を全然解かずに挑んだので、不安でしたが、今回はハンズオンだけでなく、問題集でもしっかり対策したこともあって落ち着いて受験できたと思います。
【Windowsバッチ】テキスト出力するサブルーチンへ渡す引数にスペースが含まれる場合の処理

Windowsバッチで半角スペースが含まれる値を引数としてサブルーチンへ渡し、サブルーチン内でechoとテキスト出力を行うと、echoされる内容とテキストに出力される内容が異なる。

```bat:test_1.bat
@echo off
setlocal enabledelayedexpansion

set TestStr=test 1

call :OUTPUT_LOG1 "!TestStr!"

:OUTPUT_LOG1
echo %~1
echo %~1>> .¥output_1.txt
```

```text:コンソール出力
test 1
```

```text:output_1.txt
test
```

「 1」(半角スペース以降)はechoによる表示はされるがテキストには出力されない。
回避するには、サブルーチン内で引数を一度環境変数に代入する。

```bat:test_2.bat
@echo off
setlocal enabledelayedexpansion

set TestStr=test 2

call :OUTPUT_LOG2 "!TestStr!"

:OUTPUT_LOG2
set TmpStr=%~1
echo !TmpStr!
echo !TmpStr!>> .¥output_2.txt
```

```text:コンソール出力
test 2
```

```text:output_2.txt
test 2
```

サブルーチン内で引数の文字列置換をかけたい場合なども、一度環境変数に代入することで対応可能になる。
【Flutter】Stackの overflow が使用できない

# どういうことか

Stackからはみ出た要素が途切れないようにしたい。

https://qiita.com/ling350181/items/f5719272a516889bd3bb

ググって出てきた解決策として以下のように書いてみるが、「 `overflow` という属性はない」と出てしまう。
Stackのルールが変わったんだろうか。なんなんだろう。

```dart
return Stack(
  overflow: Overflow.visible, // そんな属性はない
  // 中略
```

## 代替案？

やりたいことはこれで実現できた。

```dart
return Stack(
  clipBehavior: Clip.none,
  // 中略
```

## 参考

https://github.com/flutter/flutter/issues/66135
TextField()と.onMove(perform:の併用時のバグについて 

## 宣伝

アプリ作っているので入れてみてください！！
よろしくお願いいたします！！

https://apps.apple.com/app/6446189340


https://apps.apple.com/jp/app/meime/id6446994707?l=ja


## 本題





以下が再現コードです。


```Swift

  List{
                ForEach(0..<10) { index in
                    TextField("Section Name",text: $text)
                }
                .onMove(perform: { indices, newOffset in
                    //                    self.data.move(fromOffsets: indices, toOffset: newOffset)
                })
            }

```

このようなコードの場合だと、テキストフィールドを押した後に焦点が当たるまで、1秒ほどラグが発生します。
cscの作法 その339

# 概要
cscの作法、調べてみた。
練習問題、やってみた。

# 練習問題
closedxmlでfizzbuzzなxlsxを作れ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/746907b9-3c43-c61d-ccaf-7973ee84be6e.png)

# サンプルコード

```
using System;
using System.IO;
using ClosedXML.Excel;

namespace App
{
	class Program {
		static void Main(string[] args) {
			var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Book4.xlsx");
			var wb = new XLWorkbook();
			var ws = wb.Worksheets.Add("Sheet1");
			int i;
			for (i = 1; i < 100; i++)
			{
				if (i % 15 == 0)
				{
					ws.Cell(i, 1).Value = "FizzBuzz";
				}
				else if (i % 5 == 0)
				{
					ws.Cell(i, 1).Value = "Buzz";
				}
				else if (i % 3 == 0)
				{
					ws.Cell(i, 1).Value = "Fizz";
				}
				else
				{
					ws.Cell(i, 1).Value = i.ToString();
				}
			}
			wb.SaveAs(filePath);
			Console.WriteLine("ok");
		}
	}
}




```

以上。
wtmp btmpの権限が変わらない時の対処法

タイトル通りです。
実施した環境はRHEL8.4です。

wtmp/btmpはLINUXでのログイン成功/失敗のログファイルです。
このファイル(/var/log/wtmp btmp)の権限はデフォルトで644ですが、権限変更後再起動をすると644に戻ります。
これは/usr/lib/tmpfiles.d/var.confで管理されていて再起動の度にこちらを参照して変更しているそうです。

__解決法としては「/etc/tmpfiles.d/」配下に同名の設定ファイルがある場合こちらを優先的に参照します。
ですので「/etc/tmpfiles.d/var.conf」を作成し中身としては下記のような内容で配置します。__
~~~/etc/tmpfiles.d/var.conf
f /var/log/wtmp 0700 root utmp -
f /var/log/btmp 0700 root utmp -
~~~
再起動後確認してみてください。
~~~
# reboot もしくは # shutdown -r now
~~~

~~~
# ls -l ディレクトリ
~~~

以上です。
cscの作法 その338

# 概要
cscの作法、調べてみた。
closedxml、やってみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/6c474c1b-b0d4-3bfc-6030-3aaaa0d17a70.png)


# サンプルコード

```

using System;
using System.IO;
using ClosedXML.Excel;

namespace App
{
	class Program {
		static void Main(string[] args) {
			var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Book3.xlsx");
			var wb = new XLWorkbook();
			var ws = wb.Worksheets.Add("Sheet1");
			ws.Cell(1, 1).Value = "Hello World!";
			wb.SaveAs(filePath);
			Console.WriteLine("ok");
		}
	}
}





```

# コンパイル手順

```
>set PATH=C:\Windows\Microsoft.NET\Framework\v4.0.30319;%PATH%


>csc excel3.cs /reference:ClosedXML.dll

```
以上。
Laravel Adminで表示される日時のフォーマットがおかしい時の対処方法

## 現象

本来は特に何も指定しなくても `2023-06-01 12:00:00` のように表示されるはずが、 `2023-06-01T12:00:00.000000Z` のように表示されてしまうことがあった。

これまでLaravel 6.x（PHP7.3）では1度も観測していなかったが、**Laravel 10（PHP8.2）** にアップグレード後、画面によって発生することがあった。

## 対処方法

before：

```php
$grid->column('created_at', __('Created at'));
```

after：

```php
$grid->column('created_at', __('Created at'))->display(function ($time) {
    return date("Y/m/d H:i:s", strtotime($time));
});
```

## 参考

* [Bug: grid date and time formatting not working · Issue \#4903 · z\-song/laravel\-admin · GitHub](https://github.com/z-song/laravel-admin/issues/4903)
* [Date format, not format actully · Issue \#5479 · z\-song/laravel\-admin · GitHub](https://github.com/z-song/laravel-admin/issues/5479)
* [How to format date in grid · Issue \#3254 · z\-song/laravel\-admin · GitHub](https://github.com/z-song/laravel-admin/issues/3254)
ゼロ幅スペースをgrepで探す

# 【見えない文字】
Unicodeで文字を書いていると、時々見えない文字が混入することがあります。よく出会うのはゼロ幅スペースです（U+200B, U+2060, その他）

U+200B は、長い英単語の中で、表示の都合で改行するならここで、という制御です。
U+2060 は逆の意味で、ここでは改行しないで、という制御ができます。

コーディングの際、これらの文字をうっかりコピペしてしまうと大抵バグになります。このバグに遭遇した際、「こんな邪悪な文字を作ったのは誰だ」と言いたくなりますが、下記のようによくまとめられた情報とセットで覚えておくと何か良いことがあるかもしれません。邪悪な文字が作られた歴史をちょっとでも知っていると、ゼロ幅スペースに悩まされたときに心が穏やかなまま対応できるのではないでしょうか。

Chienomi - UnicodeWordJoinerとウェブブラウザ: https://chienomi.org/articles/technology/202001-unicode-word-joiner.html

# ソースコードに混入したときの探し方
## grep
混入した文字がわかってるときは
```
grep -r $'\u200B'
```
のように狙い撃ちで検索、
```
grep -r -e $'\u200B' -e $'\u200C' -e $'\u200D' -e $'\uFEFF'
```
のように怪しい文字コードを手あたり次第探してみる、というのが原始的ですが効果があります。
gitbashでも動いたので、windows環境でもローカルにgitbashがあればOKです。

## エディタの正規表現検索を使う
　機能が多いエディタは検索機能で正規表現を使うことができるものも多いです。適当なUnicodeに引っかかりそうな条件で検索したとき、コメント以外のところにヒットしたらそこが怪しいです。

## IntelliJを使う
　なんとIntelliJはデフォルトでゼロ幅スペースの類を強調表示してくれるのでこういったバグに悩まされることがありません。

# まとめ
　情報をまとめたということは、ハマったということです。似たような内容のコンテンツはインターネット上にたくさん存在しており、昔からエンジニアを悩ませてきた定番コンテンツであることは承知しているのですが、IntelliJのような高機能な環境だと対策がされており、便利な世の中になったと感心してしまいました。
【Android／Java】ローカルWebサーバのHTTPSを表示

## やりたいこと
XAMPPなどで立てたローカルWebサーバのコンテンツを、WebViewでHTTPS表示させたい(白画面表示の対応）

## サンプルコード
#### Java
~~~java
WebView webView = (WebView) findViewById(R.id.webView);
String url = "https://192.168.1.1/hoge/";

/* WebView内表示 */
webView.setWebViewClient(new WebViewClient() {
	@SuppressLint("WebViewClientOnReceivedSslError")
	@Override
	public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
		/* SSLエラーを許可扱いにする */
		handler.proceed();
	}

	/* ページ読込 完了 */
	public void onPageFinished(WebView view, String url) {
		/* ～(読み込み完了時の処理)～ */
	}
});
/* Webページ読込開始 */
webView.loadUrl(url);
~~~

## 解説
1. デフォルトのWebView にセットされている WebViewClientは、onReceivedSslError() の中で処理をキャンセル（handler.cancel）しているため、白画面が表示される
1. WebViewClientを生成時、onReceivedSslError()をオーバーライドして、キャンセル処理を許可（handler.proceed）上書きする
`ポイント：本番サービスでは、この対応をしないこと！`
PHP 8.1で入った`enum`を使ってみましょう

ハイサイ！オースティンやいびーん。んな、がんじゅー やいびーみ？

# 概要

PHP 8.1で`enum`、つまり列挙型が追加されました。その使い方を紹介していきます！

# Enum・列挙型とは何か

そもそもEnumは何かというと、不変のキーと定数の対を集めたものです。キーとその値から成るオブジェクトです。

Enumの定義自体は、制約されたクラス定義に近いです。

もともとは`Java`由来の概念らしいですが、以下のような使い方をします。

```java
enum Level {
  LOW,
  MEDIUM,
  HIGH
}

Level myVar = Level.MEDIUM;
```

筆者はTypeScriptの`enum`の愛好家です。

## Enumはなぜ大切か

Enumは、特定の値しか受け付けられない時に使うと、現実的な制約を表現しやすくなります。

例えば、以下の例でいくつかの権限を文字列で表現してみましょう。

```javascript
const roles = ['ADMIN', 'SUBSCRIBER', 'EDITOR'];

if (user.role === 'ADMIN') { ... }

if (user.role === 'EDITR' { ... }

```

上記の例のように決まった権限があるのですが、毎回文字列を書いていると、必ず誤字が入りますし、この三つしか権限がないことも明確ではありません。

同じ例を列挙型で書いてみると以下のようにすっきりします。

```typescript
enum Roles {
  Admin, // 0
  Editor, // 1
  Subscriber // 2
}

if (user.role === Roles.Admin) { ... }

if (user.role === Roles.Editor) { ... }

// switch構文だとさらによし
switch (user.role) {
 case Roles.Admin:
  ...
 case Roles.Editor:
  ...
}
```

上記のように、Enumは**開発者を助けるためのツールです**。Enumを使うと誤字、例外値などが入りにくくなるので助かります。

# 簡単な例

PHPにおける`enum`はJavaとほぼ同じようです。ただ、switch構文のように`case`を追加する必要があります。

```php
enum Roles {
	case Admin;
	case Subscriber;
	case Editor;
}
```

先ほど、列挙型はキーと値が対になっていると説明しましたが、上記の例だとキーが文字列型で、値がオブジェクトです。

```php
echo Roles::admin->name; // 'Admin'

echo Roles::admin->value; // ERROR
```

デフォルトの値はJavaScriptのSymbolに何となく似ています。


# Enumの値を指定する方法

上記の例だとデフォルトでEnumの値の型がオブジェクト型になりますが、必ずしもこれがいいとは限りません。

SQLデータベースのEnum型に対してPHP側でもその制約を表現したい場合は、SQLの制約に合わせて同じようなEnumを用意したいはずです。

こういう時は、**Enumの型を指定しましょう**。

```php
enum Roles: int {
	case Admin = 1;
	case Subscriber = 2;
	case Editor = 3;
}

echo Roles::Admin->name; // 'Admin'

echo Roles::Subscriber->value; // 2
```

上記のように`:`コロンを使って値の型を指定することができます。そうすると`value`が指定したものになります。

ちなみに、`string`などでも同様に定義できます。

```php
enum Roles: string {
	case Admin = 'A';
	case Subscriber = 'S';
	case Editor = 'E';
}

echo Roles::Subscriber->value; // S
```

# まとめ

列挙型とPHPでの使い方を説明してきましたがいかがでしょうか？

PHP 8.1以上でないと使えないので、まだまだ使える環境は少ないのではないかと思います。

Enumに慣れていない読者、これが何なのかさっぱりわからん、という気持ちなら、一年前の筆者と一緒です。

Enumの概念に慣れるまで時間がかかりますが、使うべき場面というのがわかってきます。そして、使うべき場面で使うと、**コードが一段と綺麗になります**。

また、Enumを正しく使いこなしている人のコードからは、只者でない趣が感じ取れます。コードの可読性が高まりますし、コードの品質も上がります。

ぜひPHPでEnumを使っていきましょう！
Selenium実行時に出たunknown error

# 環境
Python 3.11.3
Selenium 4.9.1
Google Chrome/ChromeDriver 113.0.5672.63
# WebDriverException: Message: unknown error
手元のローカルPCでは問題なく動作するがDocker上で動かしたところ以下のエラーが出力された
```
selenium.common.exceptions.WebDriverException: Message: unknown error: Chrome failed to start: exited abnormally.
```
このエラーに続いて以下のメッセージが表示されており、どうやらChromeの起動そのものが失敗していた
>  (unknown error: DevToolsActivePort file doesn't exist)
  (The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.)

試しにChrome起動時のオプションでChromeDriverを直接指定したりしたが状況は改善されず。。
```
options.add_argument("webdriver.chrome.driver=/path/to/chromedriver")
driver = webdriver.Chrome(options=options)
```
他にも色々と試したが、以下のオプションを指定することで無事解決
```
options.add_argument("--headless")
options.add_argument("--no-sandbox")
driver = webdriver.Chrome(options=options)
```
+ --headless
    + ヘッドレスモードで起動
+ --no-sandbox
    + サンドボックスを使わずに起動

なお、Dockerイメージは[selenium/standalone-chrome](https://hub.docker.com/r/selenium/standalone-chrome)を使用していますが、Dockerfileにビルド処理を追加してあげることで上記オプションを指定することなく起動できるとは思いますが試せてません。

もしくはXvfbをインストールする。
Windows端末でCドライブ以外を非表示 & アクセス禁止にする



# 経緯
情シスがPCをキッティングするとき、Dドライブにアプリなどを配布しておいて、ユーザーに割り当てるときに個別にインストールするということがあります。共有フォルダが使えないシーンでたまに使われます。

ただしユーザーが使うときにも見えてしまうので、Cドライブ以外を非表示にしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/920dada7-b25d-7dd9-b6fa-dcebf0ff0b63.png)



:::note info
**結論**
ドライブアクセス権限と、レジストリを変更します。
:::

# ドライフのアクセス権を変更
DやEドライブを右クリックし、プロパティの「セキュリティ」タブを選びます。標準ユーザー権限の「Users」を削除します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/1cc9925f-64a4-639a-9231-b9660ecd5b9b.png)



# レジストリ変更
以下のキーを追記します。値については以下のサイトをご参考下さい。今回はD～Fドライブを非表示にしてみました。

***レジストリエディターを使って特定のドライブを非表示にする方法- Windows10***
https://www.billionwallet.com/goods/windows10/win10_drive_invisible_second.html

```.ps1
New-Item 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer'
New-ItemProperty -LiteralPath 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' -Name 'NoDrives' -PropertyType 'DWord' -Value 56
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/5e23a9e7-476e-358d-1378-874c65c99c89.png)

# レジストリ確認
値を確認します。regeditのアドレスバーに張り付けると早いです。
```
コンピューター\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer
```
値はPowerShellでも確認できます。
```.ps1
Get-ChildItem -LiteralPath 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\'
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/93eddd9a-f286-d16e-34aa-130330979898.png)

# 動作確認

再起動して、想定の挙動になっていることを確認します。

D以下のドライブが見えず、アドレスバーからアクセスしようとすると拒否されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/3a01800a-ffff-68b8-7737-f9304a17f3b7.png)


# まとめ
- ユーザーに管理者権限をもたせる場合は、レジストリ変更ができてしまうので、このポリシーはつかえません。
- ActiveDirectoryを利用している会社のおおくは標準ユーザー権限だと思いますので、今回の利用シーンとしてはAD利用で、かつ冒頭にあげたようなネットワーク制限のある企業むけといえます。


# 参考にさせていただいたサイト


**Windows 10でドライブやフォルダーを特定のユーザーアカウントのみ利用可能にする方法**
https://faq.nec-lavie.jp/qasearch/1007/app/servlet/relatedqa?QID=021668

**レジストリエディターを使って特定のドライブを非表示にする方法- Windows10**
https://www.billionwallet.com/goods/windows10/win10_drive_invisible_second.html

**PowerShellによるレジストリの操作例**
https://qiita.com/mima_ita/items/1e6c74c7fb641852edff
apollo-kotlin の compose サポートを試してみる (その1)

https://github.com/apollographql/apollo-kotlin/releases/tag/v3.8.0

apollo-kotlin 3.8.0 から experimental ですが、
Jetpack Compose で Apollo のクエリが使いやすくなる拡張サポートが入りました。

どんな使い心地か試してみようと思います。


## セットアップ

適当なサンプルの GraphQL API を探してきます。ちょうど Apollo のブログ記事にデモに使える GraphQL API の紹介があるのでみてみます:

https://www.apollographql.com/blog/community/backend/8-free-to-use-graphql-apis-for-your-projects-and-demos/

ポケモンずかんとかアニメのリストの公開 API があって面白いですね。よく使われているスターウォーズの API を使ってみます:

https://swapi-graphql.netlify.app/.netlify/functions/index

スキーマを DL しておきます:

```sh
 ./gradlew :app:downloadApolloSchema --endpoint='https://swapi-graphql.netlify.app/.netlify/functions/index' --schema=app/src/main/graphql/schema.graphqls
```

DL し終わったらテスト用にざっくりとクエリを追加しておきます:

```graphql:Test.gql
query Test {
    allFilms {
        films {
            title
        }
    }
}

```


## テストコード

ざっくりとテストのクエリを投げて、結果を表示するシンプルなものを書いてみます:

```kotlin:Apollo.kt
val apolloClient = ApolloClient.Builder()
    .serverUrl("https://swapi-graphql.netlify.app/.netlify/functions/index")
    .build()
```

```kotlin:LaunchList.kt
@OptIn(ApolloExperimental::class)
@Composable
private fun FilmList(apolloClient: ApolloClient) {
    val response by apolloClient.query(TestQuery()).toState()
    val data = response?.data
    val exception = response?.exception

    when {
        response == null -> CircularProgressIndicator()
        exception != null || response?.hasErrors() == true -> {
            Text(text = "Error!")
        }
        data != null -> {
            FilmList(films = data.allFilms?.films ?: emptyList())
        }
    }
}

@Composable
private fun FilmList(
    films: List<TestQuery.Film?>,
    modifier: Modifier = Modifier,
) {
    LazyColumn(modifier = modifier) {
        items(items = films) { film ->
            Text(text = film?.title ?: "")
        }
    }
}
```

これだけでひとまず映画のタイトルリストが出ます:

![example](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359439/93c52ff6-efdf-7df4-8101-8ccd3b9663ce.gif)

読み込み中の状態も `null` かどうかで判断できるので、
ローディングインジケーターも出ていますね。

めちゃくちゃなクエリを書いてエラーになったときはエラーハンドリングもできています:

![apollo-compose-error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359439/d8b1c99b-1058-1d61-b625-f59f2d95bff9.png)

```graphql
query Test {
    allFilms {
        films {
            title
        }
    }

    node(id: "aaaaaaa") { # Error!
        ... on Film {
            title
        }
    }
}
```

使い心地としては、ライブラリ側で State として扱えるようにしてくれているので、
composable でそのままクエリして渡していけるのは楽ですね。

とはいえ、テストはどうするとか、画面回転に生き残るようにするには、とかよくある話題があるように思えますね。
このあたりを別で調べてみようと思っています。

あとは、ページネーションを考慮できる仕組みもあるようなので、
そのあたりをどういう感じで書いていけるかというところも見てみようと思います。
Render.com上で起動していたDjangoのwebアプリで`could not translate host name "{db名}" to address: Name or service not known`というエラー

# 結論
あくまで原因の1つにはなりますが、使用していたデータベースの試用期間が過ぎたため停止された可能性があります。

# 実際に起きたエラー
Djangoで作成していたwebアプリをRender.comで起動していました。起動後、しばらくは問題なくアプリを使用できていたのですが、ある日からwebアプリのアカウントにログインするときに`could not translate host name "{db名}" to address: Name or service not known`というエラーが発生し、webアプリが使用できなくなりました。

# 調査
以下の記事を参考にしました。

https://kikuichige.com/16538/

Render.comはDBの試用期間があるようです。(現在は90日間)この試用期間を過ぎると有料プランへアップグレードしない限りDBを使用することができないようです。

# 私の場合
私の場合sqlite3を使用していたと思っていたため、試用期間を過ぎても問題ないと思っていました。
ただ、これがどうやら思い込みだったようで、実際はPostgreSQLでRender.comのDBを使用していたようです。

# 調査を踏まえての対応
1. render.yamlに記述していた「databases」のブロックを削除しました。(以下の赤い部分)
   ```diff:render.yaml
   - databases:
   -   - name: django_render_db
   -     region: singapore
   -     plan: free
   -     databaseName: django_render_db
   -     user: django_user

   services:
     - type: web
       name: django_render
       env: python
       region: singapore
       buildCommand: './build.sh'
       startCommand: 'gunicorn config.wsgi:application'
       plan: free
       branch: main
       healthCheckPath: /
       envVars:
         - key: DATABASE_URL
           fromDatabase:
             name: django_render_db
             property: connectionString
         - key: SECRET_KEY
           generateValue: true
         - key: WEB_CONCURRENCY
           value: 4
       autoDeploy: true
   ```
1. configディレクトリの中にあるsettings.pyのDATABASESの定義を下記のように修正しました。(緑の部分を追加。赤い部分を削除。)
   ```diff:settings.py
   ...
   + DATABASES = {
   +     'default': {
   +         'ENGINE': 'django.db.backends.sqlite3',
   +         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
   +     }
   + }

   - default_dburl = "sqlite:///" + str(BASE_DIR / "db.sqlite3")
   - DATABASES = {
   -     "default": config("DATABASE_URL", default=default_dburl, cast=dburl),
   - }
   ...
   ```

これにより、sqlite3でデータベースを保存できるようになり、現在のところ問題なくWebアプリを起動できています。

# 終わりに
あくまで私のケースに焦点を絞った内容になりました。エラーが発生したときの状況もyaml,settingsファイルも人それぞれです。この記事で`could not translate host name`エラーの全てのケースを解決できるわけではないですが、誰か1人でも役に立つことがあれば嬉しい限りです。

以上です。

# 参考

https://kikuichige.com/16538/
PythonとOpenCVで消しゴムマジックやってみた！

# :robot: 「消しゴムマジックで消してやるのさ」
少し前に、消しゴムマジックCMのこのセリフが流行っていました。
ちょうど私もGoogle Pixelを持っていたので実際に試してみると、本当に選択した範囲が消えるんですね～！感動です。
そんな消しゴムマジックを再現しよう！ということで、Inpaintingという技術を使用して再現をチャレンジしました。

>例：空の鳥を消してみました（消しゴムマジック使用）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457551/2c81a4d9-fdc6-6a53-525f-0f925bb8e892.png)

# Inpaintingとは？
Inpaintingとは日本語で修復するという意味で、選択された範囲の画像を修復する技術のことです。
今回は、OpenCVのINPAINTを使用して再現を行いました。
この技術にAIなどを絡ませると、より精巧な修復が可能になるようです。
OpenCVにはInpaintingの方法がNSとTELEAの２種類あり、流体力学の理論を適用した画像の補完や、加重平均・勾配を使用して修復されるごとに境界を更新する方法などが用いられています。

参考：[OpenCVで画像のInpaintingの解説](https://data-analysis-stats.jp/%e6%a9%9f%e6%a2%b0%e5%ad%a6%e7%bf%92/opencv%e3%81%a7%e7%94%bb%e5%83%8f%e3%81%aeinpainting%e3%81%ae%e8%a7%a3%e8%aa%ac/)

# 用意するもの
用意するものは２つです。
- 画像
- マスク画像

画像は[pixabay](https://pixabay.com/ja/)というフリー画像サイトからお借りしました。
マスク画像というのは、消したい部分だけ塗りつぶされた画像のことです。こちらは既存の描画ツールを駆使して作成しました。結構大変でした。。。

>左が元の画像で、右がマスク画像です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457551/9239ab5b-f017-9596-ba55-26f93a391d77.png)

# コード

```
import numpy as np
import cv2
img = cv2.imread('元の画像.png')
mask = cv2.imread('マスク画像.png',0)
np.int8(mask)
dst = cv2.inpaint(img,mask,20,cv2.INPAINT_TELEA)
# dst = cv2.inpaint(img,mask,20,cv2.INPAINT_NS)
cv2.imwrite('ファイル名.png', dst)
```
inpaintの引数説明
cv2.inpaint(image, mask, radius, method)
cv2.inpaint(元の画像, マスク画像, 画像修復の半径, NSかTELEA選択)
修復半径を変えたりNSとTELEAを両方試したりするのもいいですね。

## 結果の比較
NSのradius20と100の比較
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457551/e58513a5-7498-6fe3-a4b2-392776dfeb01.png)

TELEAのradius20と100の比較
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457551/96e96f7a-8d0b-3602-0bdc-e3059027b8a1.png)

NSとTELEAの比較（radius100）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457551/b2fde3fb-423f-1559-526f-d11cd651acd1.png)

NSよりもTELEAのほうが比較的滑らかな修復ができている印象ですね。
# 感想
OpenCVを使うと少ないコードでも簡単に画像処理ができるのでとても便利でした。また、AIを組み合わせるともっと自然に修復ができるようなのでまだまだ深堀出来そうです。皆さんもぜひInpaintingを試してみてください！　

# 参考にしたサイト
https://lp-tech.net/articles/kb4bO

https://data-analysis-stats.jp/%e6%a9%9f%e6%a2%b0%e5%ad%a6%e7%bf%92/opencv%e3%81%a7%e7%94%bb%e5%83%8f%e3%81%aeinpainting%e3%81%ae%e8%a7%a3%e8%aa%ac/
求人サイトから、全企業の詳細情報を取得してエクセルに出力

求人サイトから各企業の詳細urlを取得して、情報を取得、エクセルに出力するプログラムです。

## 結果
![スクリーンショット 2023-06-05 14.59.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331893/80ae3673-d2d9-ac9b-9a49-c657ce2d1b91.png)


## 各コード

## 全体コード

```
import requests
from bs4 import BeautifulSoup
import pandas as pd

# スクレイピング対象のURL
url = "https://job.mynavi.jp/25/pc/search/query.html?HR:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,99"


# データを保存するための空のリスト
data = []

# ページにアクセス
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')


# 各企業の詳細ページへのリンクを含む要素を取得
links = soup.select('a.js-add-examination-list-text')


#相対リンクをリンクリストに追加していく
link_list=[]
for link in links:
    link_list.append(link.get('href'))


#各詳細ページにアクセス

for link in link_list:
    response = requests.get('http://job.mynavi.jp'+link)
    soup = BeautifulSoup(response.text, 'html.parser')
      # 必要な情報を取得
    company_name = soup.select('h1')[0].text
    phone_number = soup.select('td#corpDescDtoListDescText220')[0].text
    data.append([company_name,phone_number])

# データをDataFrameに変換
df= pd.DataFrame(data, columns=['企業名', '電話番号'])

# DataFrameをExcelファイルに出力
df.to_excel('企業情報.xlsx', index=False)

```
Vite + TailwindCSSで出たWarningを解決する方法

## Laravel-mix -> vite移行作業中に以下のWarningに遭遇した

### Vite build実行

```
vite build
```

### Warning発生

```
/img/bg.jpg referenced in /my-project/resources/css/app.css didn't resolve at build time, it will remain unchanged to be resolved at runtime
```

## とりあえず日本語訳してみた

```
「/my-project/resources/css/app.css」内で参照された「/img/bg.jpg」はビルド時に解決できず、ランタイムで解決されるままになります。
```

つまり、ビルドプロセス中に、`/img/bg.jpg`という画像ファイルを見つけることができなかったことを示しています。
その結果、アプリケーション実行時に動的に画像を探しに行って解決するような挙動になります。

## 原因

背景画像指定の際に、TailwindCSSの`Arbitrary values(任意の値)`を使用していたことでした。

以下のように記述していました。

```html
<div class="bg-[url('/img/bg.jpg')]">
  <!-- ... -->
</div>
```

TailwindCSSでは、`bg-[任意の画像パス]`という風にクラス名を記述することで、任意の画像を背景画像に指定することが可能です。
background image以外にも、この書き方は適応可能なので、随時調べてみてください。

https://tailwindcss.com/docs/background-image#arbitrary-values


## 解決策

### 画像パスのエイリアスを作成し、適用する

`vite.config.js`内には、各パスのエイリアスを記述できる部分があります。
そこに、画像パスのエイリアスを新規作成してください。

```diff_javascript:vite.config.js
import { defineConfig } from 'vite';
import path from 'path';

export default defineConfig({
  // <-- 中略 -->
  resolve: {
    alias: {
      '@': path.resolve('resources/js'),
+     $image: path.resolve('public/img'),
    },
  },
});
```

そして、そのエイリアスを使って、TailwindCSSのクラスを下記のように書き換えてください。

```diff_html
- <div class="bg-[url('/img/bg.jpg')]">
+ <div class="bg-[url('$image/bg.jpg')]">
  <!-- ... -->
</div>
```

これで、再度ビルドし直すと、Warningが出ないようになっているはずです。

## 参考サイト
https://stackoverflow.com/questions/75601350/tailwind-and-vite-warnings-didnt-resolve-at-build-time-it-will-remain-unchan
拡散モデルにおける確率微分方程式の条件付き確率の導出について

# はじめに
岡野原大輔さんの著書「拡散モデル」で躓いたのでメモをします。
拡散モデルにおける確率微分方程式の条件付き確率の導出についての記事です。
確率微分方程式については素人なので間違っていればご教示お願い致します。

# 本題
確率微分方程式が与えられているとする.

```math
\begin{equation}
dx=f(t)xdt+g(t)dw
\end{equation}
```

このとき, 条件付き確率は,

```math
\begin{equation}
p(x(t)|x(0))=\mathcal{N}(s(t)x(0),s(t)^2\sigma(t)^2I)
\end{equation}
```

ただし,

```math
\begin{eqnarray}
s(t)&=&\exp\left(\int_{0}^{t}f(\xi)d\xi\right)\\
\sigma(t)&=&\sqrt{\int_{0}^{t}\dfrac{g(\xi)^2}{s(\xi)^2}d\xi}
\end{eqnarray}
```
である.

https://mathlog.info/articles/IooWy76ZFWkMXeijmEh3
Linuxのディレクトリ構造

# Linuxディレクトリ構造
Youtuberの山浦さんがLinuxのディレクトリ構造について動画をあげていました。
これを知っているとLinuxの理解が速いみたいですね。音声だと頭に入ってきやすいので
よかったら見てみてください。


https://www.youtube.com/watch?v=bzqrlef15wI

### /bin
Binary Folderの略で、```OSの最小限の正常に動くためのすべてのユーザーが使用する実行ファイル```です。コマンドを実行するための実行ファイルが入ってます。

### /boot
システム起動に必要なファイルです。

### /dev
deviceの略字で***ハードウェア機器を表すファイル***です。
キーボード、マウス、プリンターなどのデバイスをファイルまたはディレクトリの形で/devフォルダの中にあります。ディレクトリどこでもアクセスできます。

### /etc
***Linux設定のための各種ファイルを持っているディレクトリ***で、システムのほぼすべての設定ファイルがあるディレクトリです。重要なディレクトリです。

### /home
***ユーザーのhomeディレクトリ***です。

### /lib
***OSに必要な各種ライブラリファイルがあります***。

### /media
/mntはユーザーがマウントするパスとして使用される場合、/
***mediaはOSで自動的にマウント(外部の記憶媒体をマウント)してくれるポイント***として使われます。


### /tmp
臨時にデータを解読·削除した動作が必要ならばtmpに位置付けます。 
***システム使用中に発生した臨時データ等が保存します。***。
***システムを使用する全てのユーザーが共同で使用するディレクトリ***です。


### /mnt
取り外し可能な装置に対してファイルシステムを臨時に接続するディレクトリです。
***/mntはユーザーが手動でマウント***します。

#### マウントとは
***/mntや/mediaはマウントするパスの場所***です。
外部機器(USBやハードディスク)を使う時、/から始まる場所に置かないとアクセスできないです。
そのために***外部の記憶装置をディレクトリのどこかに登録する必要***があります。
その***ルートディレクトリの下に登録することをマウント***と言います。



### /opt
追加でアプリケーションパッケージがインストールされるディレクトリです。


### /proc
OSのシステムをコントロールするためのディレクトリです。

### /root
***rootアカウントのホームディレクトリ***です。

### /sbin
***ルートユーザーのみが実行できるプログラム***です。


### /sys
***OSの現在の情報が入っています***。

### /usr
***全ユーザーが共通して利用するプログラムのデータ***です。


### /var
Variableの略。 ***システム運用中に生成されて削除されるデータを保存するためのディレクトリ***です。 
生成後から削除されるデータです。



# 有益資料

https://qiita.com/nys9302/items/a8ddeedd3cd9d0deb332
Node.jsでpy実行時に文字化けしてしまう問題

## 参考URL
https://ayapi.github.io/posts/nodejsspawnpythonencoding/
## 文字化け解消のコード
```js:js
const express = require('express');
const bodyParser = require('body-parser');
const { spawn } = require('child_process');
const app = express();
const cors = require('cors');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());

app.get('/', (req, res) => {
  res.sendFile(`${__dirname}/index.html`);
});
app.post('/python', (req, res) => {
  const message = req.body.message;
  console.log(message);
  let dataToSend;
  //ファイルをコマンドで実行するのと同じ
  const python = spawn('python3', ['./main.py', message], {
    env: { PYTHONIOENCODING: 'cp65001' },//ここで文字コードの指定
  });

  python.stdout.on('data', function (data) {
    console.log('Pipe data from python script ...');
    dataToSend = data.toString();
  });
  python.stderr.on('data', (data) => {
    console.log(`stderr: ${data}`);
  });
  python.on('exit', (code) => {
    console.log(`Child exited with code ${code}, ${dataToSend}`);
    res.json({ data: dataToSend });
  });
});
app.listen(3000, () => console.log('Server started on port 3000'));
```
サーバー上で　ログをローテーションする

# logrotateとは
「logrotate」は、ログファイルをローテーションし、必要に応じて圧縮などを行うツールです。「logrotate」を使うことによって、「週次や月次でローテーションする」「ファイルサイズがある値を超えたらローテーションする」といったことができます。

# サーバー
・Linux上利用可能
・Windows server該当するツールなし

# Windows server代替案
https://beyondjapan.com/blog/2023/03/winlogrotate/




# 参考サイト
https://linuc.org/study/column/3635/
cscの作法 その337

# 概要
cscの作法、調べてみた。
練習問題、やってみた。

# 練習問題
sqliteでlistviewに流し込め。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/52defa21-87ec-2983-638f-c24c4e8ffe8d.png)


# サンプルコード

```
using System;
using System.Text;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
using System.Data.Common;
using System.Transactions;
using System.Data.SQLite;

namespace App
{
	public partial class Form1: Form {
		private Label label;
		private ListView lsv;
		public Form1() {
			Text = "listview test";
			ClientSize = new Size(310, 300);
			label = new Label();
			label.Text = "koko";
			label.Font = new Font("Geneva", 12, FontStyle.Regular);
			label.Height = 20;
			label.Width = 190;
			label.Left = 50;
			label.Top = 10;
			this.Controls.Add(label);
			lsv = new ListView();
			lsv.Location = new Point(0, 40);
			lsv.Size = new System.Drawing.Size(300, 200);
			lsv.View = View.Details;
			lsv.FullRowSelect = true;
			lsv.GridLines = true;
			lsv.Columns.Add("id", 70, HorizontalAlignment.Right);
			lsv.Columns.Add("name", 100, HorizontalAlignment.Left);
			lsv.Columns.Add("number", 50, HorizontalAlignment.Right);
			lsv.Columns.Add("price", 50, HorizontalAlignment.Right);
			lsv.CheckBoxes = true;
			//lsv.ColumnClick += lsv_ColumnClick;
			lsv.ColumnClick += new ColumnClickEventHandler(lsv_ColumnClick);
			Controls.Add(lsv);
			SQLiteConnectionStringBuilder ConnectionStr = new SQLiteConnectionStringBuilder();
			ConnectionStr.DataSource = "db0.sqlite";
			using (SQLiteConnection Connection = new SQLiteConnection(ConnectionStr.ToString()))
			{
				Connection.Open();
				using(SQLiteCommand Command = new SQLiteCommand(Connection))
				{
					Command.CommandText = "SELECT * FROM fruit ORDER BY id ASC";
					using (SQLiteDataReader Reader = Command.ExecuteReader())
					{
						while (Reader.Read())
						{
							string Id = Reader.GetInt32(0).ToString();
							string Name = Reader.GetString(1);
							string Number = Reader.GetInt32(2).ToString();
							string Price = Reader.GetInt32(3).ToString();
							lsv.Items.Add(new ListViewItem(new string[]{Id, Name, Number, Price}));
						}
					}
				}
			}
		}
		void lsv_ColumnClick(object sender, ColumnClickEventArgs e) {
			Console.WriteLine(e.Column);
			foreach (ListViewItem item in lsv.CheckedItems)
			{
				Console.WriteLine(item.SubItems[1].Text + "\r\n");
			}
		}
		[STAThread]
		public static void Main() {
			Application.Run(new Form1());
		}
	}
}





```

以上。
Webの基礎について

## Web技術の基礎用語


### ステートフル
通信のやり取りの状態を保存している状態。
そのため、ECサイトなどでカートに商品を入れて画面遷移してもカートから商品が消えずに残っている。
### ステートレス
通信のやり取りの状態を保存していない状態。
ECサイトの場合は毎回クライアントから今までにカートに入れた商品を送信しないといけない。
### リクエスト
クライアントからサーバに対して送信する通信のこと。
HTTPリクエストの場合、GETメソッドやPOSTメソッドがあり、
ブラウザのバージョン情報等を表すUser-Agent、ブラウザがデコードできるエンコーディング形式を表すAccept-Encodingなどがある。
### レスポンス
リクエストに対する返答として、サーバからクライアントに対して送信する通信のこと。
HTTPレスポンスの場合、HTMLや画像等が入るボディやWebサーバーの処理結果を表すステータスコードなどがある。
### クッキー
ステートフルを実現するためブラウザにある保存されたテキストファイルのこと。
ログイン情報やECサイトのカート情報などを保存できる。個人情報漏洩の危険性がある。
### プロトコル
通信規約のこと。Webで使用されるHTTPやTCP、メールで使用されるPOPやSMTPなどがある。
### ポート番号
IPアドレスの下にあるデータの宛先のアドレスのこと。 16ビットの整数である。
サーバがマンションだとするとポートは部屋番号のようなもの。