OmniAICreator/Qiita-1.07M huggingface dataset:
UnityでAndroidビルドを出来るようにした

# この記事について
現在制作しているゲームのプラットフォームがスマホだったので、今回はAndroid版でビルドが出来るまでの手順を記事にまとめています。

**GooglePlayにリリースするなどの部分は含まれていないのでご注意下さい**

# モジュールをダウンロードする　
UnityHubを開いて以下の順で移動します。
`インストール` → `Androidビルドをするバージョンの⚙` → `モジュールを加える`
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/4b4c2176-9289-ca90-92a7-9b8091526af0.png)
![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/59211cbc-3663-2ddd-95e8-bb37fe9ac365.png)
![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/627b7397-79c2-448d-8a9b-ebc3b81ad2ab.png)

プラットフォームの項目から`Android Build Support`のチェックボックスをクリックし、右下の`インストール`をクリックしてください。
![図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/89f959da-9113-c9aa-a8e5-4c429f56470d.png)



これでモジュールのダウンロードは完了です。
次はプロジェクトの作成を行います！

# プロジェクトの作成

テンプレートを選択してプロジェクトを作成します。
テンプレートに関しては通常の`Built-In`や`URP`でも大丈夫です。
今回は、`3D Mobile`のテンプレートを選択します。
![スクリーンショット 2024-06-17 115408.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/cf50303f-862f-49d1-f68c-42e80e5029ec.png)

モバイルのテンプレートで作成すると、最初からモバイル関連のパッケージが入っていたり、モバイル用の設定がされています。

# ビルド設定を行う
プロジェクトが開いたら以下の順で移動します。
`File` → `Build Settings`
![図5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/71d2cfab-8238-0505-2249-36b8c2274709.png)
![図6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/2c8f86d2-a8d2-78e4-fd91-b3301e292f73.png)


タブが開いたら`Platform`から`Android`をクリックし、
`Development Build`のチェックボックスをクリックします。
最後に`Switch Platform`をクリックするとロードが入ります。
![AndroidBuild_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/77f0fb26-1358-07fe-7347-cd6ce49e85de.png)

ロードが完了したら`Player Settings`をクリックします。
![図7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/0331fff8-d800-76bc-12bc-77131953e336.png)

`Player`をクリックして、`Identification`項目の中から`Minmum API Level`を探します。
![AndroidBuild_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/e4ab071b-1961-052e-5252-733ffdc9f7e2.png)

`Minimum API Level`をクリックして`Android 13.0 (API Level 33)`を選択します。
![図8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/de99683e-4ef5-e610-9e26-b7300cdddcb3.png)


上記の変更が完了したらビルドを行います。
ビルドを始めると画像の様なタブが出てくるので`Update Android SDK`をクリックします。
![図9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/6c08a70f-6359-88ee-2d08-d5ca2a236375.png)


後は選択したフォルダー上にAPKがあればビルド成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/8d7724be-c383-ab86-97ac-30869259a558.png)
これでビルド設定は終了です！

# Androidの設定
Androidはデバイスによって、設定が違う可能性があるので下のリンクを元に設定して下さい。(自分はiPhone勢です)

https://appllio.com/android-development-mode-settings

また、デバイスによってはUSBからのダウンロードが出来ない設定になっている物もあります。`設定`でUSBの設定と検索すると出てくるので、`USBの使用`をファイル転送に変更すると、ダウンロードできるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/723a1cb4-a25f-cfea-204d-abc86c6cb6c2.png)
エラトステネスの篩をGolang で実装してみた

### 2024/7/7追記
コメントでmaxに４を引数とすると4も素数となることをご指摘いただき下記のとおり修正しました。
ご指摘ありがとうございました。:bow:
```diff
- for i := 2; i < sqrtMax; i++ {
+ for i := 2; i <= sqrtMax; i++ {
```
# サマリー
素数をどうやって算出すればいいか悩んだことはありませんか？
~~私はありません。~~

今回は素数を簡単に導出できるアルゴリズムを紹介します。
このアルゴリズムは紙とペンしかない状態でも実行できるので、テストで素数を出さないといけない時が来たときに役立つことでしょう。

今回紹介するアルゴリズムは考案者の名前からエラトステネスの篩(ふるい)(_Sieve of Eratosthenes_)と呼ばれているアルゴリズムです。
古代ギリシアの科学者であるエラトステネスが考案しました。

今回作成したコード以下で公開しています。
https://github.com/y-miyakaw/sieve_of_Eratosthenes

# 素数とは
素数(英: _prime_ または _prime number_)というのは、2以上の自然数かつ正の約数が1と自身のみのもののことです。
例えば5の約数は1と5のみなので素数です。

素数にどんな数字があるかを考えたときに、2, 3, 5, 7, 11, 13あたりまではすんなりと出てくるのですが、100以上とかになるとこれって素数なのか？と時間がかかるようになります。

そんなときに役立つアルゴリズムがエラトステネスの篩です。

# エラトステネスの篩の概要
こちらのアルゴリズムを簡単に説明すると、
1. 2から求めたい値までの数値テーブル(今回はslice []bool)を作成し、２以上の値をtrueにする
1. このスライスを先頭から走査する
1. まず2は素数なのでtrueとする
1. 2の倍数は素数ではないので、2の倍数をfalseにする（2を約数に持つため）
1. 続いて3の倍数は素数ではないので、3の倍数をfalseにする
1. この時、6は2の倍数でfalseとなっているので考慮外として良いため、3^2=9以上の3の倍数をfalseとする
1. 続いて5の倍数は素数ではないので、5の倍数をfalseにする
1. この時、10, 15, 20は2の倍数と3の倍数でfalseとなっているので考慮外として良いため、５^2=25以上の5の倍数をfalseとする

上記の走査を継続すると素数のキーのみがtrueで残るので、trueのキーのスライスを作成することで求めたいあたいまでの素数の一覧を作成することができる。

公開したリポジトリと同じものになるが、コードは以下のとおり
```go
package main

import (
	"fmt"
	"math"
)

func main() {
	primes := Sieve(1000)
	fmt.Println(primes)
}

func Sieve(max int) []int {
	if max < 2 {
		return []int{}
	}

	// 走査するスライスを作成
	// Create a slice to track prime candidates
	isPrime := make([]bool, max+1)
	for i := 2; i <= max; i++ {
		isPrime[i] = true
	}

	// maxの平方根を算出
	// Calculate the square root of max
	sqrtMax := int(math.Sqrt(float64(max)))

	// エラトステネスの篩の走査を実行
	// Perform the Sieve of Eratosthenes
	for i := 2; i <= sqrtMax; i++ {
		if isPrime[i] {
			for j := i * i; j <= max; j += i {
				isPrime[j] = false
			}
		}
	}

	// エラトステネスの篩の走査によってtrueとなった数字を素数のスライスに格納
	// Store numbers that remain true after sieving in the primes slice
	primes := make([]int, 0, max/10)
	for i := 2; i <= max; i++ {
		if isPrime[i] {
			primes = append(primes, i)
		}
	}
	return primes
}
```

# まとめ
素数を簡単に導き出すことができるアルゴリズムをgolangで実装してみました。

求めたい値の平方根の値まで走査することで素数がわかる(<u>10000までの素数も100まで走査すればわかる！</u>)ので、紙とペンしかない時でも、比較的簡単に素数を導出できるアルゴリズムになります。

# 参考
https://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%A9%E3%83%88%E3%82%B9%E3%83%86%E3%83%8D%E3%82%B9%E3%81%AE%E7%AF%A9
【Datadog】Datadog 認定試験受けるぞ

今日タイムラインを眺めていて、

https://qiita.com/kccs_naoto-izutsu/items/0fc5ee82477a77953eaf

Datadog の認定試験があること自体は知っていたけど、日本語対応したということで、
確かに取っ付き易くはなりましたね〜、と言うことで、久々に試験勉強してみるかと思いたちました。（2024/07/06）

なので、私はまだ受験をしておりませんので、これは体験記というより、これから受験を目指す上で準備としてやり始めたこと、調べたことなどを記します。

## やると決めたからには勉強開始

今回は日本語化されたということで Datadog の基礎 (Datadog Fundamentals)を受験したいと思っています。

ちなみに、日頃業務で Datadog を使う機会はそこそこある（1年くらい触ってる）ので、
APM とかモニターとかダッシュボードなぞの触り方はある程度分かっておるが、雰囲気でやっていて腰を据えて勉強したことはなかったというレベル感。

まずは試験ガイドの事前学習と準備に記載されている 「Datadog 学習センター」のいくつかのコースを消化することにしました。

https://www.datadoghq.com/ja/certification/overview/

↓ ドキュメントと動画の構成になっています。5分くらいずつの動画で、observability 入門な内容が1時間くらいあるかも。日本語字幕の設定が可能ですが、精度はイマイチです。

https://learn.datadoghq.com/courses/introduction-to-observability

↓101シリーズはハンズオンで、検証用環境が用意されたアカウントを使って、実際に Datadog へログインし、画面操作をしながら学ぶことが出来ます。ここは英語オンリーだったので、都度翻訳しながら進めて、1時間ずつくらいかかったかも。

https://learn.datadoghq.com/courses/dd-101-sre

https://learn.datadoghq.com/courses/dd-101-dev

↓公式ではありませんが、ちょうどセールしていた Udemy で評価が高めだった問題集も購入し、1周解いて、正答率65%くらい。これは100%解けるようにしとこうかなと思います。

https://www.udemy.com/course/datadog-fundamentals-practice-exam

### 以下、まだ手をつけてないけど、これからやるつもり

- 試験範囲になっている公式ドキュメントの読み込み
  - Datadog Agent
  - メトリクス
  - インフラストラクチャー一覧
  - API およびアプリケーションキー
  - インテグレーション
  - Docker Daemon
  - グラフへのクエリ
  - Docker Agent
  - メトリクス API
  - モニターの種類
  - DogStatsD
  - ddtrace
- 公式の模擬試験問題（26問）

### 試験はいつ受験するか
ドキュメント1周と、練習問題満点取れるようになったくらいでもういいかな。
来週とかでもいけそうだけど、余裕もって2週間後くらいにしようかと考えている。


## テストセンターでも受験出来るらしい
AWS とか他の資格試験も今は自宅でも受験が出来るもんだとは思うんですが、
環境整えたり、手続きもめんどそうというのがあり、今回もテストセンターで受験する気でいます。

調べたところ、都内で受験出来るのは以下3つのテストセンターのみでした。
（日々変わるかもしれないので、ご自身で受験を検討される際は事前にちゃんと調べてみてね）

- 東京 - 高田馬場テストセンター
- 東京 - 市ヶ谷テストセンター
- 東京 - 秋葉原昭和通り口テストセンター
[Xcode] ターミナルからXcodeプロジェクトを開く

次のコマンドで`Xcode`プロジェクトを開きます。

```terminal
$ xed path/to/you/project.xcodeproj
```

ワークスペースの場合は、`.xcworkspace`を指定します。

```terminal
$ xed path/to/you/project.xcworkspace
```

参考；

https://qiita.com/SNQ-2001/items/fdf1ff36fd1aabef31c6
LLVM IRの勉強メモ #5

LLVM IRの仕様のうち、Aliases, IFuncs, Comdatsについて見てみます。

### Aliases
エイリアス(alias)は、既存のデータに対する新しいシンボルやメタデータを定義する。（関数や変数とは異なり、新しいデータを作成することはない）
エイリアスは、その名前と、グローバル値や定数式であるエイリアシー(aliasee, エイリアスのターゲット)を持っている。

```txt: エイリアスの構文
@<Name> = [Linkage] [PreemptionSpecifier] [Visibility] [DLLStorageClass] [ThreadLocal] [(unnamed_addr|local_unnamed_addr)] alias <AliaseeTy>, <AliaseeTy>* @<Aliasee>
          [, partition "name"]
```

リンケージは`private`, `internal`, `linkonce`, `weak`, `linkonce_odr`, `weak_odr`, `external`, `available_externally`のいずれかである。`unnamed_addr`でないエイリアスはエイリアシーと同じアドレスを持つことが保証される。一方で、`unnamed_addr`のものは、同じ内容を指すことだけが保証されている。
また、`local_unnamed_addr`が与えられている場合は、そのアドレスはモジュールの中で重要でなく、内容だけが重要であることを示す。[参考: 学習メモ#3](https://qiita.com/joule/items/2a8de0fd10379e0bbf6f)

エイリアスはセカンドネームに過ぎないため、いくつかの制限がある。

- エイリアスを定義する式は、アセンブリで計算可能でなければならない
- 中間のエイリアスがオーバーライドされる可能性は、オブジェクトファイルでは表現できないので、式中のエイリアスは弱いものであってはならない
- エイリアスが`available_externally`を持つ場合、エイリアスは`available_externally`のグローバル値でなければならない。そうでない場合はエイリアシーを式にすることは可能だが、式の中でグローバル値を宣言することはできない
- リンク時または実行時に、エイリアスまたはエイリアシーがモジュール外のシンボルに置き換えられている可能性がある場合、動作が異なる可能性があるため、最適化でエイリアスをエイリアシーに置き換えることはできない

### IFunc
IFuncとはIndirect Functionのことで、エイリアスと同様、新しいデータを作成しない。単なる新しいシンボルであり、実行時にリゾルバ関数を呼び出して解決される。

```txt:IFuncの構文
@<Name> = [Linkage] [PreemptionSpecifier] [Visibility] ifunc <IFuncTy>, <ResolverTy>* @<Resolver>
          [, partition "name"]
```
:::note info
一般的なELF(Executable and Linkable Format)では、IFuncはロード時にダイナミックリンカーによって解決される。
:::


### Comdats
Comdatsは、複数のオブジェクトファイルに重複したセクションを定義できることを表すデータである。通常は同じシンボルが複数のオブジェクトファイルに定義されている場合、リンカーはエラー報告するが、LLVMでは、`Any`, `ExactMatch`, `Largest`, `NoDuplicates`, `SameSize`から、重複が許容されるレベルを選択することができる。([LLVM::Comdat Class Reference](https://llvm.org/doxygen/classllvm_1_1Comdat.html))

```txt:Comdatの構文
$<Name> = comdat SelectionKind
```

SelectionKindは以下のenumである。

- Any（任意）
リンカーは任意のComdatキーを選択できる
- ExactMatch（完全一致）
リンカーは任意のComdatキーを選択できるが、そのセクションは同じデータでなければならない
- Largest（最大）
リンカーは最大のComdatキーを含むセクションを選択する
- NoDuplicates（重複なし）
重複を許さない
- SameSize（同一サイズ）
リンカーは任意のComdatキーを選択できるが、そのセクションは同じ量のデータでなければならない

```txt:example
$foo = comdat largest
@foo = global i32 2, comdat($foo)

define void @bar() comdat($foo) {
  ret void
}
```
TkEasyGUI で パスワード変更 GUI を作る


# パスワード入力画面を作る


「chpasswd コマンドを使ってパスワードを非対話的に変更する」
https://qiita.com/nanbuwks/items/9c860f658799ba73ae4b

に、

「TkEasyGUI を触ってみる」
https://qiita.com/nanbuwks/items/260276047aa807374433

の皮をかぶせてかんたんな GUI 画面を作ってみます。


# 環境

Debian Testing(Debian 13: 2024/07/06  時点)
# 実行画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/449b1b38-3c19-caa7-a8a9-0289c08dc07c.png)

パスワードを2箇所に入れてOKを押すと、実行しているユーザのパスワードが更新されます。


# プログラム

```
#!/usr/bin/env python3
#import PySimpleGUI as sg
import TkEasyGUI as sg
from subprocess import Popen, PIPE, STDOUT
import os
username = os.getlogin()
layout = [
           [sg.Text("Password:")],[ sg.Input("",size=(25,1),password_char="*",key="-password-")],
           [sg.Text("Password(retype):")],[ sg.Input("",size=(25,1),password_char="*",key="-password2-")],
#          for PySimpleGUI
#           [sg.Checkbox("show password", enable_events=True, key="-toggle_password-")],
           [sg.Text("",key="-message-")],
           [sg.Button('Ok'), sg.Button('Cancel')],
         ]

window = sg.Window('Pleasae setup Password', layout)

# Event Loop to process "events" and get the "values" of the inputs
while True:
    event, values = window.read()

    # if user closes window or clicks cancel
    if event == sg.WIN_CLOSED or event == 'Cancel':
        break

    elif event == "Ok":
       if (values["-password-"]==values["-password2-"]):
#         print (username+":"+values["-password-"]+"\n")
          p = Popen(['sudo chpasswd'], stdout=PIPE, stdin=PIPE, stderr=PIPE, text=True, shell=True)
          p.stdin.write(username+":"+values["-password-"]+"\n")
          p.stdin.close()
          break
       else:
          window["-message-"].update("does not natch!")
          window["-password-"].update("")
          window["-password2-"].update("")

    elif event == "-toggle_password-":
        if values["-toggle_password-"]:
            window["-password-"].update(password_char="")
            window["-password2-"].update(password_char="")
        else:
            window["-password-"].update(password_char="*")
            window["-password2-"].update(password_char="*")

window.close()

```


# パスワードの受け渡し

パイプを開き、 chpasswd に STDIN で受け渡しするようにしています。

# パスワード表示確認機能は断念

```
[sg.Checkbox("show password", enable_events=True, key="-toggle_password-")],
```
として、パスワードの表示確認機能をつけようとしましたが、TkEasyGUI には以下の機能は使えないようで、コメントアウトしています。
```
 window["-password-"].update(password_char="")
```

# 問題点

## パスワードなし sudo が有効である必要があります。

- 内部で `sudo chpasswd` を実行しています。
- このプログラムの想定は Live CD 環境で、それCD だとパスワードなし sudo が有効になっています。
- しかしそうでない環境の場合はパスワードなし sudo を有効にするか、このプログラム自体を sudo で動かすようにして、ユーザ名を外部から取得するなどの対応が必要になります。

## パスワードの変更結果をチェックしていません。

- 有効なパスワードかどうかチェックしていません。
- chpasswd の実行結果をパイプで取得して、正常終了でなければ警告を出すなどの処理が必要になります。
ABC361振り返り

[前回の振り返り](https://qiita.com/comet725/items/48f11ff50670b7e5f1f5)

今日はABC開催日だったので参加結果を振り返る

https://atcoder.jp/contests/abc361

今日は21時に予定があったのでunratedで参加
予定終了後に残り時間少ないまま頑張って解いたけど
コンテストの時間内で解けたのAとCの2問というね…

以降では各問題の振り返り、感想をまとめる。

# A

listのinsert始めて使ったかも

## ソースコード

```python:main.py
import sys
def rI(): return int(sys.stdin.readline().rstrip())
def rLI(): return list(map(int,sys.stdin.readline().rstrip().split()))
def rS(): return sys.stdin.readline().rstrip()
def rLS(): return list(sys.stdin.readline().rstrip().split())
def err(*args): print(*args, file=sys.stderr)

def main():
    N, K, X = rLI()
    A = rLI()
    
    A.insert(K,X)
    
    print(*A)
    
if __name__ == '__main__':
    main()

```

# B

こういう問題はまじで拒否反応でてくるからつらい


# C

値が変化する可能性があるのは最大値・最小値から順番に消去した場合で
それぞれを合計でK個消せるから
最大値からK個消した場合
最小値からK個消した場合
最大値からK-1個、最小値から1個消した場合
最小値からK-1個、最大値から1個消した場合
最大値からK-2個、最小値から2個消した場合
最小値からK-2個、最大値から2個消した場合

と順番に適応した場合を考え、求める数の最小値を探索する

## ソースコード

```python:main.py
import sys
def rI(): return int(sys.stdin.readline().rstrip())
def rLI(): return list(map(int,sys.stdin.readline().rstrip().split()))
def rS(): return sys.stdin.readline().rstrip()
def rLS(): return list(sys.stdin.readline().rstrip().split())
def err(*args): print(*args, file=sys.stderr)


def main():
    N, K = rLI()
    A = rLI()
    
    B = sorted(A)
    
    lowB = B[:K+1]
    upB = B[-K-1:][::-1]
    
    ans = max(A) - min(A)
    for i in range(K):
        ans = min(ans,upB[i]-lowB[-(i+1)])
        ans = min(ans,upB[-(i+1)]-lowB[i])
    
    print(ans)
if __name__ == '__main__':
    main()

```

# D

問題見たのが終了15分という無理ゲー
パット見で解けないのでスルー

# E

グラフ系の問題はまだできませんorz

# F

こういう簡単に解けそうでむずい問題に時間つい食ってしまう。

適当にふるいとsetの組み合わせしようと考えたけど時間切れ。

# G

ここらへんの判定がちゃんとできると囲碁のAIが作れるのかね。

# まとめ

ABC361に参加した結果AとCの2問しか解けなかった。

予定こなした後の参加だったので調子出なかったのか
B問題が苦手な問題だったので撃沈したのかは微妙

今度は万全な状態で挑みたい
ebay APIの使い方

https://www.ebay.co.jp/developer/api

https://www.ebay.co.jp/developer/api/trading

Trading APIを使えば、出品・受注・発送など販売業務を管理する機能を自動化できる。
Trading APIは、一日に5000リクエストの制限。

## API利用準備
下記導入ガイドに従って、準備する

https://www.ebay.co.jp/developer/guide

1. デベロッパーアカウント登録
    https://developer.ebay.com/join/
2. アプリケーションキーの取得
    下記リンクを開き、必よ事項を記入して、下記3つのAPIキーを取得する
    https://developer.ebay.com/DevZone/account/Default.aspx
     - DevID : デベロッパーアカウントを識別するキー
     - AppID ： アプリケーションを識別するキー
     - CertID : API呼び出し時にアプリケーションを認証するキー
    ![eBay2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/10e64dc7-6672-a490-506b-186a95dd47d8.png)
2. ユーザートークンの取得
    下記リンクにアクセスし、Productionをチェックし、Auth'n'Authを押す。
    Sign in to Productionを押すと、eBayにログインするよう求められる。
    https://developer.ebay.com/DevZone/account/tokens/?index=0
    ![eBay1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/795b5709-ee41-23be-2ce7-5ab0609d0c08.png)

以上でAPI利用に必要な4つのAPIキーを取得した。

## APIリクエスト
今回はeBay Python SDkを使用した。最終更新日が数年前なので心配だったがまだ利用できた。

https://github.com/timotheus/ebaysdk-python

```
pip install ebaysdk
```

```Python
from ebaysdk.trading import Connection as Trading
from ebaysdk.exception import ConnectionError

appid='取得したAPIキー'
devid='取得したAPIキー'
certid='取得したAPIキー'
token='取得したAPIキー'

# ユーザー情報を取得するAPI
try:    
    api = Trading(appid=appid, devid=devid, certid=certid, token=token, config_file=None)
    response = api.execute('GetUser', {})
    response = response.dict()
    print(response.keys())
    #print(response.reply)
    print(response['Timestamp'])
    print(response['Ack'])
    print(response['Version'])
    print(response['Build'])
    print(response['User'])
except ConnectionError as e:
    print(e.response.dict())
```

正常に処理されると、紐づけたeBayアカウントのeメールなどの情報が取得される。

## 全API機能一覧

https://developer.ebay.com/DevZone/XML/docs/Reference/ebay/index.html

eBay 出品の追加、修正、再出品、取得、または終了に関わるAPI 

https://developer.ebay.com/DevZone/XML/docs/Reference/ebay/StandardListingIndex.html

出品取り下げにはtemIDとEndingReasonが必要
無断での情報共有が招いた悲劇

# はじめに

自分の会社は開発部が6人しかいない小さな会社で部のTOPにCTO、その下全員横並びのメンバという部に属しています
そこで自分はCTOを除き、部で2番目に長く在籍しているメンバであり、メンバからはそれなりには信頼を得ていると自負しています
そんな自分ですが、最近は部の会議でファシリテータをやったり、様々な意見を提案したりして、部を改善するために様々な取り組みを行っています

先日、部の改善を目的に会社の代表とCTOの二人と、部を代表して相談する機会をもらいました

# しくじったこと

結論からいうと、CTOにはあらかじめ録画・配信することを共有していましたが、会社の代表の許可は得ずに他のメンバに相談内容を配信してしまい、メンバを傷つけてしまったというお話です
その後は多くの人に相談と協力をお願いしながら、今は元に近い状態まで回復しているのではないかと思ってはいますが、この経験から対人関係は慎重にならないといけないという教訓を得ました


## 具体的なエピソード

具体的にどういったことがあったかというと
会社の代表に相談する中でメンバ一人ひとりの業務に関する状況を説明していました
その中であるメンバの状況の説明途中に「彼の話は話半分にきいたほうが良い」「普段の態度から信用できない部分がある」といった話になりました
部の業務に関わる相談中に部のメンバの悪口とも取れる内容を話すなよってところはおいておき、それをきいていた本人に精神的に辛い思いをさせてしまいました

部として相談していた内容としては概ね解決できたということろはありましたが、そのメンバはもちろんのこと、他のメンバも著しくモチベーションが下がる状態を作ってしまいました
その後当事者のメンバは、仕事はするけど代表と顔は合わせ辛いとなり、在宅での勤務を続けることになりました

# その後の対応

そういった状態になってしまってから、自分の中で事態の重大さを認識し、CTOを通じて会社の代表にこの件に関して相談する時間をもらえないかと相談しました
改めてCTOと会社の代表に、その時の内容を配信していて、その内容で精神的にダメージを受けているメンバがいるという状態を説明しました
もちろん無断で配信したことに関しては代表からお叱りを受けたわけですが、言ってしまったことはどうしようもないので、周りのメンバでフォローしてもらいたいという話でその時はおわりました

他のメンバにも今までの経緯を説明しながら、どうすれば良いかを相談しました
幸いなことに自分のやらかしに対して、他のメンバはとても優しく協力してもらえました
相談した結果、お昼に誘って色々話を聞くのが良いのではないかとアドバイスを頂いたので、全員が出社するタイミングに部の皆でランチに出て色々と話をきき、その後少しずつ回復していったのではないかと感じています
内心どう思っているのかはわかりませんが、自分が見ていてそう感じるといったレベルですが…

# 得た教訓

- 無断で録画・配信をしない（必ず許可を取る）
  - 記録に残されたくないことも話されることがある
- オンライン参加者が誰なのかをわかるようにする
  - カレンダの参加者＝会議の参加者とは認識されない
  - 社内MTGの聞き専でも紹介する
- ミスをした時はすぐに関係者に相談する
  - 自分が末端の立場だからできることかもしれませんが…

# さいごに
改めて見ると、ただ報連相をしっかりしましょうと言っているだけですね＾＾；

対人関係のリカバリは大変なので、皆さんも自分のようにならないように、しっかり許可を取って慎重に行動しましょう
世界各国の国コード（2桁・3桁）と名称を自動取得する

世界各国の国コードと名称を一括で取得する方法を記載します。

オープンなデータや基幹システムから取得すると国コードで登録されている場合が多く、2桁版の国コードと3桁版の国コードそれぞれを参照しなくてはならないケースが結構あります。

これはいろいろなサイトでデータが提供されていますが、永続性などで今回こちらから取得することにしました。
https://www.iban.com/country-codes

IBAN（International Bank Account Number）を管理している組織なら大丈夫でしょうということで、WEBサイトからデータをゲットするための方法となります。

PowerBI上の「データを変換」⇒「新しいソース」⇒「WEB」で上記アドレスをペーストして「OK」します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3832168/ab2c305f-27f4-0ab3-65d9-441ca3766642.png)

下記ダイアログが出てくるので「テーブル１」にチェックを入れて「OK]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3832168/a0930181-1c13-7662-d940-9d162754ae71.png)

そうすると「国名」「国コード2桁」「国コード3桁」「国番号」のデータをWEBから直接取得できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3832168/56f62e29-371c-a328-d919-5d25a52dca37.png)

CSVデータなどを管理するのは種類が多くなると面倒なので、できるだけオフィシャルなデータから継続して取得するとPowerBIはラクに作れます。もっといい方法はあるかもしれませんが、簡単なので試してみてください😁
タプル型とuseState

## タプル型とは
タプル型とは**要素数の決まった配列の型**のことで、`[number, string, boolean]`のように表します。

JavaScript におけるタプルとは配列の一種ですので、タプル型の変数の値には配列のリテラル値を渡すことになります。
タプル型を使用することで、「配列の何番目にどのような型の値を入れられるか」という制約をつけることができます。
```ts
type Tuple = [number, string, boolean]

const tuple: Tuple = [123, 'abc', true]
```

`[number, string, boolean]`型の変数の先頭の要素に`number`型ではない値をもつ配列リテラルを代入してみると、先頭の要素（`'123'`）の箇所に型エラーを出してくれます。
```ts
const errorTuple: Tuple = ['123', 'abc', true] //型エラー
```
```
Type 'string' is not assignable to type 'number'.ts(2322)
```

https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types

## オプショナルな要素を持つタプル型
`?`をつけることで、要素をオプショナルにすることも可能です。
```ts
type OptionalTuple = [number, string, boolean?]

const optionalTuple: OptionalTuple = [123, 'abc']
```
オプショナルな型とできるのはタプルの末尾部分に限られ、オプショナルな要素の後ろに必須要素を続けることはできません。
（オプショナルな要素を続けて複数設定することは可能です。）
```ts
type MidOptional = [number, string?, boolean] //型エラー
```
このコードは、以下のように必須要素をオプショナルな要素に続けることができない旨のエラーが出ます。
```
A required element cannot follow an optional element.ts(1257)
```

## ラベル付きタプル型
タプル型の要素には名前をつけることができ、`[num: number, str: string, bool: boolean ]`のように記述できます。
名前をつけてもオブジェクトの要素のようにアクセスすることはできませんが、何番目にどのような要素を入れておきたいかを読み手に伝えることができるようになっています。

要素番号によるアクセスが必要になってしまうため、基本的にはオブジェクトを使用してアクセスする方が可読性が高そうですね。

## 可変長タプル型
タプル型では`...`という構文を使用することで、長さの定まっていないタプルに対しても型をつけることができます。

以下は公式Docsに記載されている例です。
```ts
type StringNumberBooleans = [string, number, ...boolean[]];
type StringBooleansNumber = [string, ...boolean[], number];
type BooleansStringNumber = [...boolean[], string, number];
```

https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types

タプルの中でどの要素が何の型にあたるかが一意に定まらなくなってしまうため、複数の`...`構文を続けて書くことはできません。
```ts
type RestElementTuple = [string, ...number[], ...string[]] //型エラー
```
この書き方をすると、以下のようにエラーが出ます。
```
A rest element cannot follow another rest element.ts(1265)
```

同様の理由で、オプショナルな要素も`...`構文に続けて書くことはできません。
```ts
type RestOptionalTuple = [number, ...string[], boolean?] //型エラー
```
```
An optional element cannot follow a rest element.ts(1266)
```

## React のuseState とタプル型
公式のDocs には以下のような記載があります。
>Tuple types are useful in heavily convention-based APIs, where each element’s meaning is “obvious”. 

各要素の意味が"明らか"で、**慣習**を重視した場面で有用なようです。

https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types

例えば、React における`useState`の返り値の型はタプル型となっています。
```ts
function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
```
`[state, setState] = useState(initialState)`のように（配列の分割代入によって）状態を表す変数`state`とそれを設定する`set`関数を受け取ることで`useState`を使用することができますが、これは「`useState`からは状態を表す変数と`set`関数が常にこの順番で返される」という**慣習**を重視している場面であると捉えられますね。

普段の開発での活用場面は中々ないかもしれませんが、ライブラリの作成や型情報を読み解く際には有用な型となっていそうです。
Pythonの特殊なデータ型: None、Ellipsis、NotImplementedの使い方と活用法

## はじめに

こんにちは！今回は、Pythonの特殊なデータ型である`None`、`Ellipsis`、`NotImplemented`について、それぞれの使い方と活用法をご紹介します。これらの特殊なデータ型は、適切に使用することでコードの可読性と機能性を向上させることができます。

## 1. Noneオブジェクト

`None`は、Pythonで「何もない」や「値が存在しない」ことを表現するために使用される特殊なオブジェクトです。

### 1.1 Noneの基本的な使い方

```python
def get_user(user_id):
    # ユーザーが見つからない場合はNoneを返す
    if user_id not in database:
        return None
    return database[user_id]

user = get_user(123)
if user is None:
    print("ユーザーが見つかりません")
else:
    print(f"ユーザー名: {user.name}")
```

### 1.2 Noneのベストプラクティス

- `None`との比較には `is` または `is not` を使用する（`==` や `!=` は避ける）
- デフォルト引数に可変オブジェクトの代わりに `None` を使用する

```python
def append_to_list(value, my_list=None):
    if my_list is None:
        my_list = []
    my_list.append(value)
    return my_list

print(append_to_list(1))  # [1]
print(append_to_list(2))  # [2]
```

## 2. Ellipsis (...)

`Ellipsis`（省略記号）は、主に多次元のスライシングやタイプヒンティングで使用される特殊なオブジェクトです。

### 2.1 多次元スライシングでの使用

```python
import numpy as np

arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
print(arr[..., 0])  # 各次元の最初の要素を選択
# 出力: [[1 4] [7 10]]
```

### 2.2 タイプヒンティングでの使用

```python
from typing import Callable

def process_data(data: list, callback: Callable[..., None]) -> None:
    for item in data:
        callback(item)

def print_item(item):
    print(f"Processing: {item}")

process_data([1, 2, 3], print_item)
```

## 3. NotImplemented

`NotImplemented`は、二項演算や比較メソッドで、操作が実装されていないことを示すために使用される特殊な値です。

### 3.1 NotImplementedの基本的な使用法

```python
class ComplexNumber:
    def __init__(self, real, imag):
        self.real = real
        self.imag = imag

    def __add__(self, other):
        if isinstance(other, (int, float)):
            return ComplexNumber(self.real + other, self.imag)
        elif isinstance(other, ComplexNumber):
            return ComplexNumber(self.real + other.real, self.imag + other.imag)
        return NotImplemented

    def __radd__(self, other):
        return self.__add__(other)

    def __str__(self):
        return f"{self.real} + {self.imag}i"

c1 = ComplexNumber(1, 2)
c2 = ComplexNumber(3, 4)
print(c1 + c2)  # 4 + 6i
print(c1 + 5)   # 6 + 2i
print(5 + c1)   # 6 + 2i
```

### 3.2 NotImplementedのベストプラクティス

- `NotImplemented`を返すことで、Pythonは他の方法（例：`__radd__`）を試みる
- `NotImplemented`を`raise`しないこと（代わりに`return NotImplemented`を使用）
- `TypeError`や`ValueError`を発生させる前に`NotImplemented`を返すことを検討する

## まとめ

Pythonの特殊なデータ型である`None`、`Ellipsis`、`NotImplemented`について、それぞれの使い方と活用法を紹介しました。

- `None`: 値が存在しないことを表現
- `Ellipsis`: 多次元スライシングやタイプヒンティングで使用
- `NotImplemented`: 二項演算や比較メソッドで操作が実装されていないことを示す

これらの特殊なデータ型を適切に使用することで、より明確で効率的なPythonコードを書くことができます。ぜひ、日々のコーディングで活用してみてください！

以上、Pythonの特殊なデータ型についての記事でした。ご清読ありがとうございました！
Sequence Makerの「通信設定切替」ボタンに関する裏技！？

## はじめに
Sequence MakerはExcelから測定器を制御可能にするアドインです。Sequence Makerでは複数の測定器を制御可能で、それぞれの通信インターフェイスの基本的な設定がリボンからできます。リボンには#1～#3までの3台分のインターフェイスが表示されていますが、「通信設定切替」ボタンを押すことで次のインターフェイス設定に切り替わります。今回はこのボタンに関する裏技！？をご紹介します。Sequence Makerについての詳細は以下の記事を参照ください。

https://qiita.com/sequencemaker/items/8e6a370ab0a793a06a3b

:::note warn
***お断り***
本記事の内容はSequence Maker開発元の公式見解ではなく、あくまでも個人が趣味の範囲内で執筆しているものです。記事の内容について開発元へ問い合わせることはお控えください。ご質問・要望などは各記事のコメント欄へお願いいたします。
:::

## 「通信設定切替」ボタンの動き
ボタンを押すごとに、通信インターフェイスが切り替わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/ff060d13-5cfa-daa2-b6b3-9683557de3dc.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/a098482b-7d49-fb14-410f-d544a32e7b5c.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/35d1e3c4-9356-f716-28b8-2537aa139c6e.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/8ddb365d-90d0-01d3-0bf8-72d6f84ab762.png)

## 裏技
実は「通信設定切替」ボタンですが、
***Shiftキーを押しながらクリックすると逆順で切り替わる***
のです。
つまり上記の図の順で言うと下から上に向けて切り替わります。

:::note
この機能はV1.60～の機能です。
:::

## まとめ
裏技と言うほどではなかったかもしれませんが、小ネタということで。なお、複数のインターフェイスの設定をまとめて変更したい場合は、右下の矢印をクリックしてオプション画面で操作した方が便利です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/dfbf23f2-2a4d-eeda-e223-3046a0520cc7.png)
AzurePipelines: Azure Developer Cli を install するには、setup-azd@0 ではなく、curl で・・ :(

# 背景

azd deploy してるアプリを CI/CD する為に、pipelines で azd install 方法を調べた結果の記録

# 結論

- azd cli は現状、GitHub actions 用のみ？

```yaml: GitHub Actions であれば、以下で行けそう
- task: setup-azd@0
displayName: Install azd
```

- ということで、curl で install
```yaml: Azzure Pipelines 用
- task: Bash@3
  inputs:
    targetType: 'inline'
    script: |
      curl -fsSL https://aka.ms/install-azd.sh | bash
  displayName: 'Install azd'
```


# 状況

- task に cli で検索しても見つからない
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/639ab024-2b10-d9c9-60b1-4b959f292ef8.png)

- intelisence 使っても、見つからず
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/59a8a189-ab36-5a30-aaba-13ba16ba9d80.png)

- Document にも存在はしない
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/efaff081-baa3-e1bc-e616-b9e283be1870.png)


https://learn.microsoft.com/ja-jp/azure/devops/pipelines/tasks/reference/?view=azure-pipelines

# あとがき

Release では以下のように書いてあるので、対応してたんじゃないのか？と思うんだけど・・よくわからず

> Starter CI/CD workflows for GitHub Actions (.github/) and Azure Pipelines (.azdo/) so you can test against real Azure resources on every commit

link 切れしてた、awesome-azd を見つけたが、何故か <code>.azdo/</code> については存在していない。

https://github.com/Azure/awesome-azd/tree/main
Pythonのデータ型メモリ効率：タプルとリストの比較と最適化テクニック

こんにちは！今回は、Pythonにおけるデータ型のメモリ効率について、特にタプルとリストの比較を中心に、メモリ使用量の最適化テクニックをご紹介します。

## 1. はじめに

Pythonは動的型付け言語であり、メモリ管理を自動で行ってくれます。しかし、大規模なデータを扱う際や、メモリに制約のある環境で開発を行う場合、データ型の選択やメモリ使用量の最適化が重要になってきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/7e5401ce-70fb-323a-26e9-127333dcb9cc.png)

## 2. タプルとリストの比較

### 2.1 メモリ使用量の比較

タプルとリストは、どちらも複数の要素を格納できるシーケンス型のデータ構造ですが、メモリ使用量に違いがあります。

```python
import sys

# タプルとリストのメモリ使用量を比較
tuple_example = (1, 2, 3, 4, 5)
list_example = [1, 2, 3, 4, 5]

print(f"タプルのメモリ使用量: {sys.getsizeof(tuple_example)} バイト")
print(f"リストのメモリ使用量: {sys.getsizeof(list_example)} バイト")
```

実行結果：
```
タプルのメモリ使用量: 80 バイト
リストのメモリ使用量: 104 バイト
```

タプルの方がリストよりもメモリ使用量が少ないことがわかります。これは、タプルが不変（イミュータブル）であるため、サイズ変更のためのオーバーヘッドが不要だからです。

### 2.2 パフォーマンスの比較

メモリ使用量だけでなく、処理速度にも違いがあります。

```python
import timeit

def access_tuple():
    t = (1, 2, 3, 4, 5)
    return t[2]

def access_list():
    l = [1, 2, 3, 4, 5]
    return l[2]

print(f"タプルのアクセス時間: {timeit.timeit(access_tuple, number=1000000)} 秒")
print(f"リストのアクセス時間: {timeit.timeit(access_list, number=1000000)} 秒")
```

実行結果：
```
タプルのアクセス時間: 0.0720234 秒
リストのアクセス時間: 0.0863542 秒
```

タプルの方がわずかに高速であることがわかります。

## 3. メモリ使用量の最適化テクニック

### 3.1 ジェネレータの使用

大量のデータを扱う際、すべてのデータをメモリに保持する代わりに、ジェネレータを使用することで、メモリ使用量を大幅に削減できます。

```python
import sys

# リストの場合
numbers_list = [i for i in range(1000000)]
print(f"リストのメモリ使用量: {sys.getsizeof(numbers_list)} バイト")

# ジェネレータの場合
numbers_gen = (i for i in range(1000000))
print(f"ジェネレータのメモリ使用量: {sys.getsizeof(numbers_gen)} バイト")
```

実行結果：
```
リストのメモリ使用量: 8448728 バイト
ジェネレータのメモリ使用量: 112 バイト
```

### 3.2 __slots__の使用

クラスのインスタンスが多数作成される場合、`__slots__`を使用することでメモリ使用量を削減できます。

```python
import sys

class PersonWithDict:
    def __init__(self, name, age):
        self.name = name
        self.age = age

class PersonWithSlots:
    __slots__ = ['name', 'age']
    
    def __init__(self, name, age):
        self.name = name
        self.age = age

person_dict = PersonWithDict("Alice", 30)
person_slots = PersonWithSlots("Bob", 25)

print(f"__dict__を使用したインスタンスのメモリ使用量: {sys.getsizeof(person_dict)} バイト")
print(f"__slots__を使用したインスタンスのメモリ使用量: {sys.getsizeof(person_slots)} バイト")
```

実行結果：
```
__dict__を使用したインスタンスのメモリ使用量: 48 バイト
__slots__を使用したインスタンスのメモリ使用量: 40 バイト
```

### 3.3 適切なデータ構造の選択

状況に応じて適切なデータ構造を選択することで、メモリ使用量とパフォーマンスを最適化できます。

- 要素の追加・削除が頻繁：リスト（`list`）
- 一意の要素を扱う：セット（`set`）
- キーと値のペア：辞書（`dict`）
- 固定長で変更不要：タプル（`tuple`）

## 4. まとめ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/fd405cd5-196f-a37b-43f1-bc48b2b62d53.png)

Pythonにおけるデータ型のメモリ効率について、タプルとリストの比較を中心に見てきました。また、ジェネレータの使用、`__slots__`の活用、適切なデータ構造の選択など、メモリ使用量を最適化するテクニックをいくつか紹介しました。

大規模なデータを扱う際や、メモリに制約のある環境で開発を行う場合は、これらのテクニックを適切に活用することで、効率的なプログラムを作成することができます。

最後に、実際にボトルネックとなっている部分を適切に分析してから最適化を行うことが重要です。

以上、Pythonのデータ型メモリ効率についての記事でした。ご清読ありがとうございました！
Dockerコンテナの仮想NICのIPを調べる方法

# はじめに
以前以下の記事でDockerのネットワーク構造を調べていた時に、コンテナのNICのIP等を調べる必要があったのでその時の方法を以下にまとめます。

https://qiita.com/maplejava/items/a70ef1a4e62b73085aa1

# カンタンな方法
といっても、以下の通り調べたいコンテナ内でbashを起動してifconfigコマンドを実行すればいいだけである。

[container name/container ID]で指定したcontainer内でbashを起動する
```
docker exec -it [container name/container ID] bash

```
出力例（container IDに左図の” 6d79b5258833 “を指定した場合）
```
root@AZ-foo-pc28:/home/userpco128# docker exec -it 6d79b5258833 bash
root@6d79b5258833:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 708  bytes 49284 (49.2 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 49  bytes 2914 (2.9 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
・・・

```
カンタンですね。

しかし、別の方法もあります。
上記の記事でも紹介した通り、DockerはLinuxカーネルのnetnsの機能を使ってコンテナごとに異なるネットワーク名前空間を作ることで、コンテナ間やコンテナ‐ホスト間のネットワークを隔離しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/71590797-7351-6a97-ab0a-fc3064da9b14.png)

上記を踏まえると以下のような方法でも調べることができます。

# psコマンドから覗いてみる方法
Dockerを起動しているホスト上で以下を実行します。

Dockerコンテナを実行している状態で、ps auxfコマンドにてホスト上のプロセス一覧を表示
```
・・・
root        5416  0.0  0.1 720504 15668 ?        Sl   12:42   0:00 /usr/bin/containerd-shim-runc-v2 -namespace moby -id c81bfe4cf140bcb443318431ff4024d906b0e1d657038fe2819972c4ff516f53 -addr
root        5438  0.0  0.0   4640   896 ?        Ss   12:42   0:00  \_ /bin/sh /usr/sbin/apachectl -D FOREGROUND
root        5463  0.0  0.0  73972  5188 ?        S    12:42   0:00      \_ /usr/sbin/apache2 -D FOREGROUND
www-data    5466  0.0  0.1 1280728 9068 ?        Sl   12:42   0:00          \_ /usr/sbin/apache2 -D FOREGROUND
www-data    5467  0.0  0.0 1280672 6500 ?        Sl   12:42   0:00          \_ /usr/sbin/apache2 -D FOREGROUND
・・・

```

Dockerコンテナのプロセスは以下です。
```
root        5438  0.0  0.0   4640   896 ?        Ss   12:42   0:00  \_ /bin/sh /usr/sbin/apachectl -D FOREGROUND
```


コンテナ内でnetnsコマンドを使用するために、ホストのnetnsディレクトリ配下に該当のプロセスのネットワーク名前空間のシンボリックリンクを作る（Con1は任意のネットワーク名前空間名です）
```
ln -s /proc/5438/ns/net /var/run/netns/Con1
```

netnsコマンドを使用してDockerが作成したネットワーク名前空間の中身を盗み見る
```
root@AZ-foo-pc28:/home/userpco128# ip netns exec Con1 ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 38  bytes 3858 (3.8 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14  bytes 8372 (8.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
・・・
```
上記のように、コンテナのプロセスのネットワーク名前空間内でifconfigコマンドを実行することでもIPアドレスを調べることができます。

# 参考

https://qiita.com/megmogmog1965/items/f5682de2068a79d196a2
[vim script] ¥tでタブをechoしようとしても、そのまま「¥t」と出力されてしまう

# はじめに
最近、`vim script`を勉強してみようと手を出してみたんですが、いきなり詰まったのでここに備忘録を残しておきます。

# 解決
結論としては、ダブルクオートを使おうということです。
```vimscript
" 誤
echo 'hello¥tworld'
" -> hello¥tworld

" 正
echo "hello¥tworld"
" -> hello  world
```
ChatGPTにロールプレイをさせてみる

実はChatGPTに特定のキャラクター（役割）を指定するとそのキャラクターになりきってくれます

## 例：キャリアコンサルタント
試しにキャリアコンサルタントになってもらいましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/3be3bde5-8fc8-9e36-831e-efbb88a1f507.png)


半分嘘で半分事実で送ってみました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/b3122d04-e38c-2467-257e-73ec5726660d.png)

レスポンス内容がウィンドウに入りきらなかったので画像２枚使います

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/ebfc30de-a20c-2559-8a47-db07a6fa858f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/f33dcf4e-b963-edf1-6b65-8080ec3b9c05.png)

`具体的なステップの2`においてどうやら`適切な解決方法を導き出す自信がありません。`を
`自信がありません。`と解釈してしまったみたいで少し見当違いのレスポンスですが他のレスポンスは的確で前向きなアドバイスになったと思います
心強いねぇ・・・

## 例：英語講師
次は英語講師になってもらいましょう
ただ英語講師になるのではなく、陽気な講師にしてみましょう
別スレッドで新しくやり取りを始めます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/95b66382-6ec3-84d9-6810-aaa4c2bc7e9a.png)

陽気なのか微妙なラインですね
性格面はまだインプットされてないのかもしれませんね
とりあえず続けてみます

またウインドウに収まらなかったので画像を2枚使用します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/83950e8a-0a2c-0fd7-2698-fe38e4822be8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/77a7a050-1b71-5f17-fc63-e39b867d265b.png)

問題が出てきました
答えてみます（自信は無い。。。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/d594353f-579d-cf59-8156-f00bc9bb68c7.png)

くっ・・・ま、間違えたら指摘してくれるみたいですね。わかってましたよもちろん

> もう一度、この修正後の自己紹介文を言ってみましょうか？

この回答が気になったので答えてみます
言ってみましょうか？ってテキストのレスポンスなのに声を出すのかと。。。
実際に音声の再生はできるけど、それを前提としている？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/e559900a-f75e-75b4-8bc6-94495b500e9b.png)

気づきました。あくまで英語講師。目の前に講師がいる前提だったんですね。これはあっぱれですｗ

### そのほかにもたくさんのキャラクター
例えば下記のようなキャラクターにすることができます
- 英語講師
- 数学講師
- プログラミング講師
- 資格対策
- カウンセラー

## おわりに
専門的な質問であればキャラクターを立てると良いかもしれませんね
ある程度の分野が絞れるのでレスポンスの精度は高まるかもしれません
僕は普段からプログラムの質問をする際は技術領域ごとにキャラクターを立てています（フロントエンドエンジニアやバックエンドエンジニアなど）
皆さんも良ければChatGPTにキャラクターを指定してみてはいかがでしょうか

下記が今回使用したChatGPTとのやりとりになります

### キャリアコンサルタント

https://chatgpt.com/share/9c7fed12-3c76-4b02-b6c8-72674e66c8fd

### 英語講師

https://chatgpt.com/share/4feaaf0e-1f67-4133-8a5a-aa0716640f43

## 参考資料

https://www.udemy.com/course/prompt-llm/?couponCode=ABCART0923
Azure Pipelines: Yaml ファイルと、triggers: の関係

# 背景

create pipelines をした際、思った動きをしなかったので調べた結果の記録

# 現象

- Create pipeline をして
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/2eb5bb57-6b74-aa7f-7791-1e25a5eb48ac.png)
- とりあえず、branch に保存して、動作確認をしようとした
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/cbb71a7e-24cb-cac4-b72c-7b5bf2d54c10.png)

結果・・

- triggers に記載したように動いてくれない

```yaml: pipeline 例
trigger:
  branches:
    include:
    - main
    - feature/*
```

## 認識齟齬と感じた点

- main, feature/* と書いたのに、main での commit に一切反応しない

そんなわけないので、以下障害となりそうなところも確認したが、一向に解決しなかった。

https://learn.microsoft.com/ja-jp/azure/devops/pipelines/build/triggers?view=azure-devops#branch-consideration-for-triggers-in-yaml-pipelines

# 結論

- branch のどこにおいても、動作   << 当然ですね。
- 但し、pipeline の <font color=red>yml ファイルが存在している branch でのみ</font>動作。 << ここ重要
    - 別 branch で、同一 yml が存在している場合は branch 共通で動作 
    - 別 branch で、yml が無い場合は、**非動作**  << 
- triggers の default branch は無影響
- branch の default branch も無影響  

ようは、
- yml ファイルの設定は、branch 越えて動作するけど、その設定は対象 branch 内にある yml みてるよ。なので、yml が無ければ動作しないし、別の内容なら、その内容になる。

今回の現象としては、
- 新しく branch 切って yml を追加しようとしたから、
    -　pipeline 設定が<font color=red>他の branch にまだ存在していない</font>状況なので、<font color=red>何も動かなかった</font>

ってことでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/d3ed5fd0-fda1-bbea-ee90-7497e9e6eff4.png)

そう、ここの設定で、直接 commit directly してたら気付かない。

# あとがき

triggers: が反応しない！？？ってなって、色々調べたけど、理解が深まってよかったよかった :sweat: 

調べた内容
- branch 毎に、別の yml 置いてマトリックスで起動確認
- default branch 二種での比較
- triggers: の include/exclude, branches などの記述比較
- GUI による trigger overwide
- MS -Learn にある、trigger 阻害要因
- branch にある yml ファイルの削除 << ここでようやく結論に至った :sweat_smile: 

結構長かった・・けど、解決してよかった
もし間違ってたら指摘お願いします。 :bow:
session not created: DevToolsActivePort file doesn't existにつまづいた

# ハマった状況

スクレイピングをするときにgoogleの既存のユーザアカウントを使ってスクレイピングがしたかったので

- ユーザ情報をselenium.webdriver.chrome.optionsを使って設定
- 読み込み

という手順で実装したら"session not created: DevToolsActivePort file doesn't exist"と出るようになって1時間ほどあーでもないこーでもないと困りました。

# 対処
簡潔に対処だけ。
```python
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument('--user-data-dir=chrome://versionでみれるパス')
options.add_argument('--profile-directory=同じくchrome://versionでみれるディレクトリ')
# その他の設定は省略

driver = webdriver.Chrome(options=options)
```

プログラムと同じディレクトリにprofileディレクトリを作って、

```python
options.add_argument('--user-data-dir=作業ディレクトリ/profile/')
options.add_argument('--profile-directory=ユーザデータのディレクトリ名')
```
と直しました。


このエラー、headlessモードにするとなぜか出なくなったのですがその因果関係がわからないままで、「ファイル参照うまくいってないなら権限とかのせいかなー」と思って試したら動くようになったので、正直これで何で通常通り動くのか腑に落ちていないところがあります。
Aurora MySQL 2 → 3 へのアップグレード

# Aurora MySQL 2 のサポート終了
**2024/10/31** を以って **Aurora MySQL 2**（MySQL 5.7互換）のサポートが終了します。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/Aurora.VersionPolicy.html#Aurora.VersionPolicy.MajorVersions

次Verの **Aurora MySQL 3**（MySQL 8.0互換）へのアップグレードを実施していきます。
以下、基本的にAWSコンソール上からの操作です。

なお、**Serverless v1** も同様に期限が迫っています。以下ご参考まで。

https://qiita.com/tksnino/items/230d1741de53d35b9db9


# 準備
## パラメータグループ
Aurora 3用のパラメータグループを作成後、Aurora 2のパラメータグループと比較して、必要な箇所を変更します。
- **「アクション」→「比較」** から

※変更不可の項目もあります。

少なくとも`character_set_`群・`collation_`群・`time_zone`は変更することになるかと。

MySQL 8.0では`default_authentication_plugin`の変更がありますが、Aurora 3では引き続き`mysql_native_password`で固定です。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Compare-80-v3.html#AuroraMySQL.mysql80-authentication

## インスタンスタイプ
- `t2`シリーズおよび`t3.small`以下は使えなくなりました

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/Concepts.DBInstanceClass.html#Concepts.DBInstanceClass.SupportAurora

- `t4g.medium`が最も廉価な選択肢です

https://aws.amazon.com/jp/rds/aurora/pricing/

# アップグレード作業
## インプレースアップグレード
ブルー＆グリーンデプロイでも停止期間がゼロにはならないことから、ある程度サービス停止（メンテナンス時間）が許容されるサービスならインプレースアップグレードも可能です。

:::note info
メンテナンス中の表示などはアプリケーションないしELB固定レスポンスなどで実施
:::

インスタンスタイプが Aurora 3 のサポート外の場合は、まずインスタンスタイプの変更を先に実施する必要があります。
 **インスタンスの「変更」** から以下を更新します。
- インスタンスタイプ
→`t4g.medium`などを指定

- CA認証機関が古ければ、このタイミングで変更
→`rds-ca-rsa2048-g1`などを指定

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL-certificate-rotation.html

上記の変更内容を確認し、**「すぐに適用する」** で実行。

インスタンスの変更完了後、 **クラスターの「変更」** から以下を更新します。
- エンジンバージョン
→`Aurora MySQL 3`の任意のマイナーバージョンを指定

- カスタムパラメータグループ
→準備段階で作成したAurora 3用のパラメータグループ

上記の変更内容を確認し、**「すぐに適用する」** で実行。
→自動でAurora 2時点のスナップショットが作成されます。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Updates.MajorVersionUpgrade.html#AuroraMySQL.Upgrading.Sequence

クラスターの **「ログとイベント」** から進捗が確認できます。

## エラーが出た場合
クラスターの「ログとイベント」に以下のようなメッセージが出ているとアップグレード失敗です。

> Database cluster is in a state that cannot be upgraded: Engine bootstrap failed with no mysqld process running

**インスタンス** の「ログとイベント」タブからエラーログをDLして確認すると、例えばこんなエラーが出ていたりします。

> [ERROR] [MY-013140] [Server] Comment for table '{SCHEMA}.{TABLE}' contains an invalid utf8mb3 character string: '\x**\x**\x**'.

この場合は、既存のテーブル・カラムのコメントの文字コードが怪しかった模様。
あらかじめALTER文で更新しておきます。

そして改めてアップグレード実行。

## カスタムパラメータグループの反映
:::note warn
アップグレード完了後に再度クラスターを再起動する必要があります
:::

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Updates.MajorVersionUpgrade.html#AuroraMySQL.Upgrading.ParamGroups

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86958/99985c01-39a9-cd01-5e6d-32f9c86276aa.png)

以上で、インプレースアップグレード完了です。

# まずは検証
手順も含めて、検証環境等で事前にしっかり確認することが肝要です。
- インプレースアップグレードの検証
- アプリケーションの動作確認
Googleデータセット検索

# はじめに
データ分析について、社内外の人向けに紹介したりオススメするときに困る点の１つが、
分析してもらうデータをどうするか？という点です。
社内データをそのまま利用できればOKですが、さすがに社外に出したり、プライベートに持ち込むことは厳しいですよね・・・・。

# Googleデータセット検索
Googleには、データセットを検索できるサイトがあるのです！

https://datasetsearch.research.google.com/

使い方も簡単で、キーワードを入れると該当するデータセット候補を表示してくれます💡


# 検索例
ポケモンのデータセットもあります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3091004/f92fd7e2-3e35-853c-5386-c3cddad5eb93.png)


表示された情報をもとに、外部リンクに遷移して、データの利用条件等を確認していきます。


# 最後に
今回は、分析用データを探す「Googleデータセット検索」のご紹介でした！
Azure VM上のルートテーブルについて

# Azure VMにて…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/b9054d51-ea49-9d7d-14f5-e929e43e4f99.png)

Azure VM上でルートテーブルを確認した時のことです。
```
root@AZ-foo-pc27:/home/ncbpco127# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.10.100.1     0.0.0.0         UG    100    0        0 eth0
10.10.100.0     0.0.0.0         255.255.255.192 U     0      0        0 eth0
168.63.129.16   10.10.100.1     255.255.255.255 UGH   100    0        0 eth0
169.254.169.254 10.10.100.1     255.255.255.255 UGH   100    0        0 eth0
```
### 1行目
デフォルトルートはeth0を介してGatewayである10.10.100.1に送信されることを表す。
### 2行目
Gatewayが0.0.0.0なので、10.10.100.0/26はGatewayを介す必要がなく、ローカルのeth0を介してパケットが送信されることを表す。
### 3・4行目
？？？心当たりのないルートが定義されている…と思い、このルートについて調べてみました。

# 168.63.129.16とは

同じタイトルのMSLearnがあります。

https://learn.microsoft.com/ja-jp/azure/virtual-network/what-is-ip-address-168-63-129-16

> この仮想パブリック IP アドレスによって、次のようなことが容易になります。
> 
> - VM エージェントが Azure プラットフォームと通信して、それが "準備完了" 状態にあることを通知できるようにする。
> - カスタム DNS サーバーが存在しないリソース (VM など) にフィルター処理された名前解決を提供するために、DNS 仮想サーバーとの通信を有効にする。 このフィルター処理により、お客様が自分のリソースのホスト名だけを解決できるようになります。
> - [Azure Load Balancer の正常性プローブ](https://learn.microsoft.com/ja-jp/azure/load-balancer/load-balancer-custom-probe-overview)が VM の正常性状態を特定できるようにする。
> - VM が、Azure の DHCP サービスから動的 IP アドレスを取得できるようにします。
> - PaaS ロールに対するゲスト エージェントのハートビート メッセージを有効にする。

Azure VMに対するLBの正常性プローブやDHCPサービスから動的IPを取得する際に使用されるルートのようです！

# 169.254.169.254とは

こちらもMSLearnに記載があります。

https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service?tabs=windows

>The Azure Instance Metadata Service (IMDS) provides information about currently running virtual machine instances. You can use it to manage and configure your virtual machines. This information includes the SKU, storage, network configurations, and upcoming maintenance events.
…（略）
IMDS is a REST API that's available at a well-known, non-routable IP address (169.254.169.254). You can only access it from within the VM. Communication between the VM and IMDS never leaves the host. Have your HTTP clients bypass web proxies within the VM when querying IMDS, and treat 169.254.169.254 the same as 168.63.129.16.

Azure VMのメタデータを収集する際に使用されるルートのようです！
Azure VMの内部構造を知れた感じがして楽しいです。

# ちなみに
AWSやGCPにも同じように仮想マシンのメタデータを収集するためのIPアドレスがあります。
### AWSの場合

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/instancedata-data-retrieval.html

AWSも同じ169.254.169.254ですね！

### GCPの場合

https://cloud.google.com/compute/docs/metadata/default-metadata-values

GCPは”metadata.google.internal”というDNS名らしく、IPは10.0.0.1でプライベートIPアドレスです。

# 参考
https://milestone-of-se.nesuke.com/nw-basic/as-nw-engineer/ipv4-ipv6-link-local-address/
TkEasyGUI を触ってみる

話題の TkEasyGUI を試してみました。



「PySimpleGUI を使ってみる」
https://qiita.com/nanbuwks/items/396e33f82f1ab8702560
で試したサンプルプログラムを動かしてみました。



# 環境
- Debian Testing (2024/7/6時点のDebian 13)
- python 3.11.9
- PySimpleGUi 5.0.6

# 事前準備

```
# apt install python3-pip
# apt install python3-tk
```
# TkEasyGUI インストール
今回もシステムにインストール。

```

# pip install --break-system-package  TkEasyGUI

```
# サンプルプログラム

こちらにあるサンプルプログラムの1行目を変更して動かしてみます。
https://www.pysimplegui.com/



```
# import PySimpleGUI as sg
import TkEasyGUI as sg

# All the stuff inside your window.
layout = [  [sg.Text("What's your name?")],
            [sg.InputText()],
            [sg.Button('Ok'), sg.Button('Cancel')] ]

# Create the Window
window = sg.Window('Hello Example', layout)

# Event Loop to process "events" and get the "values" of the inputs
while True:
    event, values = window.read()

    # if user closes window or clicks cancel
    if event == sg.WIN_CLOSED or event == 'Cancel':
        break

    print('Hello', values[0], '!')

window.close()
```

うまく実行できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/0110a107-6a7c-4f62-6d85-3533084fffb0.png)
webviewハックされないためのテクニック

# 意図しないウェブページ表示の恐怖
スマホアプリにおけるwebview実装はアプリ内に特化したお知らせ等の利用で効果的ですが、その実態はただのウェブブラウザなので、適切な対応をしないと意図しない表示をアプリ内に出してしまったり、最悪な場合はアプリ内、引いてはサービス内の情報漏洩につながるリスクがあります。

こちらは、某auアプリにて意図しないウェブページが表示できてしまった例です。

![Screenshot_au PAY.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3510897/2bad8c2f-15ff-580a-a9b4-dabc50c40139.jpeg)

この内容ならただのジョークで済みますが、危険なサイトを表示出来てしまったり、意図しないサービス提供となってしまうとジョークでは済まされません。
以下ではどうやって外部URLへのアクセスを防ぐかをいくつか考えてみました。

# 総当たり確認
シンプルに、外に抜け出す穴がどこかに無いかを総当たりで探すのは、利用者観点で問題がないかを確認することにもつながる基本の打ち手です。商用サービスであればリグレッションテストの項目としてやることかと思いますので、この作業については、利用者の使い勝手をチェックするために行いましょう。

流石にウェブの全操作方法を網羅することは難しいですので、ここでのポイントは、意地でも穴をふさいでやる、というよりは、ユーザがふとした操作で抜け出し迷ってしまわないか、特に自社サービス外の内容が自社サービス内容と勘違いされてしまわないかどうかのチェックに主眼を置きましょう。

# ローカルで表示用データを持つ
WebViewと言っても必ずしもInternet経由で情報取得する必要はありません。例えばアプリ内で閉じてもよいFAQや辞書的な用途であればアプリ内で持っておくのも手です。メリットとしては外部への不要なリンクを防ぐだけでなく、回線速度に依らずすぐに参照できるため、ユーザ体験的にもプラスになります。Androidではassets内にHTML等のファイル形式で入れておき、URLは相対参照するとよいでしょう。
この場合は内容更新をアプリアップデートに頼らざるを得なく、外部リソース修正で即時対応可能なWebViewの利便性をつぶしてしまう点はデメリットでしょうか。このあたりはうまく使い分けできればいい感じです。

# ドメインに制限をかける
まあこれが一番シンプルでしょう。ドメイン名を見て、別ドメインへアクセスを止めれば基本的には外部情報の表示を阻止できます。

この方法場合、他のドメインをアプリ内で表示出来なくなるので注意しましょう。webViewの目的にも依りますが、対象外ドメインの場合は普通のブラウザで開くように分岐させるのが無難な対応でしょうかね。いろいろな都合上、別ドメインも許可したい場合はホワイトリスト的に管理するしかないですので、あまりいろいろなドメインを利用しないでサービスを作るほうがよさそうですね。

この方針を例えばandroidでやるならshouldOverrideurlloadingを管理するやり方になると思いますが、この方法はいわゆるリンクのタップ操作等を契機とした遷移を塞ぐものなので、JavascriptによるURLローディングには非対応だったり、XSS等のウェブサイト側のセキュリティ起因な課題に対応できるものではないことに注意です。アプリだけで使うウェブページだからといっても手抜きはNG。

# 気にしない
正直ほとんどがこれになるでしょうね。別に表示されても誰も困らないじゃん、という割り切り。セキュリティの基本は、その穴を突かれた時の問題の大きさの把握、つまりは、どのような攻撃があり、どう備えるべきかというリスクの管理です。なんでも塞げばいいというものではなく、どれだけの危険な事象を防げているか、そのうえで運営可能か、の妥当なレベルでの管理が求められます。

WebViewを利用しての特に危険なものは、JavascriptInterfaceを介してのWebView→androidアプリへの情報取得です。仮にこれを利用してゲームに即時影響のあるパラメータ変更だったり、スマホストレージを参照・編集する処理、社内DBにも反映される情報だったりをやり取りしているのであれば何が何でも外部ドメインへの流出は塞ぐ、または、外部ドメインからのアクセスの場合はインタフェースを無効化するべきでしょう。一方、あくまでWebView内で閉じていて、本当のビューアとしてだけの利用であれば、やんちゃなお客様が外を覗きに行くのを阻害するほどの必然性はなさそうですね。