OmniAICreator/Qiita-1.07M huggingface dataset:
infolinkの技術構成

# アプリケーション側

Djangoを使ってます。

requirements.txtはこんな感じ

```python
bleach==5.0.1　サニタイザーです。styleやタグや属性を区別するのに使う。　非推奨らしいです。githubに載ってました。どうしよう
beautifulsoup4==4.12.2　一部のclassを許可するため
Django==4.2.4
django-allauth==0.55.2　認証
django-ckeditor-5==0.2.10　djangoでckeditor5を簡単に使える。カスタマイズされたのを使いたい場合は自分でインストール
django-ipware==6.0.0　get_cliant_ip(request)みたいな感じで簡単にipをとれる。ログを保存しないといけないので使ってます。
django-widget-tweaks==1.5.0  {{form.password|add_class:"bg-gray-50 ..."}}みたいな感じでallauthのテンプレートをカスタマイズしてます。
django-environ==0.11.2　共有するときにファイルが分けれてるのが便利でいいんだと思います。チームでやったことないので、あまりわからないです。
psycopg2-binary==2.9.9　postgreSqlをつかうのに必要らしいです。詳しいことはわかりません。
tinycss2==1.1.1 これは、bleachをインストールすればインストールされるはずだけど、なぜか本番ではインストールされてなかった。エラーでもなかった。謎
```
追記
widget-tweaksは使わないほうがいいと思います。エラーの表示とかが面倒、というか気付かなかったりしたので、formsをオーバーライドして、属性を加えたりするほうが多分楽。

あとは、html,css,javascriptぐらいです。jsはreactとかnodejsを使ったほうがいいらしいですが、めんどくさいのでそのまま使いました。html css -> js -> docker-> python django みたいな感じでやってきたので、jsはわかる。

cssはloginやsignupはtailwindで、他はbootstrapです。Tailwindを使うと、editorの表示が変わるのでbootstrapにしました。

LoginとSign inはFlowbiteやtailwind公式からコピペしました。調べたら出てきます。設定ファイルもコピーするのを忘れないでください。でも、allauthと連携させるのが面倒でした。

# クラウド

awsを使ってます。

Chatgptに楽に公開できるのを聞いたらelastic beanstalkだったので、ebを使いました。

*   ELB
*   EC2
*   RDS(postgresql)

postgreを選んだのは、mysqlを使うのに必要なmysqlclientをローカルに入れてみたら、エラーになったからです。どっちのほうがいいのかはわかりません。

ebは別の記事で詳しく解説するつもりです。チュートリアル的な

そんなに楽じゃなかったけど...  さっきもちょっと変えようとデプロイしたら、謎のエラーが出てやばいです。ログ見ても、エラーらしきものはない。sssd関連のerrorは多少あるけど、あまり関係なさそう。ヘルスチェックの基準の設定を下げるべきなのかもしれません。今もsevereでも、ちゃんと動いてますし。

クレジットカード持ってるなら、gcpのほうがいいかもしれません。300$もらえるので。どっちが得なんでしょうかね、12か月の無料分と。

# 画像

画像のアップロードや配信はcloudflare imagesを使っています。理由は安いのと、使いやすいからです。

Cloudflareはdnsやcdnとしても使ってます。ルートドメインをcnameにできないところもあるらしいので、cloudflareでよかったです。infolink.us-~~.elasticbeanstalk.comみたいなドメインとつなげてます。

# メール配信

mailgunを使っています。でも、amazon sesに移行するつもりです。そっちのほうが結構安かったのと従量課金制だった気がするので。あと、mailgunって最初めっちゃ金とられたんですよね。無料期間 -> 最安プランの35$のはずなのに、21 ドルぐらいと35ドルになってました。今月はそろそろ終わるのに、35ドル払っちゃってます。

怠けてたせいだけど、悔しい。21ドルは謎。

追記
21ドルはmailgunが月末に支払いを合わせてるからっぽいです。月の途中から契約したので、21ドル.
amazon sesは拒否られました。結構やり取りしたけど、拒否られました笑 
mailchimpに移行する予定。

あと、見れるデータなどに違いがるのかもしれないけど、認証に使うだけなのでいらないです。

sendgridは登録が厳しかったので止めました。

# イラスト

ロゴは[https://pixabay.com/vectors/panda-bear-cute-asian-zoo-bamboo-1300187/](https://pixabay.com/vectors/panda-bear-cute-asian-zoo-bamboo-1300187/)  
ここからです。見た感じfreeで使っても大丈夫。  
選んだ理由は、ロゴに向いてそうだったから。

初期アイコンや僕のアイコンは[https://3axis.co/smoking-panda-vector-art-cdr-file/eo268378/](https://3axis.co/smoking-panda-vector-art-cdr-file/eo268378/)  
ここからです。見た感じfreeでつかってok。  
選んだ理由は、絶妙なキモさですね。絶妙に気持ち悪いのが気に入りました。

# 由来

infolinkはinfomationとlinkの造語です。情報をつなぐてきな意味だと読めるはず。コメントで指摘するのが情報と情報をつないだり、ショートカット的な感じかなと思ったのでこれにしました。あと、infoseekっていうのがあったので、あんまダサくないのかなっとも思ったので。まあ、infoseekは成功してないのでダサくないかはわからないけど。  
いい名前あったら教えてください。意味はそこまで重視してないので、かっこよければいいです。

パンダなのはオセロとか(ひっくり返る)、白と黒の比喩(間違いや正解)からです。オセロはのもう一つを置くのはinfolinkです！

# infolinkで、間違った情報を知る
infolink.devを使えば、間違いが指摘されたときに通知を受け取れます

infolink.devの詳細
https://zenn.dev/pandakun/articles/dc4886a996cb98

# 質問あればコメントに
Markdown貼り付けに対応しました！ infolink.dev

# 手順

https://www.youtube.com/watch?v=142mlg9wbVw

Markdownを張り付けて、htmlをコピーして、元のエディターにhtmlをペーストって感じです。

多少面倒です。すみません。技術的な問題で、エディターが別々になってしまいました(markdownに対応したckeditorは、アウトプットもMarkdownになってしまう。そして、markdownだと、変換する過程で表示がずれてしまう)。

せめて、同じページにしようと思ったのですが、競合が発生して出来ませんでした。

# infolinkとは？
この記事で詳しく書いてます。ざっくりいうと、間違いを指摘したりできるqiitaとかnoteみたいな奴です。間違いの基準とかもあるので、読んでみてください。指摘の通知も受け取れます。
https://zenn.dev/pandakun/articles/dc4886a996cb98

[infolink.dev](https://infolink.dev/)
[infolinkで投稿した記事](https://infolink.dev/userprofile/20)

Twitterアカウント
何か言いたいことがあれば、DMやリプで！(機能リクエストやバグ報告など、なんでも)
https://twitter.com/infolink_12_22
異様な書き方でプログラミング

異様な書き方でコラッツの問題を解くプログラムを書いてみる。

- `式1 if 条件 else 式2` 構文を使う。
- `式1`,`式2`は複数の式から構成されてもよい。ただし，
    - 全体を `( )` で囲む
    - それぞれの式は `,` で区切る
    - 関数の引用も式である
    - 代入文の場合はいわゆるセイウチ演算子 `:=` を使う
    - 実行される複数の式の結果をタプルとしてセイウチ演算子で捕捉しておくこともできる


```python
n = 976
oddcount, evencount = 0, 0
while n != 1:
    (junk1 := (print('n =', n, 'is even. =>', n//2), n := n//2, evencount := evencount + 1)) if n % 2 == 0 else (junk2 := (print('n =', n, 'is odd. =>', n*3 + 1), n := n*3 + 1, oddcount := oddcount + 1))
print('oddcount =', oddcount, 'evencount =', evencount)
print(junk1, junk2)
```

    n = 976 is even. => 488
    n = 488 is even. => 244
    n = 244 is even. => 122
    n = 122 is even. => 61
    n = 61 is odd. => 184
    n = 184 is even. => 92
    n = 92 is even. => 46
    n = 46 is even. => 23
    n = 23 is odd. => 70
    n = 70 is even. => 35
    n = 35 is odd. => 106
    n = 106 is even. => 53
    n = 53 is odd. => 160
    n = 160 is even. => 80
    n = 80 is even. => 40
    n = 40 is even. => 20
    n = 20 is even. => 10
    n = 10 is even. => 5
    n = 5 is odd. => 16
    n = 16 is even. => 8
    n = 8 is even. => 4
    n = 4 is even. => 2
    n = 2 is even. => 1
    oddcount = 5 evencount = 18
    (None, 1, 18) (None, 16, 5)


きったね～プログラムになった
他にも，もっと変なプログラムの書き方があるかなぁ
Ubuntu 22.04 でキー割り当てを変更する

## やり方
1. 割り当てを変更したいキーボードの、`Bus`, `Vendor`, `Product` 情報を取得する。
   ```shell
   $ cat /proc/bus/input/devices
   ```
   とすると、沢山デバイスが出力されるので、その中から対象となるキーボードを見つけて、その `I: ...` 行から、`Bus`, `Vendor`, `Product` の値を取得する。例えば、
   ```
   I: Bus=0011 Vendor=0001 Product=0001 Version=ab54
   ```
   なら、`Bus`, `Vendor`, `Product` はそれぞれ、`0011`, `0001`, `0001`
1. `/etc/udev/hwdb.d` に、適当な名前で、拡張子が `.hwdb` のファイルを作る。
   ```shell
   $ sudo /etc/udev/hwdb.d/touch mine.hwdb
   ```
1. そのファイルにキー割り当ての設定を書く。書き方は別途説明。
1. hwdb を更新してリロードする。
   ```shell
   $ udevadm hwdb --update                                                        
   $ sudo udevadm trigger
   ```

## hwdb ファイルの書き方

### 例
```shell
evdev:input:b0011v0001p0001*
 KEYBOARD_KEY_b8=enter
 KEYBOARD_KEY_b7=esc
```

### evdev 行
対象となるキーボードを指定する。

```
evdev:input:b0011v0001p0001*
```
のように、`b`の後に`Bus`の値、`v`の後に`Vendor`の値、`p`の後に`Product`の値を置く。
最後のアスタリスクは残す。

### KEYBOARD_KEY 行
キーの割り当てを指定する。

```
 KEYBOARD_KEY_b8=enter
```
は、`b8` のキーに `enter` を割り当てる

`enter` 等の割り当てるキーに対応する文字列は、[ここ](https://hal.freedesktop.org/quirk/quirk-keymap-list.txt) から見つける。

`b8` 等の割り当て先のキーのコードは、evtestをインストール・実行すると

```shell
$ sudo apt install evtest
$ sudo evtest
```

デバイスのリストが表示されるので、キーボードを選択して、キーを叩くと、こんなものが出力される。

```
Event: time 1704669406.921868, type 4 (EV_MSC), code 4 (MSC_SCAN), value b8
Event: time 1704669406.921868, type 1 (EV_KEY), code 28 (KEY_ENTER), value 0
Event: time 1704669406.921868, -------------- SYN_REPORT ------------
```

この 1 行目の value の値がキーコードになる。

## 参考にしたサイト
- https://qiita.com/HBenpitsu/items/4f5fabe9f73e0ab34174
- https://wiki.archlinux.jp/index.php/%E3%82%B9%E3%82%AD%E3%83%A3%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E3%82%AD%E3%83%BC%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AB%E3%83%9E%E3%83%83%E3%83%97
NestJSプロジェクト構築備忘録

# はじめに
プロジェクト作成時に諸々調べる時間を短縮するため、備忘録として残しておきます。

# プロジェクト作成
下記コマンドを実行し、プロジェクトを作成します。

```sh
docker run --rm -it -v $PWD:/app -w /app node:20-slim \
sh -c 'npm install -g npm && npm i -g @nestjs/cli && nest new --strict project-name'
```


nest newコマンドでプロジェクトを作成する際に、`--strict`オプションを入れないと、チェックがゆるいtsconfig.tsが生成されるようです。

https://ikmnjrd.github.io/blog/nestjs-why-disable-strict


パッケージマネージャーに何を使用するか聞かれます。
npmを選択し、プロジェクトを作成します。
```sh
? Which package manager would you ❤️  to use? npm
```


# Docker関連ファイル作成
プロジェクト作成後にできたプロジェクトルートフォルダに以下の構成でファイルを配置します。

```
プロジェクトルート
├─ .devcontainer
|  └─ devcontainer.json
├─ docker-compose.yml
└─ Dockerfile
```

プロジェクト作成時点で.prettierrcファイルが作成されるので、`prettier.configPath`は作成されたファイルに合わせます。
```json:.devcontainer.json
{
    "service": "nextjs-sample",
    "dockerComposeFile": "../docker-compose.yml",
    "workspaceFolder": "/workdir",
    "customizations": {
      "vscode": {
        "extensions": ["eamodio.gitlens", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode"],
        "settings": {
          "prettier.configPath": ".prettierrc",
          "editor.defaultFormatter": "esbenp.prettier-vscode",
          "editor.formatOnSave": true,
          "editor.codeActionsOnSave": {
            "source.fixAll.eslint": true
          },
          "editor.tabSize": 2
        }
      }
    }
}

```

```Dockerfile:Dockerfile
FROM node:20-slim

RUN apt-get update && apt-get install -y git vim locales-all

ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8

WORKDIR /workdir
```

フロントエンドのポートと被ることがあるため、ポートをデフォルトの3000から3001へ変更しています。
```yml:docker-compose.yml
version: '3.9'
services:
  input-attendance-backend:
    ports:
      - 3001:3001
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/workdir
    tty: true
```

main.tsのポートも忘れずに変更します。
```main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3001); // 3001に変更
}
bootstrap();
```

srcフォルダ配下のファイルに`@/*`の記載でアクセスできるようにtsconfig.jsonに以下を追加します。
```json:tscofig.json
{
  "compilerOptions": {
    ...
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}
```

また、相対インポートをエラーとしたいため、以下のルールを追加します。
```js:.eslintrc.js
module.exports = {
  ...
  rules: {
    ...
    '@typescript-eslint/no-restricted-imports': ['error', { patterns: ['./', '../'] }],
  },
};

```

自動作成されたファイルは相対インポートになっており、エラーとなるため解消してください。

例えばmain.tsは以下のように修正すればエラーは出なくなります。

```diff_typescript:main.ts
import { NestFactory } from '@nestjs/core';
- import { AppModule } from './app.module';
+ import { AppModule } from '@/app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3001);
}
bootstrap();
```

以上で完了です。
ベンチマークのスコアは、常に高ければ高いほど良いのでしょうか？


私の書籍やニュースレターを読まれている方なら、私がパフォーマンスエンジニアリングを支持していることをご存じかもしれません。パフォーマンスエンジニアリングとは、パフォーマンス作業を行う際、要件と制約を前もって明確にし、それらを満たすようにシステムを設計することをいいます。求められるもの以上に良く（もしくは悪く）システムを設計するのではなく、求められる仕様に忠実にシステムを設計するのがエンジニアリングです。求められるよりも 2 倍大きな箱を設計したとしても、顧客の棚にフィットせず、顧客が希望する倍のコストがかかり、構築に規定の倍の時間がかかるとしたら、それは「より良い」箱を設計したことにはなりません。間違った箱を設計しているのです。

あらゆる計算機システムには、性能要件があります。もしそうでなければ、世界が終わりを迎える寸前に仕事を終えるようなシステムですら、要件を満たすことになってしまいます。そのようなシステムにお金を払ってくれる顧客はいないでしょう（もしいたら、ぜひ紹介してください）。

では、性能要件として求められるレイテンシーやスループットを上回るのは、常に良いことと言えるでしょうか？ 1 秒間に 1,000 リクエスト処理できるより、1 秒間に 10,000 リクエスト処理できる方が常に良いのでしょうか？ ページの読み込みを 1 秒ではなく 0.5 秒で行えるのは？

たいていの場合、要件を上回るには制約を破るという代償を伴います。プログラミングには様々な制約があります。その中でも特に重要なのは時間とお金です。もちろん、制約を満たせるのであれば、要件を上回ることに通常問題はありません（ただし、顧客には確認した方が良いでしょう。例えば、2 倍速いシステムと 2 倍早く完成するシステムのどちらが良いかなど）。

要件を上回るのが有用かを判断する一番のコツは、分母と分子を反転させることです。例えば、1 秒あたりのリクエスト数ではなく、1 リクエストあたりの秒数で考えてみるのです。

## 実例：Puma

私は、Rack Web アプリケーションサーバーである Puma のプロジェクトメンテナーの一人です。私は、Puma に対し、すべてのリクエストに 1 ミリ秒以上のオーバーヘッドを追加してはならないという非公式な要件を設定しています。この要件は「ほとんどのアプリケーションはレスポンスを返すのに少なくとも 10 ミリ秒、通常は 100 ミリ秒以上かかる」という、HTTP ベースの Web アプリケーションへの私の理解から導き出したものです。つまり、ほとんどのアプリケーションで、Puma のオーバーヘッドをレスポンスタイム全体の 10％以下（通常は 1％以下）にするという要件です。私はこれを良い要件と感じています。もし、このオーバーヘッドを 1 ミリ秒から 0.1 ミリ秒に減らしたとしても、Puma を 10 ミリ秒以上の待ち時間がある HTTP アプリケーションに使っているユーザーにとって、それほど大きな違いはないでしょう。

しかしながら、Web サーバーでは、この要件の分母と分子を反転させ、レイテンシーではなくスループットをベンチマークとして使うのが一般的です。例えば、TechEmpower が測るのは「リクエスト/秒」という観点のベンチマークです。現在の Puma のスコアは、設定にもよりますが、10,000 ～ 15,000 リクエスト/秒となっています。

しかし、このベンチマークは、アプリケーションサーバーにとっては全く意味がありません。アプリケーションサーバーの仕事は、アプリケーションを提供することです。サーバーが 1 秒間に何回「hello world」を応答できるかは、アプリケーションサーバーの仕事にとって重要でしょうか？ そうしたベンチマークに使われる「アプリケーション」は、比較に意味がないほど、ユーザーが実際に行っていることとあまりにもかけ離れてしまっています。

リクエストごとに 0.5 ミリ秒のオーバーヘッドを追加する機能を Puma に追加するか検討しているとしましょう。現在のベンチマークを見ると、Puma は 10,000 リクエスト/秒、つまり 0.1 ミリ秒/リクエストの処理をしています。この機能をマージすると、スループットベンチマークは大幅に悪化し、新しい結果は 1666 リクエスト/秒となり、84％の減少となってしまいます。この機能はマージすべきでしょうか？

次のように考えてみてください。現在、実際の Puma アプリケーションの 99%は、アプリケーションの処理に 10 ミリ秒強費やしています。すると、この変更を入れると、99％の Puma ユーザーのアプリは 6％遅くなってしまうことになります。この機能にはそれだけの価値があるのでしょうか？ そうかもしれませんし、そうでないかもしれません。しかし、6％のパフォーマンスペナルティと引き換えにでも、私が Puma に組み込みたい機能や変更はたくさん考えられます！

ここでは、全てを左右しているのはフレームです。この機能を追加するということは、アプリケーションが約 2 ミリ秒以下でレスポンスを返す必要がある場合には Puma は使わないでくださいと言っていることになります。しかし、実際にその制約に引っかかる HTTP アプリケーションの数は、おそらくほとんどないはずです。

ともあれ、0.5 ミリ秒が重要になるシナリオやユースケースも確かに存在します。例えば、Puma が WebSocket のパフォーマンスを向上させたい場合には、アイドル接続のオーバーヘッドに注意する必要があります。アイドル接続に 0.5 ミリ秒のオーバーヘッドがあると、処理できる接続数に大きな影響を与えますし、Puma プロセスごとに 1,000 以上のアイドル接続があることは決して珍しくはありません。

アプリケーションの作者であるあなたは、そのアプリケーションに対するパフォーマンスとして何が期待されているかを誰よりもよく知っているはずです（そう望みます！）。スコアが高ければ高いほど良いという考えにはとらわれずに、どの程度のパフォーマンスで十分なのかを考えてみてください。

-Nate
Pythonで「辞書に含まれるすべてのキーと値を取得する」の動作を確認してみた

# 概要

Pythonで「辞書に含まれるすべてのキーと値を取得する」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/python/dictionary/index8.html

# 実装

以下のファイルを作成しました。
```sample.py
mydict = {"L":"Lemon", "O":"Orage", "G":"Grapes"}
print(mydict.keys())

mydict = {"L":"Lemon", "O":"Orage", "G":"Grapes"}
for mykey in mydict.keys():
    print(mykey)

mydict = {"L":"Lemon", "O":"Orage", "G":"Grapes"}
mylist = list(mydict.keys())
print(mylist)

mydict = {"L":"Lemon", "O":"Orage", "G":"Grapes"}
print(mydict.values())

mydict = {"L":"Lemon", "O":"Orage", "G":"Grapes"}
for myvalue in mydict.values():
    print(myvalue)

mydict = {"L":"Lemon", "O":"Orage", "G":"Grapes"}
mylist = list(mydict.values())
print(mylist)

mydict = {"L":"Lemon", "O":"Orage", "G":"Grapes"}
print(mydict.items())

mydict = {"L":"Lemon", "O":"Orage", "G":"Grapes"}
for mykey, myvalue in mydict.items():
    print("key:" + mykey + ", values:" + myvalue)

mydict = {"L":"Lemon", "O":"Orage", "G":"Grapes"}
mylist = list(mydict.items())
print(mylist)
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
dict_keys(['L', 'O', 'G'])
L
O
G
['L', 'O', 'G']
dict_values(['Lemon', 'Orage', 'Grapes'])
Lemon
Orage
Grapes
['Lemon', 'Orage', 'Grapes']
dict_items([('L', 'Lemon'), ('O', 'Orage'), ('G', 'Grapes')])
key:L, values:Lemon
key:O, values:Orage
key:G, values:Grapes
[('L', 'Lemon'), ('O', 'Orage'), ('G', 'Grapes')]
```

# まとめ

何かの役に立てばと。
std::functionを使った関数の利用

## std::functionとは
あらゆる関数ポインタ、関数オブジェクト、メンバ関数ポインタ、メンバ変数ポインタを保持できるテンプレートクラスです。これを使うことで柔軟で汎用的なコードを書くことが出来ます。


### ・functionの作り方
```C++:main.h
#include<functional>
class Input;

class Function
{
    //Updata関数で実行される関数を格納するfunction
    //引数なし
    std::function<void(void)>update_;
    //引数あり
    std::function<void(Input&)>update_;

    
    //functionと結び付けるupdate関数
    void NormalUpdate(void);
    void NormalUpdate(Input& input);
}
```

### ・functionと関数の結びつけ方
```C++:Function.cpp
void Function::Init(void)
{
    //std::bindを利用して関数とクラスのインスタンス（this）を
    //結び付けている。
    update_ = std::bind(&Function::NormalUpdate,this);

    //ラムダ式を利用して関数を結び付けている。
    update_ = [&](Input& input) 
    {
		NormalUpdate(input);
	};
}
```

### ・関数オブジェクトの実行の仕方
```C++:Function.cpp
void Function::Update(Input& input)
{
    //引数なしfunctionの実行
    update_();

    //引数ありfunctionの実行
    update_(input);
}
```

##
update_に結びついている関数を変更すれば、Update関数の中身を変更しなくともUpdateの動作を変更することができ、コードの柔軟性が向上します。
Google Search Consoleで何故かインデックスされないときの対応


人によって原因は違うでしょうが、手段のひとつとして記しておきます。

## 1. とりあえず操作画面を開く

<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649673/4ab30957-4d40-53c7-e2fb-a074d88446ec.png">

## 2. 左の「URL検査」をクリックするか、上の検索欄をクリックし、インデックスされていないURLを入力し、Enterを押す

<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649673/ea02514b-076d-9bbb-bdb6-913d3237d7de.png">

## 3. URL検査画面に遷移したら、「インデックス登録をリクエスト」をクリックする

<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649673/0dc2d1ad-8ee7-a372-ad3c-e184e83cad48.png">

## 4. 後はインデックスされるように神に祈る

一日ぐらいたったらインデックスされているでしょう。
多分。

## チラ裏

昔はこんなことしなくてもよかったんだけどなあ。
C++アプリケーションをWebアプリケーションに変換できますか？

![1_sH5T4A38EQtpmawo6FTRLw-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3486144/6ca1fb38-78e5-3aef-29e0-b728368ac6e6.png)
__2023年3月14日更新：Cheerp 3.0をリリースし、Apache 2.0ライセンスに変更しました！ [リリースノートはこちら](https://leaningtech.com/cheerp-3-0-the-most-advanced-c-compiler-for-the-web-now-permissively-licensed/)。__

C/C++で書かれた高性能なアプリケーションやライブラリをお持ちで、それをWebアプリにしてより多くの人に使ってもらいたいとお考えではありませんか？

最近まで、これは非常に難しく、JavaScriptでソフトウェアを完全に書き直す必要があったかもしれません。

しかし、Cheerpを使えば、ライブラリや完全なアプリケーションを含む既存のコードベースを自動的にHTML5に移植することができ、時間とコストを節約できます。

__Cheerpとは？__
Cheerpは、HTML5 Webアプリケーションのためのオープンソースの商用C/C++コンパイラで、[C/C++をWebAssembly、JavaScript、](https://leaningtech.com/cheerp/)またはその2つの組み合わせにコンパイルすることができます。

Cheerpは、C++コードをWebに導入するための最も先進的で柔軟なソリューションです。業界標準のClang/LLVMスタックをベースにしており、IDEや継続的インテグレーション環境に簡単に統合できるように、賢明なデフォルト、明確なエラーメッセージ、gccのようなコマンドラインオプションを備えた、堅牢なワークフローを提供します。

CheerpはWindows、macOS、Linux上で動作し、C++デベロッパーが選択したシステム上でシームレスにWebアプリケーションを作成することを可能にします。
![0_9W0pBdLUtluoF4dx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3486144/36728c90-8f75-3c26-1e75-e2b888dcd84b.png)
__Cheerpで何ができるの？__

Cheerpは、パワフルで、柔軟で、堅牢なツールです：

__既存のC++アプリケーションをWebアプリケーションに変換します：__ Cheerpは、どんな大規模なC++アプリケーションでもHTML5のWebアプリケーションに再コンパイルすることができます。これにより、コアビジネスロジックへの介入を最小限に抑えながら、クラウドに統合されたモダンなユーザー体験をユーザーに提供することができます。

C++のコードをコンパイルすることで、JavaScriptでアプリケーションをゼロから書き直す必要がなくなり、時間やリソース、2つのコードベースを並行して管理する手間を省くことができます。

__C++ライブラリをWebAssemblyにコンパイルし、HTML5アプリケーションに統合する：__一般的なルールとして、問題があれば、それを解決するC/C++ライブラリ（オープンソースまたはプロプライエタリ）があります。Cheerpの高度な相互運用性機能のおかげで、C/C++ライブラリのコンパイルとHTML5ウェブアプリへの統合はこれ以上ないほど簡単です。

__ネイティブC++ゲームをHTML5にコンパイル：__ Cheerpを使えば、コードを書き換えることなく、C++ゲームをウェブに素早く移植できます。最新のWebブラウザは、3Dグラフィックス(WebGLを通して)、プログラム可能なサウンドパイプライン(WebAudioを通して)、モーションセンサー(加速度センサーとGPS)を含む強力なゲームプラットフォームです。Cheerpを使えば、ゲーム全体を変換することも、ワンクリックで始められるプレイ可能なティーザートレーラーやデモを提供することもできます。

__Cheerpの仕組み__

Cheerpのワークフローは、通常次のようなものです：

1 - 既存のC/C++コードベースが、あなたの求める問題（例えば、エンコード/デコード、物理ライブラリ、またはあなたの分野に完全に特化した何か）を解決している。このコードベースをWebAssembly/JavaScriptに移植して、HTML5アプリケーションに統合することにしました。

2 - コードベースに目を通し、HTML5にエクスポートする必要がある関連APIにタグ一覧を付けます；

3 - Cheerpを使って、コードベースをWebAssemblyとJavaScriptにコンパイルします；

4 - .jsファイルと.wasmファイルを、HTML5アプリケーションの残りの部分と一緒にHTTPサーバーで提供します；

5 - コンポーネントの機能を変更または追加する必要がある場合は、C/C++ソースを編集します；

6 - ステップ3に戻る：コードをコンパイルし、それを提供し、反復する。

__なぜCheerpなのか？__

Cheerpは、その高度な相互運用性機能のおかげで、DOMやWebAPIやライブラリへのアクセスにおいてより柔軟性を保ちながら、Emscriptenよりもしばしば高速でサイズの小さいWebAssemblyコードを生成します。

Cheerpは、コンパイルからJavaScript、コンパイルからWebAssemblyへのソリューションで長年の経験を持ち、必要に応じてサポートや専門的なサービスを提供できる強力な技術チームを擁するLeaning Technologiesの支援を受け、積極的に開発されているプロジェクトです。

数百万行のコードでテストされ、多くの商用製品に選ばれているCheerpは、複雑で大規模なアプリケーションをWebアプリケーションに変換することを可能にする最高のテクノロジーです。

Cheerpが、既存のC++コードを活用し、プラグインやダウンロードを必要とせず、どんなデバイスでも動作するHTML5ウェブアプリケーションを開発するために、あなたの組織をどのように支援できるかについての詳細については、[ご連絡ください](https://leaningtech.com/contact-us/)。

https://leaningtech.com/legacy-modernisation-jp/

引用元：https://leaningtech.com/can-you-convert-c-applications-into-web-apps/
【LaTeX】tcolorboxでページ跨ぎ


# はじめに

先日（2023年1月7日），$\LaTeX$で文書を作成していると，tcolorboxでページを跨ぐとその後の文章が消えてしまうという事態が起きました．[奥村晴彦先生のQ&Aページ](https://okumuralab.org/tex/mod/forum/discuss.php?d=1633 "tcolorboxでページを跨ぐと，その後の文章が消えてしまう")などを参考に，tcolorboxの更新もやってみたのですが上手く行かず、、、
色々調べてみた結果，解決法が見つかったので，もし同じことで困った方がいれば参考にしてみてください．

# tcolorboxでのページ跨ぎ

結論：tcolorboxコマンドに`[enhanced,breakable=true]`を追記（注：プリアンブルに`\tcbuselibrary{breakable}`と書く必要あり）することで解決します．
```LaTeX:tcolorboxコマンド（ページ跨ぎ対応ver.）
\documentclass[dvipdfmx]{お好きな文書クラス}

%プリアンブル
\usepackage{tcolorbox}
\tcbuselibrary{breakable}

\begin{document}

%本文
\begin{tcolorbox}[enhanced,breakable=true]
ページを跨ぐような長い文章
\end{tcolorbox}

\end{document}
```

# tcolorboxについてはこちら

https://www.ctan.org/pkg/tcolorbox

# 参考文献

- 奥村晴彦，黒木裕介．[改訂第8版]$\LaTeX2\varepsilon$美文字作成入門．技術評論社，2020．
分野別記事一覧


> 目の前の何気ない事物を、あることもないこともできた偶然として発見するとき、人は驚きとともに「ありがたい」と感じる。「いま(present)」があるがままで「贈り物(present)」だと実感するのは、このような瞬間である。（森田真生『数学の贈り物』）

# プログラミング

## **Python**

### 数学

- [Processing のインストール手順](https://qiita.com/PRESENT_Science/items/122c43697bcb5f23a181)
- [再帰でフラクタルを描く①（フラクタルツリー）](https://qiita.com/PRESENT_Science/items/95caa05b7e73b5e32269)

### 自動処理

- [LINE Notify を使ってみよう](https://qiita.com/PRESENT_Science/items/49e89837d8f028965a19)

## ***LaTeX***

### 備忘録

- 2024/1/7 [tcolorboxでページ跨ぎ](https://qiita.com/PRESENT_Science/items/e74fa06065b0828e246f)
- 2024/1/27 [右寄せ・中央寄せ・左寄せが上手くいかない](https://qiita.com/PRESENT_Science/items/7805465a8d5fe25049f0)

# 高校数学

## 計算テクニック

- [部分分数分解の計算テクニック ヘビサイドのカバーアップ法（Heaviside cover-up method）](https://mathlog.info/articles/Le7OXtsu7kdmr6zMyXfh)

# 大学数学

# 高校物理学

# 物理学

## 力学

### 理論

### 演習

### 番外編

## 解析力学

### 理論

### 演習

### 番外編

## 力学的波動論

### 理論

### 演習

## 流体力学

### 理論

### 演習

### 番外編

- [オイラー方程式を用いないベルヌーイの定理の導出](https://mathlog.info/articles/G5dhmwiv8ZRNTF9JPM6X)

## 電磁気学

### 理論

### 演習

### 番外編

## 光学

### 理論

### 演習

- [円孔による回折](https://mathlog.info/articles/z0HxRulkIHQUuTfEPO3R)

### 番外編

## 熱力学

### 理論

### 演習

### 番外編

## 統計力学

### 理論

### 演習

### 番外編

## 量子力学

### 理論

### 演習

### 番外編

## 相対性理論

### 理論

### 演習

### 番外編

# 高校化学

## 理論化学

## 無機化学

## 有機化学

# 自由研究

- [単振り子の周期の厳密解](https://mathlog.info/articles/ZJvLGUrNhhe3EVmX2NrU)

# その他
【ラズパイ+ubuntu】sudoなしでadd_event_detectを使うとfailed to add edge detectionエラーが出るときの解決方法

お疲れ様です。秋並です。

ubuntuで `RPi.GPIO` の `add_event_detect` 関数をsudoなしで使うとエラーが出て実行できませんでした。
そこで、色々調べてみた結果、解決方法が見つかったので書き残しておきます。

## 実行環境
- Raspberry Pi 4B
- Ubuntu22.04

# グループの追加
gpioグループに[username]（[username]はご自身のユーザー名に置き換えてください）を追加します。

```bash
sudo groupadd -r gpio
```
```bash
sudo usermod -a -G gpio [username]
```

# udevルールの追加
udevルールファイルを作成します。
```bash
sudo nano /etc/udev/rules.d/99-gpiomem.rules 
```
以下の内容を記述します。
```
SUBSYSTEM=="bcm2835-gpiomem", KERNEL=="gpiomem", GROUP="gpio", MODE="0666"
SUBSYSTEM=="gpio", KERNEL=="gpiochip*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:gpio /sys/class/gpio/export /sys/class/gpio/unexport ; chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport'"
SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:gpio /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; chmod 666 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'"
```

<br>

内容を保存したら、ルールを適用します。
```bash
sudo udevadm control --reload-rules
```
```bash
sudo udevadm trigger
```
<br>

再起動すると、sudoなしでadd_event_detect関数を使えるようになります。
# 参考
[Python RuntimeError GPIO](https://copyprogramming.com/howto/python-runtimeerror-gpio)
2024/1/8主にITとかセキュリティの記事

クラウドに関する記事のまとめ(2023.12.25～2024.1.6）
https://blogs.itmedia.co.jp/business20/2024/01/20231225202416.html?ref=rss

ロシア軍ハッカー部隊が実行か
通信大手へのサイバー攻撃(1/4)
https://www.oita-press.co.jp/1002000000/2024/01/04/NP2024010401001539

意図しないオブジェクトのアップロードや変更を通知する方法、または防止する方法を教えてください(1/6)
https://dev.classmethod.jp/articles/tsnote-s3-event-modify-notifications/

LLM（大規模言語モデル）とは？仕組みから活用事例、今後の課題について解説(1/5)
https://xrcloud.jp/blog/articles/business/11753/

英国の新ノストラダムス、クレイグ・ハミルトン・パーカーが予言した2024年に起こりうる5つのこと(1/5)
https://karapaia.com/archives/52328512.html
関係データベース (RDB) で1つのフィールドに複数の値を入れたくなったとき

# 1.はじめに
こんにちは！Webエンジニアになりたくて勉強を始めた初学者です。
本記事では、RDBの構築時に1つのフィールドに複数の値を入れたくなったとき、どういった方法があるかを初心者目線でかみ砕いて記載します。

# 2.配列を入れたらダメなの？
例えば、商品に対するジャンル分けのデータベースを考えてみましょう。このとき、1つの商品が複数のジャンルを持つケースは容易に想像できると思います。
例：ドライヤーに対して、「家電」、「美容」といったジャンルを付与する

このとき、「ジャンル」というカラムを作って複数の値（配列）を入れる方法が考えられます。
この方法で対応できる場合もあるかもしれませんが、基本的には推奨されない方法です。
- 第1正規形の定義を満たさない
- 実際的には、クエリを工夫すれば疑似的な配列として利用できる場合があるが、クエリが複雑になるため可読性や保守性が損なわれてしまう

商品 | ジャンル
-- | --
ドライヤーA | 家電,美容

# 3.必要な分だけカラムを増やせばいい？
「ジャンルが2つあるのなら、カラムを2つ作ればいい」という考えもあるかもしれません。ジャンルの最大数が限られている場合はこの方法でもよいかもしれませんが、汎用性に課題があります。
- ジャンルの最大数を増やしたくなったら、その都度改修する必要がある
- ジャンルの最大数を増やすと、カラムが増える分だけクエリも長く複雑になってしまう


商品 | ジャンル1 | ジャンル2
-- | -- | --
ドライヤーA | 家電 | 美容

# 4.個別にレコードを作って対応する
最後に、レコードを増やすことで対応する方法を記載します。この方法では、商品とジャンルの関係1つ1つについてレコードを作成します。ジャンルの最大数に関係なくカラムは1つで済みます。
- 正規形の定義を満たす形でテーブルを作成できる
- ジャンルの最大数を増やしても改修する必要はない

商品 | ジャンル
-- | --
ドライヤーA | 家電
ドライヤーA | 美容

※同じ「商品」の別レコードを区別するためには、連番などのカラムを作っておいて複合主キーにすれば対応できる

記事は以上となります。
もし記事に誤りや、「こういう方法もある」などご意見がありましたら、コメントいただけますと幸いです。
X-NUCLEO-GFX01M1で温度計を作る(マクロ変換)(MCP9701)(STM32G071)(ILI9341)


x MCP9701-E/TO 販売コード 103199

x 過去ログを見よ　とりまarduinoのところにいろいろある

目的
テキストのテスト
A2に温度センサーを接続した。
(変換をマクロ化した。)(20240108)

![o_cop886.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a6bd743c-76d1-16c2-1351-47dfd080154e.jpeg)


```c++



//ili9341_mcp9701_071_2

//インクルド
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"


//100の割り算 0から30000までは、だいたい正しい   
#define DIV100(in) ((in*(65536/100*64+24))>>22)
//MCP9701の温度を求める x100
#define TMP(so) ((((so)*270769)-134432821)>>16)


//設定
#define TFT_RST 54 //A1
#define TFT_DC 3
#define TFT_CS 4

//液晶の定義
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);


//初期化
void setup() {

  //シリアルの初期化
  Serial.begin(9600);
  Serial.println("ILI9341 Test!"); 

  //液晶の初期化
  tft.begin();

  //画面のクリア
  tft.fillScreen(ILI9341_BLACK);
  
}//setup


//無限ループ
void loop(void) {


  //センサーの値を読み込む
  analogReadResolution(12); // ADC 12bit mode
  int s = analogRead(A2);   // センサーの読み取り値

  //センサーの値を温度に変換
  int t = TMP(s);
  int d1 = DIV100(t);
  int d01 = t - (d1 * 100);
  

  //温度の表示

  //クリア
  tft.fillRect( 0 ,0 , 24*5 , 24 , ILI9341_BLACK);

  //表示位置を0,0にする
  tft.setCursor(0, 0);

  //テキストの表示
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(3);
  tft.print(" ");
  tft.print(d1);
  tft.print(".");
  if( d01 >= 0 && d01 <= 9 ) { tft.print("0"); }
  tft.print(d01);
  tft.print(" ");
  
  delay(1000); //1秒待つ

}//loop


```
GitHubコミットをSlack通知する方法(Slack RSSアプリを使用する編)

# この記事は？
下記の投稿の続編です。

https://qiita.com/kamiryo/items/809702a00cc28d9a6049

第三者が運用しているGitHubレポジトリ※へのコミットをSlackワークスペースで各種更新の通知を受けるという要件を実現するための方法を調査・実装している。

※オープンソースソフトウェアのGitHubレポジトリなどを想定いただければ

上記記事では、実現方法としてSlackのGitHubアプリを利用した方法を紹介したが、残念ながら、すべてのPublicレポジトリに対応できない制約があることがわかっている。(詳細は上記の記事をご覧ください。)

今回の記事では、[SlackのRSSアプリ](https://slack.com/apps/A0F81R7U7-rss?tab=more_info)を利用し、SlackのGitHubアプリでは連携できないコミットを検知できるかを検証することを目的とします。

# 先に結論
Publicレポジトリであれば、atomフィード(RSS)を定期的にウォッチすれば、GitHubのアカウント不要でコミットの更新を確認できる。そこに、SlackのRSSアプリ(RSSエンドポイントをフェッチし更新を検知、差分内容をSlackへ投稿をしてくれるアプリ)を使うことで、第三者のPublicレポジトリの更新は検知できる。

# 環境
* Slackアプリ プロダクション 4.36.136 64-bit
* Windows 10
* GitHub（SaaS版であり、オンプレ版でも、 有償アカウントでもない）
* Slack (無料アカウント)

# RSSアプリでの連携
## 概要
SlackのワークスペースへRSSアプリを導入し、GitHubのatomフィード(RSS)を定期的に監視(フェッチ)させることで、特定のチャネルに投稿をされるようにする。

## 必要なもの
* Slackワークスペースへのappのインストール権限があるSlackアカウント

## インストール方法
* Slack(管理WEB画面操作)
    * `https://[ワークスペース名].slack.com/apps` にブラウザでアクセス
    * "RSS"で検索し、インストール

## 設定方法
* Slack管理WEB画面でRSSの設定画面を表示する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124955/47c3d302-69af-043e-749b-19df54ad4dbe.png)
* フィールドの追加よりフィードURLを入力する
対象レポジトリのブランチのコミット履歴のフィードにアクセスするには、以下の通り。
`https://github.com/{user}/{repository}/commits/{branch}.atom`
* チャネルへの投稿を入力する
上記フィードの更新を検知した際に、このチャネルに投稿されます。

## 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124955/439e3d9d-287e-03b1-de14-0387c9664441.png)

※参考に書かせていただいた記事にもありますが、RSSが更新後Slack側がフェッチした後にSlackに通知がされますので、若干タイムラグがありました。(15-20分程度は最大かかりそうです)

## まとめ
本記事の手順を行うことで、対象レポジトリに対して権限を有するGitHubアカウントを所有していなくても、レポジトリのURLのみを知っていれば、Slackでコミットの更新を定期的に自動で検知できる仕組みを実現することができました。

めでたしめでたし。

# 参考
atomフィードは色々ある模様です。

https://qiita.com/sawanoboly/items/eddc1e230657184d5121

Slack RSSアプリの仕様を調べてくださっている方がいました。

https://cartman0.hatenablog.com/entry/2017/10/17/Slack_RSS_integrations_%E3%81%AEfetching%28polling%29%E3%81%AE%E4%BB%95%E6%A7%98_%28About_specifications_of_fetching%28polling%29_in_Slack_RSS_integrations%29#google_vignette
100の割り算　割られる数が30000ぐらいまで正しい

目的
温度センサーの計算
MCP9701
温度センサーの最大で約150℃
x100倍で15000

オンラインコンパイラーを使用

```c++


#include <stdio.h>
int main(void){
    // Your code here!

//100の割り算 0から30000までは、だいたい正しい   
#define DIV100(in) ((in*(65536/100*64+24))>>22)

    int in = 30000;
    
    printf("%d %d",in,DIV100(in));
    
    
}


```


```

30000 300


```
「カムイチェㇷ゚ アン クスケライ アオカイ シㇰヌアン ペ ネ」のアオカイは代名詞なのか

「カムイチェㇷ゚ アン クスケライ アオカイ シㇰヌアン ペ ネ」という文を[見かけた](https://qiita.com/maskot1977/items/98e36df29cf1ff3fd99c)のだが、このアオカイが代名詞なのか気になった。代名詞だとすると、Universal Dependenciesで書くなら、こうなる。

```
# text = カムイチェㇷ゚ アン クスケライ アオカイ シㇰヌアン ペ ネ
1	カムイ	kamuy	NOUN	名詞	_	2	nmod	_	SpaceAfter=No
2	チェㇷ゚	cep	NOUN	名詞	_	3	nsubj	_	_
3	アン	an	VERB	自動詞	_	7	advcl	_	_
4	クス	kusu	SCONJ	接続詞	_	3	mark	_	SpaceAfter=No
5	ケライ	keray	ADV	副詞	_	7	advmod	_	_
6	アオカイ	aoká	PRON	代名詞	_	7	nsubj	_	_
7	シㇰヌ	siknu	VERB	自動詞	_	9	acl	_	SpaceAfter=No
8	アン	=an	PART	人称接辞	_	7	expl	_	_
9	ペ	pe	NOUN	形式名詞	_	0	root	_	_
10	ネ	ne	AUX	デアル動詞	_	9	cop	_	_
```

アイヌ語UDエディターで可視化すると、[こんな感じ](https://koichiyasuoka.github.io/UD-Ainu/editor/editor-ain.html#%23%20text%20%3D%20%E3%82%AB%E3%83%A0%E3%82%A4%E3%83%81%E3%82%A7%E3%87%B7%E3%82%9A%20%E3%82%A2%E3%83%B3%20%E3%82%AF%E3%82%B9%E3%82%B1%E3%83%A9%E3%82%A4%20%E3%82%A2%E3%82%AA%E3%82%AB%E3%82%A4%20%E3%82%B7%E3%87%B0%E3%83%8C%E3%82%A2%E3%83%B3%20%E3%83%9A%20%E3%83%8D%0A1%09%E3%82%AB%E3%83%A0%E3%82%A4%09kamuy%09NOUN%09%E5%90%8D%E8%A9%9E%09_%092%09nmod%09_%09SpaceAfter%3DNo%0A2%09%E3%83%81%E3%82%A7%E3%87%B7%E3%82%9A%09cep%09NOUN%09%E5%90%8D%E8%A9%9E%09_%093%09nsubj%09_%09_%0A3%09%E3%82%A2%E3%83%B3%09an%09VERB%09%E8%87%AA%E5%8B%95%E8%A9%9E%09_%097%09advcl%09_%09_%0A4%09%E3%82%AF%E3%82%B9%09kusu%09SCONJ%09%E6%8E%A5%E7%B6%9A%E8%A9%9E%09_%093%09mark%09_%09SpaceAfter%3DNo%0A5%09%E3%82%B1%E3%83%A9%E3%82%A4%09keray%09ADV%09%E5%89%AF%E8%A9%9E%09_%097%09advmod%09_%09_%0A6%09%E3%82%A2%E3%82%AA%E3%82%AB%E3%82%A4%09aok%C3%A1%09PRON%09%E4%BB%A3%E5%90%8D%E8%A9%9E%09_%097%09nsubj%09_%09_%0A7%09%E3%82%B7%E3%87%B0%E3%83%8C%09siknu%09VERB%09%E8%87%AA%E5%8B%95%E8%A9%9E%09_%099%09acl%09_%09SpaceAfter%3DNo%0A8%09%E3%82%A2%E3%83%B3%09%3Dan%09PART%09%E4%BA%BA%E7%A7%B0%E6%8E%A5%E8%BE%9E%09_%097%09expl%09_%09_%0A9%09%E3%83%9A%09pe%09NOUN%09%E5%BD%A2%E5%BC%8F%E5%90%8D%E8%A9%9E%09_%090%09root%09_%09_%0A10%09%E3%83%8D%09ne%09AUX%09%E3%83%87%E3%82%A2%E3%83%AB%E5%8B%95%E8%A9%9E%09_%099%09cop%09_%09SpaceAfter%3DNo%0A%0A)。もし、このオカイが動詞だとすると、普通はa=okayじゃなくてokay=anになるはずだから、まあ、[幌別方言のaokay](https://www.ff-ainu.or.jp/web/potal_site/files/horobetsu_tyukyu.pdf#page=46)だと考えていいのかな。

![ain.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428317/c5c49e76-e37a-345c-baf7-0ec4c75e0fbf.png)
なんちゃってスクラムを導入してかなり恩恵を受けたのでふりかえりをしてみた

## はじめに

**前職の株式会社Zuuでの話です。また個人の見解です。**

現在とある金融系Webメディアを運営する会社で、新卒二年目のフルスタックエンジニアとして保守運用をしています。

今回は未熟なエンジニアが自チームにスクラムを導入して半年程経ち、なんちゃってスクラムながらかなり恩恵を受けることができたので、ふりかえりの意味を込めてまとめました。

## スクラム導入の背景

今年の4月から異動になった新チームでは、過度な残業時間が日常化しており、常に炎上していることが課題となっていました。

ボトルネックとして、工数見積もりの精度の低さ、実績工数の管理の甘さ、タスク漏れから精度の高い工数の見積もりやプロジェクトのプロセスを進められないことにありました。

そのためチームワークの促進、心理的安全性の改善、工数やタスクの見える化の改善を行う必要がありました。

そこでアジャイルで有名なフレームワークであるスクラム開発を採用することで、正常な開発プロセスを踏めるのでないかと思い導入を決めました。

## 導入プロセス

### キャッチアップ

以下の本やUdemyでインプットを行い、また勉強会に参加し現役のスクラムマスターからアドバイスをもらうなどをしてキャッチアップを進めました。

本

- [いちばんやさしいアジャイル開発の教本](https://amzn.to/4aob5Dh)
- [アジャイルサムライ――達人開発者への道](https://amzn.to/3Tr6ZnU)
- [SCRUM BOOT CAMP THE BOOK](https://amzn.to/41pgbv2)

Udemy

- [【アジャイル開発】スクラム基礎講座](https://www.udemy.com/course/scrum-course-japanese/)
- [現役アジャイルコーチが教える！たった1日で理解できるアジャイル開発とスクラム 導入と実践、組織変革編](https://www.udemy.com/course/daipresents-advanced-agile/)

勉強会

- [スクラム実験室](https://scrum-jikken.connpass.com/)
- [Scrum Masters Night!](https://smn.connpass.com/)

### チームメンバーの同意を得る

定期的にアジャイルやスクラムについての勉強会を開催することで、メリットとデメリットなどを共有することやどれだけ本気でやっているか熱意を伝えることで同意を得ることができました。

また、ドラッガー風エクササイズやインセプションデッキなどチームビルディングを行うことで、徐々に取り入れて行きました。

### ロールの準備

スクラム開発では、プロダクトオーナー、開発チーム、スクラムマスターの3つの役割があるため、他のメンバーに協力してもらう必要がありました。

プロダクトオーナーには、ディレクターとして兼任しているチームリーダーに担当してもらいました。

スクラムマスターには、前チームのリーダーに担当してもらいました。（工数などの兼ね合いから最初の二ヶ月のみ参加してもらいました。）

### スクラム導入！！！

スクラム導入の準備が完了したので、いよいよスクラムの開始です！

以下のイベントを一週間のスプリントで行いました。
ビジネスサイドを巻き込むことができなかったため、スプリントレビューは行っていません。

- スプリントプランニング
- デイリースクラム
- 見積もり
- スプリントレトロスペクティブ

また、タスク管理の不透明性が課題だったため、このタイミングでNukabのバックログタスク管理ツールの統一を行いました。

## 成果

### リリーススケジュールの安定

計画作りを徹底して行うことで差し込み案件や障害などの突然発生するタスクが発生しても、リリースの見通し立てることができるなど、安定したリリーススケジュールを運用することができました。

### メンバーのタスクの進捗の可視化

タスク管理ツールのバックログに統一したことやスプリントプランニングでタスクの分割を徹底して行うことで、進捗の把握やタスク漏れなど改善することができました。

### タスクの見積もりの精度の向上

チームメンバー全員で見積もりを行うことで、別メンバーが担当するタスクの要件理解の推進やタスク背景の共有を行うことで精度の高い見積もりを行うことができました。

## できたこととできなかったこと

### できたこと

- ペアプロ文化の促進
- テスト駆動開発など新しい挑戦
- チームメンバー全員で行う精度の高い見積もり
- スプリントプランニングによるリリーススケジュールの計画
- スプリントレトロスペクティブから週次のふりかえり文化の定着

#### なぜできたのか？

スクラムの定義しているイベントを運用することで、アジャイルで重要とされているイベントを暗黙的に運用することができた!

心理的安全性の確保やふりかえりを行うことで新しい挑戦やチームの課題について、共有する機会を増やすことができた!

開発フローの見直しや別メンバーの抱えているタスクに興味を持つ習慣ができ、チームワーク力を向上することができた！

### できなかったこと

- ベロシティの運用
- ストーリーポイントを用いた見積もり
- スプリントゴールの設定
- ビジネスサイドを巻き込むこと
- スプリントレビューによるフィードバック
- リソース効率よりフロー効率を意識した開発プロセス

#### なぜできなかったのか？

差し込み案件が多いプロジェクトにそもそもスクラム開発が向いていない。。。

自分がスクラムマスターの役割をしているのにも関わらず、ビジネス的視座が足りていない。。。

ビジネスサイドの同意を得ていない状態で始めたことやエンジニアとビジネスサイドの連携不足により、短期的な目標を共有することができていない。。。

## 今後やっていきたいこと

### [ハピネスチームビルディング](https://qiita.com/kojimadev/items/4b28f801863cf4e8f0da)

マネジメントからだけではなく、チーム文化などの環境を強化することで生産性の向上に貢献したい!

### ビジネスサイドを巻き込んだアジャイル開発

ビジネスサイドとより近い位置でアジャイル開発を促進し、プロダクト価値を最大化する仕組みを作りたい！

### 脱スクラム開発

自分が担当しているプロジェクトは保守・運用のため、差し込み案件が多いことや最終ゴールが決まっているスクラム開発と相性が悪いです。

自分のチームにより適したアジャイル開発のプロジェクトを運用したい！

## まとめ

なんちゃってアジャイル開発状態からスクラム開発を導入することで、チームとしての生産性を改善できたと思います。
チームメンバーもスクラム導入に対して前向きに取り組んでくれたおかげで自分にはない経験則から支えてもらったおかげで失敗に終えることなくできたと思います。
また、この経験から挑戦することの大切さやマネジメントを経験することができ、大きく成長することができました。
来年も新しいことを挑戦して今年に負けないくらいの成果を生み出したいと思います！
archiveページをACFの為に固定ページにする際に詰まった点

WordPressを使用してarchiveページにAdvanced Custom Fields（ACF）で画像を管理画面から登録できるようにしようとした際、固定ページに変更する過程で詰まった点です。

## 踏んだ手順
・ファイル名をarchive-○○○.php→page-○○○.phpに変更
・管理画面から新しい固定ページを作成
・ACFで使用したい画像のカスタムフィールドを適用するページとして、新しく作成した固定ページを選択
・表側ページarchiveから固定ページに変更したページを開いても画面が真っ白になって開かなかった

## 原因
functions.phpで今回のカスタム投稿タイプの設定についての記述の中の
「has_archive => true」
によって固定ページで設定していたスラッグ名とバッティングしてしまい、ページが正常に表示されていなかったため。
```ruby:functions.php
  register_post_type(
    'news',
    array(
      'label' => 'ニュース',
      'public' => true,
      'has_archive' => true,
      'show_in_rest' => true,
      'menu_position' => 5,
      'supports' => array(
        'title',
        'editor',
        'thumbnail',
        'revisions',
      ),
    )
  );
```

## 対策
「has_archive」をfalseにする、もしくは異なるスラッグを使用することで解決。
Python×SeleniumでWebブラウザ操作を自動化

<h1>はじめてPythonでSeleniumを使うにあたって</h1>
環境構築の備忘録として。
2024-01-07(日)
<h1>１.ChromeのバージョンとWebDriverのバージョン</h1>
<p>Chromeのバージョン120.0.6099.199に対応するWebDriverは、ChromeDriverの公式ダウンロードページから<a href="https://chromedriver.chromium.org/downloads">ダウンロード</a>できます。</p>
<p>ただし、バージョン115以降のChrome用WebDriverのダウンロード方法が変わりました。</p>
<p>具体的な手順は以下の通りです。</p>
<p>ChromeDriverの公式<a href="https://chromedriver.chromium.org/downloads">ダウンロードページ</a>を開きます。</p>
「<a href="https://googlechromelabs.github.io/chrome-for-testing/">Current Releases</a>」のセクションを見て、自分のChromeのバージョンに対応するChromeDriverを探します。
対応するChromeDriverのリンクをクリックしてダウンロードします。

<h1>2.Chromeのバージョンの"Status"が❌の場合</h1>
例
<p>Channel | Version | Revision | Status</p>
<p>Stable (upcoming) | 120.0.6099.199 | r1217362 | ❌</p>
「Stable (upcoming)」のセクションに表示されているChromeDriverは、まだ正式リリースされていないバージョンを指します。そのため、安定性や互換性に問題がある可能性があります。

Chromeバージョン120.0.6099.199に対応するChromeDriverがまだStable版としてリリースされていない場合、以下の選択肢が考えられます：

Beta版またはDev版のChromeDriverを使用する：これらのバージョンは、まだ完全にテストされていない可能性がありますが、最新のChromeバージョンをサポートしている可能性があります。
Chromeのバージョンをダウングレードする：Chromeのバージョンをダウングレードして、既にリリースされているChromeDriverと互換性のあるバージョンにすることも可能です。

<h1>3.PCのモデルに対応したアーキテクチャを選ぶ</h1>
🍎マーク「このMacについて」でモデルを確認

Macを使用している場合、選択するべきChromeDriverはMacのアーキテクチャ（ARM64またはx64）によります。以下の2つの選択肢があります：

Mac ARM64：新しいApple Silicon（M1チップなど）を搭載したMacを使用している場合、mac-arm64のバージョンのChromeDriverを選択します。具体的には、以下のURLからダウンロードできます：
https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/121.0.6167.47/mac-arm64/chromedriver-mac-arm64.zip

Mac x64：Intelチップを搭載したMacを使用している場合、mac-x64のバージョンのChromeDriverを選択します。具体的には、以下のURLからダウンロードできます：
https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/121.0.6167.47/mac-x64/chromedriver-mac-x64.zip

<h1>4.ダウンロード後</h1>
ダウンロードしたchromedriverファイルを/usr/local/binディレクトリに移動することで、システム全体で利用できるようになります。

具体的な手順は以下の通りです：

ターミナルを開きます。
cdコマンドを使用して、chromedriverファイルがダウンロードされたディレクトリ（通常はダウンロードフォルダ）に移動します。例えば、cd ~/Downloadsと入力します。
mv chromedriver /usr/local/binというコマンドを実行します。これにより、chromedriverファイルが/usr/local/binディレクトリに移動します。
以上の手順により、chromedriverはシステムのパスに含まれ、どのディレクトリからでもアクセスできるようになります。これにより、Seleniumなどのスクリプトからchromedriverを直接呼び出すことができます。

<h1>5.最後に</h1>
<p>from selenium import webdriver</p>
driver = webdriver.Chrome()

この手順により、ダウンロードしたChromeDriverをシステム全体で利用できるようになります。それぞれのスクリプトでChromeDriverのパスを指定する必要がなくなります
JetpackComposeのWebViewで上部に読み込みインジケータを表示する

# はじめに
今回はJetpackComposeのWebViewで上部に読み込みインジケータを表示する方法を紹介していきます
### 本文
Composebale関数内で下記の処理を記述します
newProgressは1から100で帰ってきますがProgressIndicatorは0から1で表示するので
渡す場合は100で割らないとずっと読み込み完了のままインジケータが進みません
```kotlin
val isLoading = remember { mutableStateOf(true) } 
val currentProgress = remember { mutableStateOf(0f) }

val webChromeClient = object : AccompanistWebChromeClient() {
    override fun onProgressChanged(view: WebView?, newProgress: Int) {
        super.onProgressChanged(view, newProgress)
        currentProgress.value = newProgress.toFloat() / 100f
        isLoading.value = newProgress < 100
    }
}

if (isLoading.value) {
    LinearProgressIndicator(
        progress =  currentProgress.value,
        modifier = Modifier.fillMaxWidth(),
    )
}
```
### 最後に
昔はAndroidViewで書いていたWebViewも公式から出てくるようになり色々実装できるようになったので備忘録として今回の記事を書きました
どなたかのお役に立てれば幸いです
vite v4.5.1 building for production...が出た場合の対処法

## 概要
- laravel + Vueで作成中のアプリをbuildしたところエラーが出てしまった。
- 対処法を忘れないうちに簡単にまとめておく

## エラー内容
```sh:err
root@bf2e0773ce1f:/var/www/html# npm run build

> build
> vite build

vite v4.5.1 building for production...
✓ 135 modules transformed.
warnings when minifying css:
▲ [WARNING] A nested style rule cannot start with "a" because it looks like the start of a declaration [css-syntax-error]

    <stdin>:35:0:
      35 │ a[data-v-4e3ad3a9] {
         │ ^
         ╵ :is(a)

  To start a nested style rule with an identifier, you need to wrap the identifier in ":is(...)" to prevent the rule from being parsed as a declaration.


public/build/manifest.json              0.42 kB │ gzip:  0.17 kB
public/build/assets/app-5c5a93ca.css    2.03 kB │ gzip:  0.80 kB
public/build/assets/app-041e359a.css  225.70 kB │ gzip: 30.76 kB
public/build/assets/app-d8199b45.js   278.03 kB │ gzip: 97.43 kB
```
## 解決法
cssの`a`タグの書き方が違うと怒っている。
今回の場合、`scss`で書いているvueファイルがあったが、scssの指定が漏れてしまっていた。
<b>scssを利用するには、cssとは違い言語の指定を忘れてはいけないようだ。</b>
```vue
- <style scoped>
+ <style scoped lang="scss">
```
IssueHunt株式会社のやられサイトをWindows上に構築してみた

# 【やられサイトの目的】
俗に言う、`Offensive-Security`というやつです。

[IssueHunt株式会社 【プレスリリース】バグバウンティ・プラットフォームや、プロダクトセキュリティ支援サービスを提供するIssueHunt株式会社が脆弱性診断実践用プログラム「Kowaseru」をオープンソースで公開](https://prtimes.jp/main/html/rd/p/000000055.000039740.html)
>セキュリティ対策を始める際、「守る」にはまず「攻める」方法を知る必要があります。
>そこで、バグバウンティ・プラットフォームをはじめとした様々なソフトウェアを完全内製開発している当社が、攻撃者の目線に立った脆弱性診断を実践できる「Kowaseru」をオープンソースで公開いたしました。
>基本的な脆弱性が含まれておりますので、脆弱性診断の実践練習やセキュリティ教育の一つのコンテンツとしてご活用ください。

# 【構築環境】
Windows 10 Pro 22H2 64bit
Core i3
RAM 12GB

# 【Windows環境で構築する前にインストールしたソフトウェア】
[Gitbash](https://gitforwindows.org/)
[Node.js](https://nodejs.org/en)
[Docker Desktop](https://docs.docker.com/desktop/install/windows-install/)

:::note warn
注意
インストール中に"Windowsセキュリティの重要な警告"のポップアップが出た場合は、"アクセスを許可する"を押す
:::

# 【構築概要】
`Github`の[readme.md](https://github.com/IssueHunt/Kowaseru)を参考にしました。

# 【手順】

###### ⓪Gitbashでリポジトリをcloneする

```
git clone https://github.com/IssueHunt/Kowaseru.git
```

指定が無ければ、`C:\Users\ユーザー名\Kowaseru`にリポジトリが`clone`される
###### ①DBの準備
`Gitbash`でKowaseruディレクトリに移動
```
cd Kowaseru
```
Dockerイメージ/コンテナの作成
```
docker-compose up -d
```

###### ②Kowaseruディレクトリ内に以下の内容で.envファイルを作成する

```
BASE_URL=http://localhost
PORT=4000
DB_HOST=localhost
DB_PORT=5432
DB_USER=root
DB_PASSWORD=root
DB_NAME=kowaseru
SESSION_SECRET=
```

:::note
SESSION_SECRETの値には以下の実行結果を代入する
```
openssl rand -hex 32
```
:::

###### ③パッケージのインストール
コマンドプロンプトを立ち上げKowaseruディレクトリに移動
```
cd Kowaseru
```
パッケージをインストールするコマンドを実行
```
npm i
```

###### ④DBのマイグレーション
```
npm run migration:up
```
###### ⑤サーバーの実行
```
npm start
```
実行後
```
C:\Users\ユーザー名\Kowaseru>npm start

> kowaseru-server@0.0.1 start
> env-cmd -f .env tsx src/entry.ts

Listening... http://localhost:4000
```
と、`4000ポート`でリッスン中の表示が出る
# 【やられサイトの環境を実行】
ブラウザのアドレスバーに入力
```
http://localhost:4000
```
以下の画面が表示すると成功
![kowaseru.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630154/d7a977cd-1648-3358-52cf-791ffbcdbddb.png)


# 【おわり】
敷居が高いイメージだったが、やってみると意外と簡単に構築できた。
`Kali Linux`から攻撃して遊びたいので、BASE_URLには固定IPアドレスを指定している。

**Let's enjoy Pentesting :)**
Raspberry Pi 4Bと時雨堂のmomo（3）

# 1. はじめに
以下でAyame Laboにサインインなしで動作確認できた。次はサインインして使ってみる。

https://qiita.com/tetsuoMikami/items/bbf6102d8306b348e0a0

# 2. Ayame Labo
Ayame Laboにサインインする。GitHubアカウントを持っていると瞬時に終わる。

https://ayame-labo.shiguredo.app/

上記にアクセスして、「GitHub アカウントでサインイン(または新規サインアップ)する」を選択して、GitHubのアカウントでサインインする。GitHubは有名なので割愛。

おとなしく同意する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865486/5c0eeec6-40ae-abf2-8c0d-a9ea5baf0025.png)

# 3. 使ってみる

ドキュメント: https://github.com/shiguredo/ayame-labo-doc
によると「ルーム認証用のルーム ID とシグナリングキーを埋め込んであるサンプル」があるのでそれを使ってみる。以下をルームIDとして使う。ドキュメントにはayame-laboとあったが、受信専用を開くと「-sample」がついているルームIDが指定されている。

```
＜GitHubのアカウント＞@ayame-labo-sample
```

シグナリングURLはサインインなしと変わらないらしい。シグナリングキーはダッシュボードにある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865486/33e5a8c5-0998-be62-bbe3-875847c6834b.png)

Raspberry Piで以下のコマンド実行すると配信開始。
```
./momo --no-audio-device --resolution HD --framerate 30 --fixed-resolution ayame --signaling-url wss://ayame-labo.shiguredo.app/signaling --room-id ＜GitHubアカウント＞@ayame-labo-sample --signaling-key ＜ダッシュボードからコピーしたシグナリングキー＞
```

シグナリングキー設定済みのサンプルの「受信のみ」から飛ぶと映像が見れるページに行ける。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865486/9a69ab70-ea29-f353-fd4f-463c35e2cf60.png)

# 4. その他
ダッシュボードに接続ログが出ていた。一回の「接続」押しで1回というわけではないということが分かった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865486/ed2db768-9ca1-d04f-9aae-7b92404f9dde.png)

# 5. 今後
Laboを使いこなしてから自力でAyameサーバー立てたい。
【JavaScript】ローカルストレージへ値を保存・取得・削除する方法


## 保存

```js
localStorage.setItem('key', 'value')
```

## 取得

```js
localStorage.getItem('key')
```

## 削除

```js
localStorage.removeItem('key')
```

全て削除

```js
localStorage.clear()
```

## keyが存在するか

```js
localStorage.hasOwnProperty("key")
```
【AWS】Lambdaで署名付きURLを作成する実装例【署名付きURL】

## はじめに
以前APIGatewayとLambdaの連携についての記事を投稿しましたが、この構成の使用例として、Lambda関数でのS3ファイルの署名付きURLを生成して返す実装について投稿します。

[APIGateWayとLambdaの連携についての記事]
https://qiita.com/Nana_777/items/0ce03f59045aa04401bc

## 署名付きURLを利用するメリット
### 一時的なアクセス制御
署名付きURLは有効期限を持ち、期限が切れるとアクセスが拒否されます。これにより、一時的にアクセスが必要な場合に、不要にアクセス権を与え続けることを避けることができます。

### 簡単なアクセス管理
署名付きURLを使用することで、AWS Identity and Access Management (IAM) ポリシーの設定が簡略化されます。特定のS3オブジェクトに対するアクセス許可を一時的に発行でき、必要がなくなれば署名付きURLを無効にできます。

### 安全なデータ転送
署名付きURLはHTTPSプロトコルを使用して生成され、データの転送が暗号化されます。これにより、データの安全な伝送が確保されます。

### プリサインドURLの生成
プリサインドURLは、あらかじめ生成して署名を付けたURLです。これにより、ユーザーによる要求があった場合に即座に署名付きURLを提供することができます。

### クエリパラメータでの制御
署名付きURLは、クエリストリングの一部として署名情報を含むため、アクセス時の要件をクエリパラメータで指定することができます。例えば、特定のIPアドレスからのアクセスのみを許可するといった柔軟なアクセス制御が可能です。

## アーキテクチャ図
![署名付きURL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192949/120bfa0f-64b8-b8b2-7af4-e758852077e3.png)


## 構築手順
### 1．Lambda関数の実装
#### ①Lambda関数を作成する
- 前回の記事では固定のレスポンスを返すだけでしたが、今回のコード例ではLambda内で署名URLを発行してレスポンスとして返します。
- 以下の例ではWebAppから「ファイル名」をAPIGatewayのパラメータ経由で取得し、Lambda関数で署名付きURLを発行した後、それをレスポンスとして返しています。
- S3のバケット名とフォルダ名は環境変数に設定してそれを取得するようにしています。
- generate_presigned_url メソッドを呼び出すことで署名付きURLを発行しています。

<コード例>
```python:sample.py
import os
import boto3
import json

# Lambdaの環境変数からフォルダ名とバケット名を取得
folder_name = os.environ['FOLDER_NAME']
bucket_name = os.environ['BUCKET_NAME']

def lambda_handler(event, context):
    # API Gatewayからのクエリストリングパラメータ取得
    file_name = event['queryStringParameters']['fileName']

    # 署名付きURLの有効期限（秒）
    expiration_time = 60 * 60  # 1時間

    # AWS SDKの設定
    s3 = boto3.client('s3')

    # フォルダ名とファイル名を組み合わせてオブジェクトキーを生成
    object_key = f'{folder_name}/{file_name}'

    try:
        # 署名付きURLの生成
        signed_url = s3.generate_presigned_url(
            ClientMethod = 'get_object',
            Params = {'Bucket' : bucket_name, 'Key' : object_key},
            ExpiresIn = expiration_time,
            HttpMethod = 'GET'
            )
        return {
            'statusCode': 200,
            'body': json.dumps({'signedUrl': signed_url})
        }
    except Exception as e:
        print('Error generating signed URL:', e)
        return {
            'statusCode': 500,
            'body': json.dumps({'error': 'Internal Server Error'})
        }

```
### 2．API Gatewayの設定
※こちらは前回の記事を参照してください
https://qiita.com/Nana_777/items/0ce03f59045aa04401bc


## 署名URL生成(getSignedUrlPromise)メソッドのパラメータ説明

|パラメータ  |説明  |
|---|---|
|ClientMethod|文字列, 必須。署名付きURLを生成する対象のS3操作を指定します。例えば、'get_object'や'put_object'などがあります。|
|Params|辞書, オプション。S3操作に必要なパラメータを指定します。この辞書には、バケット名 (Bucket)、オブジェクトキー (Key)、およびその他の必要なパラメータが含まれます。|
|ExpiresIn|数値, オプション。署名付きURLの有効期限を秒単位で指定します。デフォルトは3600秒（1時間）です。有効期限が切れると、そのURLはアクセスできなくなります。|
|HttpMethod|文字列, オプション。HTTPメソッドを指定します。例えば、'GET'や'PUT'などがあります。デフォルトはNoneで、メソッドはClientMethodに基づいて選択されます。|
TryHackMeのVPN接続でエラー

## 事象
TryHackMeへVPN接続時にエラーが出る

## 原因
VPN接続できない原因は接続先のVPNサーバー
EU-Regular-3はバグがあるようで他の接続先を試すとOK

ggっても情報なかったので誰かの無駄な時間が減ることを願いメモ
【備忘録】Dockerfile内の`apt-get update`がGPGエラーで失敗する


## 概要
nginxのイメージをもとにDockerをビルドしていたのですが、どうあがいてもGPGエラーで`apt-get update`ができなくなってしまいました。

```
Building proxy
Step 1/12 : FROM nginx:1.25.3
 ---> d453dd892d93
Step 2/12 : RUN apt-get update -y
 ---> Running in 111d4ba94f4f
Get:1 http://deb.debian.org/debian bookworm InRelease [151 kB]
Get:2 http://deb.debian.org/debian bookworm-updates InRelease [52.1 kB]
Get:3 http://deb.debian.org/debian-security bookworm-security InRelease [48.0 kB]
Err:1 http://deb.debian.org/debian bookworm InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 0E98404D386FA1D9 NO_PUBKEY 6ED0E7B82643E131 NO_PUBKEY F8D2585B8783D481
Err:2 http://deb.debian.org/debian bookworm-updates InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 0E98404D386FA1D9 NO_PUBKEY 6ED0E7B82643E131
Err:3 http://deb.debian.org/debian-security bookworm-security InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 54404762BBB6E853 NO_PUBKEY BDE6D2B9216EC7A8
Reading package lists...
W: GPG error: http://deb.debian.org/debian bookworm InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 0E98404D386FA1D9 NO_PUBKEY 6ED0E7B82643E131 NO_PUBKEY F8D2585B8783D481
E: The repository 'http://deb.debian.org/debian bookworm InRelease' is not signed.
W: GPG error: http://deb.debian.org/debian bookworm-updates InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 0E98404D386FA1D9 NO_PUBKEY 6ED0E7B82643E131
E: The repository 'http://deb.debian.org/debian bookworm-updates InRelease' is not signed.
W: GPG error: http://deb.debian.org/debian-security bookworm-security InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 54404762BBB6E853 NO_PUBKEY BDE6D2B9216EC7A8
E: The repository 'http://deb.debian.org/debian-security bookworm-security InRelease' is not signed.
E: Problem executing scripts APT::Update::Post-Invoke 'rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true'
E: Sub-process returned an error code
ERROR: Service 'proxy' failed to build : The command '/bin/sh -c apt-get update -y' returned a non-zero code: 100
```

## 解決方法
イメージの外側、ホストマシンでDocker自体の更新をしてみます。

```
apt upgrade docker
```

上記のコマンド終了時、どうやらエラーとなっているパッケージがある旨の表示が出力されました。

 ```
 Errors were encountered while processing:
   nginx-core
   nginx-full
   nginx
   python3-certbot-nginx
 ```

ホストマシンにインストールされたパッケージとDockerイメージ内のパッケージが競合している(？)ということなのか・・・？

それらをアンインストールしてみます。

```
sudo apt remove nginx-core nginx nginx-full python3-certbot-nginx
```

結果、Dockerfileのビルドが通るようになりました。
Dockerは結構使っているつもりですが、やっぱりハマるときはハマるんですよねえ・・・(8時間近くハマった)