OmniAICreator/Qiita-1.07M huggingface dataset:
同じ構造を省略する例

## はじめに
json構造で、同じ箇所を共通化する方法で迷ったので記載しておく。

## 同じ構造を省略する例
非同期を扱う場合でkintoneを例にとると、
あるアプリデータを追加する場合と修正する場合、id違いである。
record箇所は追加と修正で、共通のデータを再利用するようにしましょう。
・追加の場合
```javascript
const body = {
  "app": kintone.app.getId(),
  "record": {
    "文字列1行": {
      "value": "テスト"
    },
    "文字列複数行": {
      "value": "テスト\nテスト2"
    },
    "数値": {
      "value": "20"
    },
    "日時": {
      "value": "2014-02-16T08:57:00Z"
    },
    "チェックボックス": {
      "value": ["sample1", "sample2"]
    },
    "ユーザー選択": {
      "value": [
        {
          "code": "sato"
        }
      ]
    },
    "ドロップダウン": {
      "value": "sample1"
    },
    "リンク_ウェブ": {
      "value": "https://www.cybozu.com"
    },
    "テーブル": {
      "value": [
        {
          "value": {
            "テーブル文字列": {
              "value": "テスト"
            }
          }
        }
      ]
    }
  }
}
await kintone.api(kintone.api.url('/k/v1/record.json', true), 'POST', body);
```
・修正の場合
```javascript
const body2= {
  "app": kintone.app.getId(),
  "id": 100,
  "record": {
    "文字列1行": {
      "value": "テスト"
    },
    "文字列複数行": {
      "value": "テスト\nテスト2"
    },
    "数値": {
      "value": "20"
    },
    "日時": {
      "value": "2014-02-16T08:57:00Z"
    },
    "チェックボックス": {
      "value": ["sample1", "sample2"]
    },
    "ユーザー選択": {
      "value": [
        {
          "code": "sato"
        }
      ]
    },
    "ドロップダウン": {
      "value": "sample1"
    },
    "リンク_ウェブ": {
      "value": "https://www.cybozu.com"
    },
    "テーブル": {
      "value": [
        {
          "value": {
            "テーブル文字列": {
              "value": "テスト"
            }
          }
        }
      ]
    }
  }
}
await kintone.api(kintone.api.url('/k/v1/record.json', true), 'PUT',body2);
```

以下のようにして重複は避けてください。
```javascript
const baseRecord = {
  "文字列1行": {
    "value": "テスト"
  },
  "文字列複数行": {
    "value": "テスト\nテスト2"
  },
  // ... 他のフィールド
};

// 追加の場合
const bodyForAdd = {
  "app": kintone.app.getId(),
  "record": baseRecord
};
await kintone.api(kintone.api.url('/k/v1/record.json', true), 'POST', bodyForAdd);

// 修正の場合
const bodyForUpdate = {
  "app": kintone.app.getId(),
  "id": 100,
  "record": baseRecord
};
await kintone.api(kintone.api.url('/k/v1/record.json', true), 'PUT', bodyForUpdate);
```

https://cybozu.dev/ja/kintone/docs/rest-api/records/add-record/
【Golang】カラムにGormのDeleted_atが含まれる場合のレコード取得について

論理削除を実装するために、gorm.DeletedAtを使用した場合、レコードの取得のクエリが論理削除されたデータを取得しないように自動的に切り替わる。
場合によって、論理削除したレコードも取得したことがあるため、論理削除したレコードを取得する方法についても備忘録として残す。

### gorm.DeletedAtカラムがある場合のオブジェクト取得のクエリ
以下は公式ドキュメントのサンプルを流用
https://gorm.io/ja_JP/docs/query.html
```go
type User struct {
  ID           string `gorm:"primarykey;size:16"`
  Name         string `gorm:"size:24"`
  DeletedAt    gorm.DeletedAt `gorm:"index"` // Gormの特定のフィールドタイプの使用
}

var user = User{ID: 15}
db.First(&user) // 論理削除を実装している構造体でFirst()メソッドを実行
//  SELECT * FROM `users` WHERE `users`.`id` = '15' AND `users`.`deleted_at` IS NULL ORDER BY `users`.`id` LIMIT 1
```

注目して欲しいのが、コメントアウトされている生成されるクエリである。
以下は見やすいように整形したもの。
```go
SELECT * 
FROM `users` 
WHERE `users`.`id` = '15' AND 
      `users`.`deleted_at` IS NULL // このwhere句に注目
ORDER BY `users`.`id` 
LIMIT 1
```

論理削除が含まれる構造体に対するクエリにはwhere句の中に「deleted_at IS NULL」の条件が含まれている。
つまり、デフォルトでdeleted_atカラムがNULL以外のレコードが条件となっている。

通常であれば、論理削除されたものは取得しなくてもよいため、Gormは親切なメソッドを作成してくれている。


### 論理削除されたレコードを取得する。「Unscoped()メソッド」

仕様や要件によっては論理削除したレコードも取得したことがある。
この論理削除されたレコードを取得する方法も公式に載っているため、紹介する。
https://gorm.io/ja_JP/docs/delete.html
```go
db.Unscoped().Where("age = 20").Find(&users)
// SELECT * FROM users WHERE age = 20;
```
:::note info
論理削除されたレコードは「Unscoped()メソッド」を使用することで取得することができる。
:::

#### 論理削除のレコードを取得しないデフォルトのクエリを打ち消すサンプルコード
```go
type User struct {
  ID           string `gorm:"primarykey;size:16"`
  Name         string `gorm:"size:24"`
  DeletedAt    gorm.DeletedAt `gorm:"index"` // Gormの特定のフィールドタイプの使用
}

var user = User{ID: 15}

db.Unscoped().First(&user)
```

通常のgormを使用したコードの前にUnscoped()を追加するだけ。

### まとめ
Gormでは論理削除の実装及びそれを考慮したレコードの取得が簡単に行える。
ただし、論理削除が含まれる構造体へのGormのデフォルトのクエリが変化するため、注意が必要。
論理削除されたレコードを取得したい場合は「Unscoped()メソッド」を使用すること。
Head First デザインパターン 第2版 を読んだ感想

# 概要
[Head First デザインパターン 第2版](https://www.oreilly.co.jp/books/9784873119762/)を読んたので、感想を残しておこうと思う。600ページ近くある本なのに、本嫌いな私が全く飽きずに楽しく読み進められる素晴らしい本だった・・・。

# 感想
この本の特徴は真面目な技術書と違い、終始砕けた口調でイラストを多用しながら、ストーリー仕立てでデザインパターンの実装を学んでいく変わった本だ。
カモ池シミュレーションゲームという謎のシステム開発を通じStrategyパターン（後半にまさかの発展形も）を学び、ガム販売システムの開発を通じてStateパターンを学ぶといった普通の技術書じゃまず見られないような展開で話しが進んでいく。
更には（何故か仲の悪い）各パターン同士の座談会というショートストーリーまで用意されている。
しかしこのような内容だからこそ、読んでいて飽きないし、何かと印象に残る・・・そう記録に残りやすいのだ。本の冒頭に記載されているが、メタ認知を目指しているらしい）

もちろん内容も充実していて、デザインパターン以外にもオブジェクト指向の基礎まで書かれているので、この本を読むだけで両方学べてしまう。

逆にデザインパターンもオブジェクト指向も基礎しか書かかれていないので、発展形的な内容を求めている人には向かないと思う。

## こんな人に向いてる
- 文章で理解するのが苦手な人
  - 図やイラストで理解するのが好きな人
- 砕けた文章に抵抗がない人
- オブジェクト指向を同時に学びたい人
- 他のデザインパターン本で挫折した人

## こんな人はイマイチかも
- 真面目な文章が好きな人
- デザインパターンの再学習をしたい人
- Java言語を全く知らない人
    - 何らかのオブジェクト指向ベースの言語が理解出来れば問題ないとは思う
- 全てのデザインパターンを網羅したい
    - 使用頻度が少ないデザインパターンは巻末に超簡潔に書かれているだけ

# さいごに
本当に楽しく学習出来たので、読み終わった後に続きがないことに対する喪失感すらあった。万人受けする内容じゃないかもしれないけど、私と同じように文章苦手なタイプには刺さる本だと思うので、是非手に取って読んで欲しい。

なお、本書は5000円と高価だが図書館で借りて読めたので、もし図書館が近くにある方は確認してみるといいかも？

# 参考

- [Head First デザインパターン 第2版 頭とからだで覚えるデザインパターンの基本](https://www.oreilly.co.jp/books/9784873119762/)
- [サンプルコードのC#版](https://github.com/nabedroid/DesignPattern)
JPHACKS2023-Review

# 概要
JPHACKSという日本最大の学生向けハッカソンに参加した。
内容としては作品のテーマは自由、２日間で動く製品を作成し、デモ発表を行うというもの。
私達は「チーム鳥取大学」として三人チームで参加し、感情×Techのサービス「Emotter」を開発した。

# 役割分担
役割分担は、内容をSNS部分と感情認識部分に大きく分割し他2人に分配、私はインテグレーターとして全体の進捗を管理しつつ他2人が詰まっている部分の補佐とプレゼンを行なった

# 作成物
Emotterは完全なTwitterオマージュのSNSであり、画像認識・自然言語処理を用いた感情認識システムにより直接のコミュニケーションに近い新感覚のSNSとなっている。

## サービスの流れ
Emotterの投稿までの流れを示す。
まず、以下の投稿フォームに投稿内容を書き込む。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3487085/1b80b170-8e71-c7f9-5970-0962a5e48de9.png)

投稿内容が書き終われば、投稿ボタンを押す。
すると、WEBカメラが起動し、投稿者の顔が撮られる。

その後、写真をデータURLに変換し、投稿内容と共にサーバにPOSTされる。

POSTされた画像と投稿はそれぞれ機械学習モデルに通され、ネガポジ判定が行われる。

そして、投稿内容、それぞれの感情認証結果がデータベースに保存される。
（画像はこの時点で破棄される。）
この感情認証結果と投稿内容のセットのことをエモートと呼ぶ。

タイムラインにはこの感情認証結果が一致したエモートのみ表示され、悪意のある投稿は排除される。

以上がEmotterの一連の流れである。

## ソースコード
ソースコードはGitHubにアップロードしている。

https://github.com/rakawanegan/Emotter

## デモ動画
デモ動画はYouTubeにアップロードしている。
（デバッグモード時に私の顔が写っているので非公開にしているかもしれない。）

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

## 技術スタック
技術スタックとしては、以下を用いた
- Django：PythonベースのWEBアプリ開発用フレームワーク
- FER：表情認識のPythonモジュール
- BERT：日本語モデルを東北大学が提供の感情分類データセットを用いファインチューニング

苦戦した部分としては、顔画像をデータURIに変換しPOSTを行う箇所がDjangoでは実装困難であった為、ChatGPTの力を借りながらではあるが、無学のJava Scriptで書いたことである。
残念ながら初日はこの処理をする部分で詰まってしまい進捗が思ったように進まなかった。

GitHubのリポジトリに学習済みモデルを生成するコードが入っているが、再現性の担保の為、学習済みモデルを一定期間Google Driveにアップロードしておく。

https://drive.google.com/drive/u/0/folders/1x91HepGToqNp_h2tSSycvnFx98bzjMp2

# 振り返り
JPHACKSへの参加を通じて、チームワークや他人への依存の難しさを痛感した。
しかし、この経験を通じて、エンジニアとしてのスキルの底上げが出来たと思う。

反省点としては、タイムラインやアクションプランが不明確であったせいで当日バタバタしたこと、分業がはっきりできていなかったことで1人に大きな負担を強いてしまったことがある。

総括として、2日間でサービスを構築するというハードで貴重な経験を積むことができた。
定時帰る術-Linux sshでサーバ管理（ssh、scpコマンド）

昔の昔では、telnetもよく使われたが、今完全に消えてしまった。
機器管理もできるし、ポートテストもできるし、便利だと思う。
WindowsもLinux（REHL）もデフォルトでインストールされてないのが少し寂しい

（川口はネットワーク出身で、昔から個別でインストール必要があるのが、いつかからデフォルトパッケージから削除されたのが知りません。）

どうでもいい話は以上で、今日はsshクライアントの話をしようと思う。
（opensshではないよ）

### 定義ファイル場所
（コマンドのオプションの方が優先）
```
[root@mgmt ~]# ll /etc/ssh/ssh_config
-rw-r--r--. 1 root root 1770  6月 30  2022 /etc/ssh/ssh_config
```

### ssh
使い方も簡単
(今回はパスワード認証で、よく使われてる証明書認証はサーバ側の方も設定する必要があって、openssh話をする際に、話させてもらう予定)
```
[root@momo ~]# ssh 192.168.100.6
The authenticity of host '192.168.100.6 (192.168.100.6)' can't be established.
ECDSA key fingerprint is SHA256:o3FAB+htsiuMQHwjyosMrZGGIWabLtLo8rMEVoFP5zU.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.100.6' (ECDSA) to the list of known hosts.
Password:
Activate the web console with: systemctl enable --now cockpit.socket

Register this system with Red Hat Insights: insights-client --register
Create an account or view all your systems at https://red.ht/insights-dashboard
Last failed login: Wed Nov  1 22:06:07 JST 2023 from 192.168.100.100 on ssh:notty
There was 1 failed login attempt since the last successful login.
Last login: Wed Nov  1 21:57:37 2023 from 192.168.1.67
[root@mgmt ~]#
```
### ポート転送
仕事でもよくポート転送する。
ポート転送することで、何でもできてしまう。（いろんな意味で）
ポート転送もサーバ側で許可（デフォルト）/拒否できるため、これもopenssh話をする際に、話させてもらう予定




### scp
sshはサーバのCLI管理用ツールで、scpはssh経由でのファイル転送ツール
これでmomo（ロカール）のsnow-testファイルを192.168.100.6配下に転送できる
```
[root@momo ~]# touch snow-test
[root@momo ~]# ls
DDNSNow_update.log  anaconda-ks.cfg  snow-test
[root@momo ~]# scp snow-test 192.168.100.6:/var/tmp
Password:
snow-test                                     100%    0     0.0KB/s   00:00

```

###トラブルシューティング
↓にはよく問題ある箇所
■認証方式
■鍵（あっているか、そもそも持っている、パーミッション（600）は大丈夫か）
■/etc/hosts.allow、/etc/hosts.deny（7系以前のLinux）
■FW
■ping疎通
未経験からエンジニア転職するために戦略的に分析してみた

プログラミングを学習するのに最初にぶつかる壁は、
どの言語を学習すればよいか？
だと思う。

30歳を超えてエンジニアに転職をするために、戦略を立てて学習する言語を考えてみた。

## 求人が多いもの
東京ならいざしらず、地方都市で求人が多いものを探した。
ハローワークのキーワード検索を行った。
結果、PHPが一番多かった。

## 地元で使われているもの
「今世界ではやってる言語」
「もっとも使われてる」
「求められてる」
みたいな記事を読むと、Typescriptとかが出てくるが、
私の住んでいる地域ではほとんど求人がなかった。


## 競争が激しくないもの
競争が激しい＝フロントエンド
みたいな話をよく見かけた。

ＰＨＰだと競争が激しくないのか、それは不明だが、

「安定している技術」
は
「古くて枯れている」
と表現されることも多いみたいだった。

ＰＨＰは安定している。
そして競争が激化という話はあまり聞かない。
昔作ったサイトの改修などの話も聞く。

その他、時点でＪＡＶＡ

反対語にJavaScript
VueがNodeなど、細分化がすすみ、学んでも学んでもキリがないから。


## アルゴリズムで勝負しないもの
学生のころ、友達に2日くらいプログラミングを学んだことがあった。
挫折したのはアルゴリズムができなかったから。
アルゴリズムで実装していく…
というのは醍醐味で面白いところだとは思うのだが、自分には向いてないと思っていた。
好きな人や得意な人はごまんといるし。

なので、機械系ではなくWeb系を考えた
セキュリティなど、知識系が必要なところは、学習でカバーできるかな？
と思ったためだ。

対極はC/C＋＋　　だと思っている…。

##　参入障壁が低いもの（日本語の教材が多い）
PHP、いうことなし。
ただしバージョンによって食い違いがあるから、
(教材のバージョンが最新じゃなかったりする）
その部分だけ注意。

## その結果
SQLやってます！！！
SQLServerをM1Mac上のDockerで動かす

# SQLServerとかDockerイメージにamd64形式のしか無いものをM1Macで動かす方法。

SQLServerとかDockerイメージにamd64形式のしか無いものをM1Macで動かす方法です。

* MacOSを最新（14）に上げる
* DockerDesktopを最新（4.25）に上げる
* docker-composeにこんな風にplatformって命令を追加する

```
    sqlserver:
        image: mcr.microsoft.com/mssql/server:2022-latest
        platform: linux/amd64
```

という半分暴力的な解決が出来ました。

というのもMacOS13以上且つ、DockerDesktop4.16以
上だとRosettaっていうM1でもIntelが使えるなんか変換ツールが標準で使えるようになっているらしい。
Dockerを起動しようとしてlinux/amd64 とかコンソールメッセージに出てきたら試してみるべし。

以下参考にさせて頂いたページ。ありがたやー

https://qiita.com/toyoyuto618/items/f225e1b2ab22ca5adf33

一応、docker-composeのsqlserver部分全文です。

```yaml
    sqlserver:
        image: mcr.microsoft.com/mssql/server:2022-latest
        platform: linux/amd64
        environment:
        - ACCEPT_EULA=Y
        - SA_PASSWORD=NanikaSugoiPassword!!
        ports:
        - "1433:1433"
        volumes:
        - sqlserver-data:/var/opt/mssql
```
以下で接続できます。

```
jdbc:sqlserver://;serverName=localhost;databaseName=master
```
AWSのS3で本番環境でも画像を保存できるようにしよう。【vol2】

### 【概要】
---
AWSのS3についてのアウトプット(備忘)、また、これからはじめて触れるよ！って方の参考になればと思います〜。
設定に若干苦戦したのと、他の記事で情報の過不足の部分があったので初めての方でもわかりやすく設定できればと思います！！
(画面は2023年11月時点のものとなります。)

### 【対象】
---
・S3でクラウド環境に画像を保存したい。
・renderでdeployをしたい。(Herokuなどでも可ですが、環境ヘ変数の設定が少し異なります。)
・.envファイルで管理したい。(credentialファイルでも設定可ですが、今回は.envで管理します。)

### 【環境】
---
・Rails7系
・Ruby3.2.2
・CarrierWave導入済。(carrierwaveについては省略します。)
・Docker ver3
・render

### 【前提条件】
---
・[・AWSのS3で本番環境でも画像を保存できるようにしよう。【vol1】 ](https://qiita.com/iijima-naoya-45b/items/0bdf75bde960787c9c04)
・[・AWSのS3で本番環境でも画像を保存できるようにしよう。【vol2】 ](https://qiita.com/iijima-naoya-45b/items/ff16c778a7cea2ea18af)←イマココ
・[・AWSのS3で本番環境でも画像を保存できるようにしよう。【vol3】 ](https://qiita.com/iijima-naoya-45b/items/1b966b3152d4b0d73e49) 

### 【手順】
---
1.初めに
2.Gemのインストール
3.development.rbの編集
4.storage.ymlの編集

### 【1.はじめに】
---
今回はAWSのS3を用いた画像アップロードを実装していきます。

### 【2.Gemのインストール】
---
S3を使用するために必要なaws-sdk-s3というGemをインストールします!
今回は、`require: false`のオプションを設定してください。なおオプションを設定する理由は下記です。

>通常、Gemを追加すると、自動的にプログラム内で読み込まれますが、このオプションを指定することで、手動で読み込む必要がある場合にのみ読み込むことができます。これにより、プロジェクト全体でAWSの他の機能を使用する場合に、不要なコードの読み込みを避けることができます。(ChatGPTより引用)

```ruby:Gemfile
gem "aws-sdk-s3", require: false
```

```ターミナル
bundle install
```

### 【3.development.rbの編集】
---
画像の保存先をlocalからS3に保存されるように設定を変更します。
まず、`development.rb`に記述している画像の保存先の設定を下記のように変更します。

```ruby:config/environments/development.rb
#config.active_storage.service = :local
config.active_storage.service = :amazon
```

なお、`production.rb`も変更しておきましょう。
```ruby:config/environments/production.rb
#config.active_storage.service = :local
config.active_storage.service = :amazon
```

### 【4.storage.ymlの編集・環境変数の使用】
---
```ruby:storage.yml
amazon:
  service: S3
  access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>  
  secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> #環境変数の設定はvol3で行います。
  region: ap-northeast-1 #regionを変更
  bucket: <%= ENV['AWS_BUCKET_NAME'] %> 
```

お疲れ様です。次工程が最後になります。

### 引用
---
https://qiita.com/oak1331/items/74da3cf101e2e2107f32
【AWS】グラコレに学ぶAWS Well-Architectedフレームワーク

>AWS Well-Architectedフレームワーク　グラコレ
>https://aws.amazon.com/jp/builders-flash/202101/awsgeek-well-architected/?awsf.filter-name=*all

AWS Well-Architectedフレームワークは主に5つの柱から成り立つと、グラコレ(全体図)から読み取れます。

■AWS Well-Architectedフレームワーク　グラコレ(全体図)
https://d1.awsstatic.com/Developer%20Marketing/jp/magazine/2020/img_awsgeek-well-architected_07.2b53046d7bb5b056f9a2117f59cc763b6b39b08a.png


5つの柱それぞれにホワイトペーパが用意されていて、詳細を丁寧に確認できますが
個別のホワイトペーパーを読む前に、まずは全体概要のホワイトペーパーを確認するとよいそうです。

次は全体概要に目を通そうと思います。

■ AWS Well-Architected フレームワークの概要　ホワイトペーパー
https://d1.awsstatic.com/whitepapers/ja_JP/architecture/AWS_Well-Architected_Framework.pdf
Azure Databox で移行してみた

## 個人アカウントでは Azure Databox 発注できない
社内検証のため発注してみたが、Production チームにメールしても許可してもらえず、お客様サービス提供するための検証で１週間粘った結果、発注できるようになりました。

サブスクリプションが、次のいずれかの種類であること
- Microsoft 顧客契約 (MCA) または Microsoft Enterprise Agreement (EA)
- Cloud Solution Provider (CSP)
- Microsoft Azure スポンサー プラン
- Microsoft Partner Network (MPN)

## Azure Databox 割と大きい、重い
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160072/483b477b-1e6f-24ea-e902-a249777ebb1b.png)

## ドキュメントによりコピーのコマンドが違う
結果から言うと、１番のコマンドは使いやすい

```bash:Azure File Sync にオフラインでデータを移行する
robocopy <SourcePath> <Dest.Path> /MT:20 /R:2 /W:1 /B /MIR /IT /COPY:DATSO /DCOPY:DAT /NP /NFL /NDL /XD "System Volume Information" /UNILOG:<FilePathAndName>
```
```bash:SMB 経由でデータをコピーする
robocopy <Source> <Target> * /e /r:3 /w:60 /is /nfl /ndl /np /MT:32 or 64 /fft /B /Log+:<LogFile>
```

## Robocopy クセがある
**`/B`** バックアップ モードでファイルをコピーし、現在のユーザーがアクセス許可を持っていないファイルを、Robocopy によって移動できます。

問題は
- このパラメータは管理者特権のコマンドプロンプトか `PowerShell` で実行する必要がある
- 権限ない場合は、`メモリ不足` のエラーメッセージが表示され、分からない
- 特権必要はどこにも書いていない

## 発送処理
Azure Databox の出荷処理後の **Reference Number** 以外に、日本郵便の**トラッキング番号**も一緒に、受付センターにメールする
Xcode Build時のエラー'Linker command failed with exit code 1 (use -v to see invocation)'の解決方法

# 開発端末
MacBook Air M2チップ(macos Ventura 13.4)

# エラー内容
Framework 'FBLPromises' not found
Linker command failed with exit code 1 (use -v to see invocation)

# 解決方法
Unity-iPhone.xcworkspaceで開き直して、ビルド再実行

# Unity-iPhone.xcworkspaceがない人
ターミナルからビルドするフォルダに移動し、コマンド実行。
```:コマンド
pod install
```

# pod installでエラーが出た人
[!] `GoogleAppMeasurement` requires CocoaPods version `>= 1.10.2`, which is not satisfied by your current version, `1.9.0`.

以下コマンド実行
```:コマンド
sudo gem install cocoapods
```
# 最後に
pod installが正常に終了すると、Unity-iPhone.xcworkspaceが作成されているので
それビルドして終了。お疲れ様でした！！
[HTML・JSP] なぜ画面に表示されない。。あぁ～これが原因か。

#### はじめに

やまだです。
新人研修や遊び程度しか触れてこなかったフロント関連。
まさか配属先で触れていくことになるとは。。。
（今までJavaとMySQLがメイン）
ということで、現在までに出会ったプチミスを記載していきます。

#### 思ったように画面に表示されない理由

下記内容を疑ってみたら、想定した画面にたどり着くかもしれない。

 - リストがうまく表示されない場合
   - 「リストの横幅のサイズ　＞　リスト内の項目のサイズ」になってる？
 - 画面レイアウトが反映されない場合
   - cssでの指定を誤っていないかい？
     - 表示させたい名称の綴りを間違えていない？
     - 例えば、\<col>を利用しているのに、css上では\<div>と書き間違えていない？
     - カラーを上書きするような書き方になっていない？
   - タグの終了がずれてたりしない？
     - フォーマットを整えると足りない箇所が分かるかも。
 - JSPエラーが出る
   - リストが空でも表示させたい場合、\<logic:present>を利用し忘れてない？

#### おわりに

これからも出会ったら更新していきます。
更新しないよう頑張りたいですね。。。
【Swift】バージョンを比較したい

# はじめに
「バージョンアップしてください」的なアラートを出す際に、現在使用しているバージョンとストアにある最新バージョンを比較するという作業が必要です。
バージョンできるようにするための構造体を作成しましたので記録しておきます。

:::note warn
**注意**
セマンティックバージョニングのみ対応してます
:::

# 実装
```SemanticVersion.swift
import Foundation

public struct SemanticVersion {
    public let major: Int
    public let minor: Int
    public let patch: Int

    public init(_ major: Int, _ minor: Int, _ patch: Int) {
        self.major = major
        self.minor = minor
        self.patch = patch
    }

    public init?(_ string: String) {
        let pattern = #"([0-9]+)\.([0-9]+)\.([0-9]+)"#
        let versions = string.match(pattern)
            .compactMap(Int.init)
        guard versions.count == 3 else { return nil }

        self.major = versions[0]
        self.minor = versions[1]
        self.patch = versions[2]
    }
}

extension SemanticVersion: CustomStringConvertible {
    public var description: String {
        "\(major).\(minor).\(patch)"
    }
}

extension SemanticVersion: Comparable {
    public static func < (lhs: SemanticVersion, rhs: SemanticVersion) -> Bool {
        (lhs.major, lhs.minor, lhs.patch) < (rhs.major, rhs.minor, rhs.patch)
    }
}
```

```String+match.swift
import Foundation

public extension String {
    func match(_ pattern: String) -> [String] {
        guard let regex = try? NSRegularExpression(pattern: pattern),
              let matched = regex.firstMatch(in: self, range: NSRange(location: 0, length: self.count))
        else { return [] }
        return (0 ..< matched.numberOfRanges).map {
            NSString(string: self).substring(with: matched.range(at: $0))
        }
    }
}
```

# 使い方1
```swift
let version1: SemanticVersion = .init(1, 0, 0)
let version2: SemanticVersion = .init(1, 0, 1)

print(version1 < version2)
```

# 使い方2
```swift
let version1: SemanticVersion = .init("1.0.0")!
let version2: SemanticVersion = .init("1.0.1")!

print(version1 < version2)
```

# おわり
これで比較できるようになりました！
典型問題の暗記でAtCoder青になった

10 月に AtCoder で青色になったので、水色から青色になるためにやったことを残しておきます。

## 前提

青色になるまでは ABC だけに参加していました。 ARC や AGC には参加していません。

## 勉強法

ABC に出題される問題は典型問題が多く、過去問に類題があることがほとんどです。よって典型問題の解き方を暗記し、速く解けるようになることを目標にしました。

具体的には、ABC212 以降の D、E、F 問題をひたすら回しました。ほとんどこれしかやっていません。
競プロの書籍もいくつか出版されていますが読んでいません。ABC の解説で理解していけば十分でした。[^1]
また、典型といえば[典型90](https://atcoder.jp/contests/typical90)がありますが、青色になるための典型問題はABCの過去問に十分出題されていると思うので、別にやらなくても良いと思います。

[^1]: 書籍が必要なかったのは、体系的に学ぶ必要がなかったことと、ABC の解説自体が良い教材なことが大きいです

### 問題の進め方

1 問 5 分くらい考えて解けそうなら解いて、解けそうでなければ解説を見ます。解説がよくわからなかった場合は解説放送で補います。解説 AC をためらわず、1問1問に時間をかけないようにし、とにかく数を回すことを意識しました。

解説をみるときは

+ 何に気付けていれば解けていたか
+ どの部分が典型か

を意識すると良いと思います。

2,3 周繰り返していると、解法が暗記できていて実装も速くできる問題がでてくるので、そのような問題は飛ばすようにします。スプレッドシートなどで管理しておくと良いでしょう。

## おわりに

これを続けていると、本番で解法が見えるのが速くなっていったように感じます。
勉強自体は面白くなく、競プロの問題を解く楽しみのようなものはありませんが、凡人が手っ取り早く青色まで到達できる勉強方法だったように思います。
Ruby on Railsで使える画像処理ツール4選

# Ruby on Railsで使える画像処理ツールまとめ

Ruby on Railsのウェブアプリケーションで画像アップロードと処理が必要な場合、Active Storage、ImageMagick、MiniMagick、およびImageProcessingなどのツールが非常に役立ちます。この記事では、これらのツールについて詳しく説明し、どのようにプロジェクトに統合できるかについて説明します。

## 1. Active Storage

Active Storageは、Ruby on Railsの標準ライブラリで、ファイルのアップロードと管理を簡単に行うためのものです。これは、主に画像やファイルのアップロードをサポートし、アクティブレコードモデルと緊密に統合できます。これにより、データベース内のリンク、クラウドストレージプロバイダー（例: Amazon S3）、またはローカルファイルシステムなど、複数のストレージバックエンドとの連携が容易に行えます。

## 2. ImageMagick

ImageMagickは、画像の作成、編集、変換、表示に使用されるオープンソースのソフトウェアスイートです。Ruby on Railsなどのプロジェクトで、画像のリサイズ、クロップ、回転、フィルタリングなどの画像処理タスクを実行するために一般的に使用されます。ImageMagickは、コマンドラインツールとして提供されており、Rubyから直接操作するためにラッパーライブラリが存在します。

## 3. MiniMagick

MiniMagickは、RubyのGemで、ImageMagickをラップして使いやすくしたものです。これを使用することで、画像処理タスクを実行するためのAPIを提供し、Railsアプリケーション内で画像の縮小、切り抜き、変換などを簡単に行えます。Active StorageやCarrierWaveなどのファイルアップロードライブラリと統合することもでき、アプリケーション内で画像処理を効果的に行う手助けをします。

## 4. ImageProcessing

ImageProcessingは、画像処理タスクを簡略化するためのRubyライブラリです。Active StorageやCarrierWaveなどのファイルアップロードライブラリと統合でき、画像のリサイズ、クロップ、フィルタリング、圧縮などのタスクを処理できます。ImageProcessingはプラグインをサポートしており、プロジェクトのニーズに合わせてカスタマイズできます。

これらのツールは、Ruby on Railsのプロジェクトで画像アップロードと処理に役立ち、ユーザーエクスペリエンスを向上させるのに役立ちます。Active Storageはファイルのアップロードとストレージを容易にし、ImageMagickとMiniMagickは画像処理を行い、ImageProcessingはさまざまな画像処理タスクをカスタマイズできるフレームワークです。これらのツールは、ウェブアプリケーションの開発者にとって重要な資産であり、プロジェクトの要件に合わせて選択できます。
AWS Application Migration Service (MGN) で移行してみた

## トラブル一覧
- １台のみ、通常数時間のデータ転送は２ヶ月以上かかるため、MGNの移行を諦めた。エージェントの問題だと、お手上げです。
- 古い Windows (2008 R2以前) だと、第5世代のインスタンス(c5, m5など)は、起動できない
- Windows 2008 以前、ENA (Elastic Network Adapter) サポートしないため、インスタンス作成後に ENA 無効化処理が必要
- 古い Windows のパッチ (Windows Update) 更新しないと、インスタンス作成後に長時間ログインできない（数十分～数時間）
- リハーサル成功しても、３日後の本番移行で、全てのカットオーバーインスタンス起動できない (**c5→c4, r5→r4 で解決**)
- AWSのドキュメントは、全て信じじゃダメです。Windows Cluster は移行できるが、移行後の動作は保証しない!!! **共有ストレージのクラスターは一発アウト**

## 反省点
- 「Staging移行 → Prod 移行」の通常移行ではなく、最初から本番含めて MGN Agent をインストールし、同期に問題ないかを確認する
- Windows Cluster の調査不足、共有ストレージのクラスターを AWS 上で正常動作するために、3rd Party のツールが必要
- MGN Agent は正常に動作しない場合、AWS Support に問い合わせしても、解決できない可能性があるため、運ゲです!!

## 改善点
- カットオーバー後（本番）のインスタント設定作業は手動で行ってますので、時間かかりました。Post Launch Action を使い、自作スクリプトや Systems Manager document などできるだけ自動化がおすすめです
PowerShellでGETとPOST可能な簡易Webサーバを立てる

# これはなに？

後述のPowerShellスクリプトで簡易ローカルサーバを立てることができる。
`http://127.0.0.1:8080/`にGETすると"Hello, world!"を返し、POSTするとBodyの文字列をそのまま返す。
PUTやDELETEには対応せず`400 Bad request`を返す。

※`Ctrl+C`やISEの停止ボタンでは止まらないので、停止する時はコンソールそのものを落とすこと。
※類似サイトで「PowerShellを管理者権限で実行すること」と書かれているサイトを見つけたが、手元の環境では通常のadminユーザでも動いた。

# スクリプト

```powershell:my_server.ps1
$url = "http://127.0.0.1:8080/"

$listener = New-Object system.net.HttpListener
$listener.Prefixes.Add($url)
try {
    $listener.Start()
    $url
    while ($true) {
        $context = $listener.GetContext()
        $request = $context.Request
        $response = $context.Response
        if($request.HttpMethod -eq "GET"){
            # GET時にはHello, world!を返す
            $text = "Hello, world!" 
        }elseif($request.HttpMethod -eq "POST"){
            # POST時には受け取った文字列をそのまま返す(エンコーディングは考慮しない)
            $reader = New-Object System.IO.StreamReader($request.InputStream)
            $text = $reader.ReadToEnd()
            $reader.Close()
        }else{
            # PUTなどには未対応。必要に応じて上記のelseifを参考によしなにすること
            $response.StatusCode = 400 # Bad request
            $response.Close()
            continue
        }
        $bytes = [System.Text.Encoding]::UTF8.GetBytes($text)
        $response.ContentLength64 = $bytes.Length
        $output = $response.OutputStream
        $output.Write($bytes, 0, $bytes.Length)
        $output.Close()
    }
} finally {
    $listener.Stop()
    $listener.Dispose()
}
```

# Powershellから動作確認する例

## GET

```powershell
$uri = "http://127.0.0.1:8080/" 
[System.Text.Encoding]::UTF8.GetString($(Invoke-WebRequest $uri).Content)
#Hello, world!
```

## POST

```powershell
$uri = "http://127.0.0.1:8080/" 
$body = [System.Text.Encoding]::UTF8.GetBytes("Hello, world!")
Invoke-RestMethod -Method POST -Uri $uri -Body $body
#Hello, world!
```

# 参考資料

+ [PowerShellで簡易Webサーバを立てる](https://yudachi-shinko.blogspot.com/2023/04/powershellweb.html)
+ [PowershellでHTTPサーバを建てる](https://szk302.dev/posts/Powershell%E3%81%A7HTTP%E3%82%B5%E3%83%BC%E3%83%90%E3%82%92%E5%BB%BA%E3%81%A6%E3%82%8B/)
+ [PowerShellでHTTPサーバー的なものを作る](https://qiita.com/kikuchi/items/785631cb24dfe5fa8d52)
+ [PowerShellで日本語を含むJSONをPOST](https://qiita.com/KakeiAkihiko/items/f936e4605aa343fcef0d)
Railsで画像アップロードするときのS3バケットの設定

## はじめに
Railsで画像アップロードするときのS3バケットの設定方法を紹介します。
必要最低限の権限だけ付与するようにしようと思います。

RailsからAWSへアクセスするためにはアプリケーション用のIAMユーザーを作成して、アクセスキーとシークレットアクセスキーを使います。

作成したIAMユーザーにS3へのアクセス権をつけることでRailsからS3へアクセスできます。

## 環境
`Rails 6.1.6`
`ruby 3.0.6`

## S3バケットの設定
バケットのアクセス許可の設定はブロックパブリックアクセス、バケットポリシー、オブジェクト所有者で行います。

### ブロックパブリックアクセス
チェックボックスが4つ並んでいるUIのところです。
今回のユースケースでは`新しいパブリックバケットポリシーまたはアクセスポイントポリシーを介して付与されたバケットとオブジェクトへのパブリックアクセスをブロックする`と`任意のパブリックバケットポリシーまたはアクセスポイントポリシーを介したバケットとオブジェクトへのパブリックアクセスとクロスアカウントアクセスをブロックする`にチェックをつけます。

### バケットポリシー
次にJSONでバケットポリシーを設定します。
特定のIAMユーザーのみがバケットへアクセスできるようにします。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowIAMUserUpload",
            "Effect": "Allow",
            "Principal": {
                "AWS": "IAMユーザーのARN"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::バケット名/*"
        }
    ]
}
```

### オブジェクト所有者
ACL有効にチェックをつけます。
スプレッドシートでSNSフォロワー数の推移をグラフ化してみた

# 概要

2021年から2023年までのSNSフォロワー数の推移をグラフ化してみました（GoogleのSpreadSheetを利用）。TwitterとInstagramを始めたころはデータを取っていなかったので、情報はありません。

# 2021年のSNSフォロワー数の推移

2021年は、Twitterがトップでした。Instagramが2位、途中から始めたTikTokが3位になります。

![Twitter、Instagram、YouTube、TikTok、Facebook、LINE（2021年）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/12f7c2b2-8836-6c9c-3f3f-9ad4cbba8443.png)

# 2022年のSNSフォロワー数の推移

2022年は、TikTokが一時的にトップになりましたが、後半でInstagramに抜かれました。Twitterは順調に増えています。その他のSNSはあまり伸びていません。

![Twitter、Instagram、YouTube、TikTok、Facebook、LINE、食べログ（2022年）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/419dcb43-0976-9a5e-3997-d328e26f851f.png)

# 2023年のSNSフォロワー数の推移

2023年は、Instagramがトップです。2位はTikTok、3位はTwitterになっています。まだ11月なので傾向は変わるかもしれませんが、今のところはそんな感じです。Twitterが9月ごろから急激に伸びましたが、その後また急激に減少して今は変化は落ち着いています。

![Twitter、Instagram、YouTube、TikTok、Facebook、LINE、食べログ、Qiita、Pokekara、note（2023年）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/8b13867f-81a1-eebc-a68d-73aef6d73058.png)

# まとめ

2021年から2023年にかけてのSNSフォロワー数の推移をグラフ化してみました。Instagramがもう少し伸びてくれるといいのですが、万アカはまだまだ遠い感じです。
手っ取り早くVSCodeでPHPファイルを実行してブラウザを開く

# 準備

この手順は1回だけ行います。ファイルを実行しようとする際に毎回行うものではありません。

1. [PHP](https://www.php.net/)をインストールする
1. [PHP Extension Pack](https://marketplace.visualstudio.com/items?itemName=xdebug.php-pack)をインストールします。
1. VSCodeでphpファイルが入った**フォルダ**を開きます。このとき、ファイルではなくワークスペースとして開きます。
1. サイドパネルから**実行とデバック**タブを開き、`launch.jsonファイルを作成します`を押します。
1. PHPを選択します。
1. 以下の内容で`launch.json`を保存します。

```json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Built-in web server",
            "type": "php",
            "request": "launch",
            "runtimeArgs": [
                "-dxdebug.mode=debug",
                "-dxdebug.start_with_request=yes",
                "-S",
                "localhost:0"
            ],
            "program": "${file}",
            "cwd": "${fileDirname}",
            "port": 9003,
            "serverReadyAction": {
                "pattern": "Development Server \\(http://localhost:([0-9]+)\\) started",
                "uriFormat": "http://localhost:%s",
                "action": "openExternally"
            }
        },
    ]
}

```

# 実行

1. PHPファイルを開きます。
1. F5キーを押すか、**実行とデバック**タブで三角形の実行ボタンを押します。

# 設定

エラーメッセージを表示するため、`php.ini`に以下の行がある場合、コメントアウトすると良いでしょう。

```ini
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off
```

# デバッグ

ステップ実行などデバッグを行うには[Xdebug](https://xdebug.org/)が必要です。
MQTTサーバ(Mosquitto)にクライアント証明書での認証を導入する

# 概要
MosquittoによるMQTTサーバに，TLSのクライアント証明書によってユーザ側の認証をするようにします．サーバの証明書ではなく**クライアントの証明書**です．
MQTTにおいてユーザ認証といえばユーザ名とパスワードですが，平文パスワードだけだとちょっと心配…という場合に導入してみるといいかもしれません．
MQTT自体の解説だったりサーバ構築の丁寧な解説は別の記事を参照してください．自分が構築した時に参照したサイトはいくつか参考文献に載っけておきます．
筆者はそこまで認証系に詳しいわけではないので間違いなどあれば指摘してくださると助かります．

# 動作確認環境
- Ubuntu Server 22.04 LTS (Broker, Client)
  - mosquitto 2.0.11
  - OpenSSL 3.0.2
- Mac OS Ventura 13.4.1
  - mosquitto 2.0.18

# 準備
既にMosquittoのTLS対応をしたなどでCAができている場合は飛ばして大丈夫です．
1. OpenSSLでオレオレ認証局を作ります．適当な作業ディレクトリを作って移動します．
   ```
   mkdir cert
   cd cert
   ```
1. CAの秘密鍵を作ります．パスフレーズが求められるので適当に決めます．
   ```
   openssl genrsa -des3 out ca.key 2048
   ```
1. CSRファイルを作成します．この時もいろいろ聞かれますが適当に答えます．
   ```
   openssl req -new -key ca.key -out ca.csr -sha256
   ```
ここまででいったん準備完了．理論上これで一応動きますが，他記事をみてサーバの方の証明書も作っておくことを推奨します（サーバ証明書なしでクライアント証明書のみの場合の動作検証はしてません）．

# クライアント証明書を作る．
- Q. そもそもクライアント証明書ってなんすか？
- A. サーバ側から見て，特定のクライアントのみ通信を許可したいときに，クライアントの身許をはっきりさせるために配る証明書．SSHの設定とかしてるなら公開鍵を配る感じに近い（というか実際は中身公開鍵認証だからほぼまんま公開鍵）
というわけで作っていきます．

1. クライアント用の秘密鍵を作る．デバイス名は適当に決めてください．
   ```
   openssl genrsa -out {デバイス名}.key 2048
   ```
1. CSRファイルを作る．
   ```
   openssl -req -new -key {デバイス名}.key -out {デバイス名}.csr
   ```
1. クライアント証明書を作る．
:::note warn
コマンドのほとんどはサーバ証明書作るのと同じですが，後ろに`add-trust clientAuth`をつけるのを忘れずに！
:::
   ```
   openssl x509 -req -in {デバイス名}.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out {デバイス名}.crt -days 3650 -sha256 -addtrust clientAuth
   ```
これで，`{デバイス名}.crt`, `{デバイス名}.key`, `{デバイス名}.csr`のみっつができました．

最後に，`mosquitto.conf`ファイルの末尾に，
```
require_certificate true
```
を追加してサーバを再起動しましょう．

これで，MQTT Brokerに入るには，`{デバイス名}.crt`, `{デバイス名}.key`，それと`ca.crt`が必要になります．もしローカルではなくリモートで接続したければそちらのデバイスにこれらを渡しておきましょう．

# 接続してみる
一応，サーバ側の証明書もca.crtで作り，ポートを8883にしている想定です．また，カレントディレクトリに認証系のファイルを置いている想定です．条件に該当しない場合は適当に読み替えてください．

## Subscribe
- ローカル実行
    ```
    mosquitto_sub -p 8883 --cafile ca.crt --cert {デバイス名}.crt --key {デバイス名}.key -t {トピック} --insecure
    ```
::: note warn
`--insecure`をつけるとCommon Nameとホスト名が違っていても無視してくれます．ローカル実行時はつけないとTLS Errorを吐くことが多いです．
:::
- リモート実行
    ```
    mosquitto_sub -h {ホスト名} -p 8883 --cafile ca.crt --cert {デバイス名}.crt --key {デバイス名}.key -t {トピック}
    ```

## Publish

- ローカル実行
    ```
    mosquitto_pub -p 8883 --cafile ca.crt --cert {デバイス名}.crt --key {デバイス名}.key -t {トピック} --insecure -m "{メッセージ}"
    ```
- リモート実行
    ```
    mosquitto_pub -h {ホスト名} -p 8883 --cafile ca.crt --cert {デバイス名}.crt --key {デバイス名}.key -t {トピック} -m "{メッセージ}"
    ```

気が向いたらPythonなどから接続する方法を追記するかもしれないです．

# 参考文献
MQTT Essentials ([Amazonページ](https://www.amazon.co.jp/MQTT-Essentials-Lightweight-Protocol-English-ebook/dp/B01MS9I105))
> Hillar, Gastón C. MQTT essentials - a lightweight IoT protocol : the preferred IoT publish-subscribe lightweight messaging protocol. 1st edition, Birmingham, England ;, Packt Publishing, 2017, ISBN1-78728-514-6.

サーバ構築に関して：
[【Mosquitto】MQTTブローカの構築・動作確認 (ユーザ認証・TLS暗号化まで)](https://qiita.com/Nenshu_agetai/items/b000cd33027ac17dea9)

MQTTの概説・mosquittoの導入に関して：
[【MQTT】MQTTの導入 mosquittoのインストール/動作確認まで](https://qiita.com/koichi_baseball/items/8fa9e0bdbe6d0aebe57d)
Qiitaの記事に画像を貼る

# Windowsの機能を使って画像キャプチャ（Windowsボタン＋Shift＋S）

キャプチャした後、QiitaにCtrl＋V

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582674/aced0c7b-7942-5778-a6a6-748326fece43.png)


# Excelとか画像を選択して、コピー（Ctrl＋C）

コピーした後、QiitaにCtrl＋V

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582674/691a05b4-0311-8564-7f4c-ee46832cbe25.png)


# Qiita上でクリップボードの画像をPNG形式に保存＆アップロードされる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582674/52a2d07c-3851-8b6d-0096-c37e91955d6e.png)

# 全画面をPrintScreenボタンでコピー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582674/d8736cfc-b911-9a27-835b-f76419355a9e.png)

    便利だけど、危険！
react-card-flipでカードを裏返したときに表側が透けるバグの修正

react-card-flipというライブラリを使ったときに発生したバグを修正した記録です。

### react-card-flipとは
https://www.npmjs.com/package/react-card-flip

要素を裏返すためのアニメーションをつけられるライブラリ。

### 発生したバグ
カードを裏返したときに、表側の内容が透けて(反転されて)表示されてしまう。
![card-flip.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1645471/2b80ab24-a486-7e53-3e1e-bf02c56f6138.gif)
(バグを再現したgif。本来は、カードをひっくり返したときに「裏側」と書かれた面がこちらに向くようにしたい。)

### バグの発生条件
調査の結果、このバグは「safariを使用している」かつ「カード内でスクロールが発生する場合」に発生することが分かった。

### 修正方法
https://developer.mozilla.org/en-US/docs/Web/CSS/backface-visibility

`backface-visibility: hidden;` というCSSのプロパティがあるため、これをカードの表側のコンポーネントに適用させる。これは、要素が裏側を向いたときにその要素を表示するかどうかを決めるプロパティだ。

カード内がテキストのみである場合は、このプロパティを追加するだけで修正される。はず。
![card-flip-2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1645471/4265a1f1-2398-8007-000f-9a787ff3e9c3.gif)
(`backface-visibility: hidden;` 追加後のgif)

### さらにハマった
私が実際に作成したカードは、カードの上部7割にスクロールできるテキストが表示されていて、下部3割にはreactのsvgコンポーネントで作成した図形が表示されていた。

`backface-visibility: hidden;`をカードコンポーネントに追加してみると、テキストスクロール部分は表示されなくなったが、svgの部分は消えずに残っていた。

次に、カードコンポーネントだけではなく、svgコンポーネントに対してもこのプロパティを追加してみた。すると、iOSの方では表示されなくなった(正しく表示されるようになった)が、macのsafariでは消えずに残っていた。

色々と試行錯誤した結果、`backface-visibility: hidden;` と同時に
`transform: translate3d(0,　0,　0);`
を適用すれば正しく表示されることが分かった。

https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate3d
Qiitaの記事を修正する。

1. 記事のページを開く
1. 左側のバーにある「・・・」ボタンを押す
1. 「編集する」を押す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582674/5dc3ccff-9669-68ce-3594-181e2d3b883f.png)

# スマホの場合

スマホの場合、「・・・」ボタンは下にある。
![Screenshot_20231102-085251.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582674/d560ae21-8507-92dd-51a7-c99d4cdb136e.png)
Livewire3にアップグレードすると、ページネーションのクリック後のスクロール動作を指定できる

# Livewire3でそのままページャーを実装するとTOPにスクロールされてしまう
[前回記事](https://qiita.com/limtae/items/c5ea2ad6e48ba0baa62b "Livewire3.0にアップグレードするとモデルのプロパティを直接バインドできない件")でも書いたが、Livewire3にアップグレードする際は色々と落とし穴が多いので、しっかりアップグレードガイドを読んでおいた方がいい。




今回遭遇したのは、ページネーションのボタンをクリックするとページTOPにスクロールされてしまう現象。これは、実際のページネーションのテンプレートを見ると一目瞭然。


```
@php
if (! isset($scrollTo)) {
    $scrollTo = 'body';
}

$scrollIntoViewJsSnippet = ($scrollTo !== false)
    ? <<<JS
       (\$el.closest('{$scrollTo}') || document.querySelector('{$scrollTo}')).scrollIntoView()
    JS
    : '';
@endphp

```

対応は至ってシンプル。これだけ！
```
{{ $items->links(data: ['scrollTo' => false]) }}

```

もし逆にページ番号押下時に別の位置にスクロールさせたい場合は、以下のようにセレクタを指定すればよし！
```
{{ $items->links(data: ['scrollTo' => '#main']) }}
```

以上、またLivewire３で気づきがあれば投稿するかも。
QiitaのMarkdownについて

Qiita上のマークダウンは文中で改行しても
改行される。（他のViewerでは改行されなかった）

# シャープとスペースで見出しになる。
#シャープだけだと見出しにならない。

## シャープ２つとスペースで見出しが1段下がる。
##スペースがないと見出しにならない。

### シャープ３つ（以下同文）

    思ったより、１つ～２つの見出しの違いがない。
    ３つ以降は違いがはっきりする。

#### シャープ４つ
##### シャープ５つ
###### シャープ６つ
####### シャープ7つ

    見出しのシャープは６つまで？
    シャープが５つと６つで違いないぞ？


箇条書きは下記のように「1.  xxx」で記載できる。

1. test1(1. test1と記載)
1. test1(1. test1と記載)
1. test1(1. test1と記載)
1. test1(1. test1と記載)
1. test1(1. test1と記載)

1.test1
1.test1
1.test1
ドットの後にスペースがないと箇条書きにならない。

# 1. test1
# 1. test1
# 1. test1
見出しの場合、「1. 」を付けても箇条書きにならない。

    行の先頭にタブを付けると強調できる。

```
バックダッシュというのか、バッククオートというのか、
「`」を３つ「```」で囲むとコードエリアになる。
```
    タブとの違いが分からない。
    （親切な方が編集リクエストで教えていただきました）
    タブも改行できる。

# 「```」の場合、続けてプログラミング言語名を書くとコードが色付けされる
```c
int main(void)
{
    return 0;
}
```

    開始時に「```c」でsyntax的なカラーリングになる。
    終了時は「```」で良い。

# 空白インデントの場合
    int main(void)
    {
        return 0;
    }

別途、下記で調査。
https://qiita.com/Qiita/items/c686397e4a0f4f11683d
Pythonでポートフォリオを作っている理由

Q なぜPythonなの？他の言語（Java、php、ruby）とどう違うのか？

以下は、Pythonの特徴です。

•	書きやすく読みやすいシンタックス。
•	多彩なライブラリとフレームワークが豊富。
•	柔軟性が高く、ウェブ開発からデータ解析、AIまで幅広い用途で使用できる。
	
 
 
以下は、Javaとの違いについです。

Javaはトランスパイル言語。サーバーレスのときはPythonに劣る場合がある。
例えば、JVMからdockerを使う場合、立ち上げに時間がかかる。コールドスタートという。

また、1ファイルに1クラスのためファイルが多くなってします。Javaは主にアプリケーションやサーバーサイドの開発に使用される。


以下は、PHPとの違いについです。

PHPは主にウェブアプリケーションのバックエンド開発に特化している。Pythonはウェブ開発だけでなく、さまざまな領域で使用できる。
	
 

以下は、Rubyとの違いについてです。

RubyはRuby on Railsというフレームワークを中心にウェブアプリケーションの開発に使われる。Pythonはその用途がより幅広い。



Q Pythonがある事でJavaのJVMの良さが薄れているって本当？

PythonとJavaは、それぞれ異なる特性を持つプログラミング言語であり、用途や目的に応じて選ばれることが多いです。ただし、近年Pythonの人気が高まっているという背景から、いくつかのポイントでPythonがJavaやJVMの利点を影を潜めているという意見もあります。以下にその理由をいくつか挙げます。

1. **簡潔な文法**: Pythonは読みやすく、書きやすい文法が特徴です。これに対して、Javaは冗長な部分もあるため、初心者にとってはPythonの方が取っ掛かりやすいとされています。
 
2. **データサイエンスとAI**: PythonはデータサイエンスやAI分野で非常に人気があり、多くのライブラリやフレームワークが提供されています。これに対して、Javaは主にWebアプリケーションやエンタープライズアプリケーションの開発に使われることが多いです。

3. **スクリプト言語の特性**: Pythonはスクリプト言語であり、動的型付けのため開発速度が速いとされています。一方、Javaは静的型付けのため、大規模なアプリケーションやシステムの開発に向いています。

4. **教育と学習**: 近年のプログラミング教育ではPythonがよく取り上げられており、学習者の入門言語として選ばれることが多いです。

ただし、これらの点はあくまで一般的な傾向であり、JavaやJVMには以下のような利点もあります。

1. **パフォーマンス**: Javaはコンパイル言語であり、JVM上で動作するため、実行速度が速い場合が多いです。
 
2. **プラットフォーム独立性**: Javaの「Write Once, Run Anywhere」の原則に従い、異なるプラットフォームで動作するアプリケーションを簡単に開発することができます。

3. **堅牢性**: Javaは静的型付けのため、型のエラーをコンパイル時に検出することができ、バグの発見が容易です。

結論として、Pythonが増加している人気により、一部の領域ではJavaの利点が薄れてきているとも言えますが、JavaとJVMはその堅牢性やパフォーマンス、プラットフォーム独立性などの特性から、多くの企業やプロジェクトで引き続き利用されています。両者を適切に使い分けることが大切です。



Q SDKの情報がPythonだと豊富なんですか？

はい、Pythonは近年の人気と成長に伴い、多くの企業やオープンソースコミュニティがPython SDK（Software Development Kit）を提供しています。以下の理由でPythonのSDK情報が豊富であると言えます。


1. **人気と共同体**：Pythonは様々なアプリケーション、特にデータサイエンス、ウェブ開発、オートメーション、AI、機械学習などに広く使用されています。このような多様な利用シーンに対応するため、多くのSDKやライブラリが開発されています。

2. **拡張性**：Pythonは簡単に拡張できる言語であり、CやC++で書かれたモジュールを組み込むこともできます。これにより、高速な処理や特定の機能を持つSDKの開発が容易になっています。

3. **クロスプラットフォーム**：Pythonは多くのオペレーティングシステムで動作します。このため、PythonのSDKは様々なプラットフォームでの使用を目指して開発されることが多いです。

4. **AWS、Google Cloud Platform、Azureなどの大手クラウドプロバイダ**：これらの大手クラウドサービスプロバイダはPython用のSDKを提供しており、これによりクラウドリソースの管理や操作がPythonから容易に行えます。

5. **成熟したパッケージ管理システム**：Pythonのpipやcondaは、SDKやライブラリのインストール、管理を簡単にします。このようなツールの存在が、Pythonのエコシステムの成長を後押ししています。


これらの理由から、Pythonは多くの分野での開発に適しており、それに伴ってSDKの情報も豊富であると言えます。
MacBook Pro(M1 Pro)でDocker Engine Stopping...

## TL;DR
MacBook Pro(M1 Pro)でDocker Engine Stopping...のまま変わらない事象が発生。
MacBookProのソフトウェアアップデートで解決しました。

## 経緯
インターンでMacBookProを貸し出していただき、環境構築する際の一幕。

まず最初に
```
Cannot connect to the Docker daemon at unix://var/run/docker.sock Is the docker daemon running?
```
という`docker`実行時のエラーから始まりました。

普段Macユーザーではないのが災いし、OSバージョン古いとは思ってませんでした(´;ω;｀)
前に触ったのも1年前のインターンだったので、こんなことに……。

## 参考記事
https://qiita.com/ryomoucmei/items/f89406d675532c78497e

上記を参考に対処していたのですが、うまくいかず小一時間ほど悩みました。

最終的にOSアップデートで終わりました。

一時間返してくれ。
APIをたたいてみる①ツールを使ってリクエストを投げる

# 概要
APIを気軽にたたきたいが、何をどうすればたたけるかを軽く検証する。

# Azure OpenAI のAPIをたたいてみる
既に準備済のAzure OpenAI のAPIをたたきます。

とりあえずURLだけでたたいてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/d5dc421b-53dd-0545-8532-cced250f07a8.png)

このように雑にアクセスすると404が返ってきます。

必須な情報として、APIキーとPOSTするメッセージ情報があります。

これらをリクエストのボディー部分ではなくヘッダー部分に入れなければなりません。

# TalendAPITester を使ってみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/a7f661a1-0b93-4f34-5ed3-b04bec043203.png)

TalendAPITesterはAPIをたたけるツールです。

POSTを選択し、URL等を指定していきます。


https://learn.microsoft.com/ja-jp/azure/ai-services/openai/reference

Azure OpenAI の公式より、リクエストに必要な情報を調べます。

```
curl https://YOUR_RESOURCE_NAME.openai.azure.com/openai/deployments/YOUR_DEPLOYMENT_NAME/chat/completions?api-version=2023-05-15 \
  -H "Content-Type: application/json" \
  -H "api-key: YOUR_API_KEY" \
  -d '{"messages":[{"role": "system", "content": "You are a helpful assistant."},{"role": "user", "content": "Does Azure OpenAI support customer managed keys?"},{"role": "assistant", "content": "Yes, customer managed keys are supported by Azure OpenAI."},{"role": "user", "content": "Do other Azure AI services support this too?"}]}'
```

`-H`はヘッダーの意味です。
ヘッダーに
`Content-Type` : `application/json`
と
`api-key` : `Azureで指定されたAPIキーとなる文字列`
を入れていきます。
また `-d` はボディーという意味です。
ボディーにJSON形式で送りたいデータを入力しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/6440ab0f-97ad-0986-0f1b-d615a8b8836f.png)

この状態で右上のSENDを押してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/d3b4e34f-328a-a487-f251-fccf55280fc8.png)

ダメ見たいですね。
公式ページを見るとモデルのバージョン指定がいるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/8edd08af-8961-8fe6-600c-97273cde29bd.png)

実行してみたらいい感じでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/5e6fe6ff-d8ca-d538-2522-770ac6dc7a5e.png)

# まとめ
TalendAPITester はめっちゃ使いやすい。
Swaggerもいい感じなので使い分けは必要かも

APIをたたくイメージがつかめた。

# 追記 : JSON形式のダミーを返すWebサイトを見つけました。
https://jsonplaceholder.typicode.com/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1505183/4eb6ed75-9574-d7a5-b56a-3a016b8e40c7.png)

軽く何かテストしたいときとかに便利ですね
Discord.pyの使い方

### Discord.pyのインストール方法
Discord.pyを使うにはまずPythonとpipがインストールされている必要があります。その上で`pip install discord.py`コマンドでインストールできます。

### 基本的なBotの作成方法
Botのトークンを取得する方法
Discord Developersポータルから新しいアプリケーションを作成し、Botを追加します。するとTokenが発行されるのでこれをコピーしておきます。

Botを起動するための基本的なコード
```
import discord

client = discord.Client()

@client.event
async def on_ready():
print('We have logged in as {0.user}'.format(client))

client.run('TOKEN')
```
このようなコードでBotを起動できます。

イベントハンドラーの設定方法
```
@client.event
async def on_message(message):
if message.content.startswith('$hello'):
await message.channel.send('Hello!')
```
のようにデコレーターを使ってイベントハンドラーを設定します。

### Botの機能を追加する方法
コマンドの追加方法
```
@client.command()
async def hello(ctx):
await ctx.send('Hello!')
```
のようにコマンドデコレーターを使ってコマンドを追加できます。

リアクション追加の方法
```
@client.event
async def on_message(message):
if message.content.startswith('$thumb'):
await message.add_reaction('👍')
```
のようにadd_reactionメソッドを使ってリアクションを追加できます。

チャンネルの管理方法
チャンネルの作成、削除などを行うには`discord.TextChannel`クラスの各種メソッドを使います。

### Botをホストする方法
ローカルでのホスティング
Pythonスクリプトを実行したままにしておくことでローカルでホスティングできます。

クラウドサービスを使ったホスティング
HerokuやAWSなどのクラウドサービスを使えば24時間安定してホスティングできます。

### Discord.pyのドキュメントや参考になるサイト・コミュニティの紹介
公式ドキュメント:
https://discordpy.readthedocs.io/en/latest/

Discord.py公式サーバー:
https://discord.gg/dpy

Qiita Discord.pyタグ:
https://qiita.com/tags/discord.py
非同期でのNode.jsのReadStreamの振る舞いを確認してみる

# 前準備
## 環境
OS：Windows 11 Home 64 ビット オペレーティング システム
CPU：11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz   3.00 GHz
RAM：32.0 GB
Node.js：Node.js v20.4.0.

## 入力用テキストファイルを作成する
```in.txt
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
（中略）
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
```

## ログ出力用関数を準備する
```fDateTime.js
module.exports = function() {
    //formatted DateTime
    date = new Date();
    const yyyy = date.getFullYear();
    const mm = ('0' + (date.getMonth() + 1)).slice(-2);
    const dd = ('0' + date.getDate()).slice(-2);
    const hh = ('0' + date.getHours()).slice(-2);
    const mi = ('0' + date.getMinutes()).slice(-2);
    const ss = ('0' + date.getSeconds()).slice(-2);
    const ms = ('0' + date.getMilliseconds()).slice(-3);
    return yyyy + mm + dd + hh + mi + ss + '.' + ms;
}
```

## 機能を実装する
```fs_readStream.js
const fDateTime = require('.\\fDateTime.js');

const IN_FILE = "data\\in.txt";
const OUT_FILE = "data\\out.txt";

console.log("ファイル取得（非同期・stream）:"+IN_FILE);

const fs = require("fs");
const rStream = fs.createReadStream(IN_FILE);
const wStream = fs.createWriteStream(OUT_FILE);

rStream.on('data', chunk => {
    console.log(`chunk Length:${chunk.length} (bytes)`);
    return wStream.write(chunk);
});

rStream.on('end', () => {
    return wStream.end();
});
```


## 動作させてみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/830ff178-94bc-ddb6-358a-4c1514713d82.png)

## 振る舞い確認用のログを付加する
```fs_readStream_addDateTimeLog.js
const fDateTime = require('.\\fDateTime.js');

const IN_FILE = "data\\in.txt";
const OUT_FILE = "data\\out.txt";

console.log("ファイル取得（非同期・stream）:"+IN_FILE);
console.log(`main start:${fDateTime()}`);

const fs = require("fs");
const rStream = fs.createReadStream(IN_FILE);
const wStream = fs.createWriteStream(OUT_FILE);

rStream.on('data', chunk => {
    console.log(`chunk Length:${chunk.length} (bytes):${fDateTime()}`);
    return wStream.write(chunk);
});

rStream.on('end', () => {
    console.log(`readStream.on end  :${fDateTime()}`);
    return wStream.end();
});

console.log(`main end  :${fDateTime()}`);
```

## 動作させて非同期の振る舞いを確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/c51165a9-83bf-6ea4-5db1-70257a77e76d.png)

# 以下のサイトを参考にしました
[nodejs.org File system](https://nodejs.org/api/fs.html)
window10の環境構築 vue3 + TS + pinia

# install NODE
https://nodejs.org/en

```
node -v
```

# install YARN
```
npm -g i yarn
```
```
yarn -v
```

# install VUE
```
yarn global add @vue/cli
```
OR
```
npm -g i @vue/cli
```
```
vue --version
```

# install IDE
## Webstorm
https://www.jetbrains.com/ja-jp/webstorm/
## VsCode
https://code.visualstudio.com/
### plugins
- TypeScript Vue Plugin (Volar)
- Vue Language Features (Volar)
- Auto Close Tag
- Auto Rename Tag
- Vue Peek
- Auto Import
- Rainbow Brackets 2
- Path Intellisense

# Create Project
```
vue create project-name
```

# Vue3: UI + store + http + mock
```
yarn add ant-design-vue@4.x pinia axios axios-mock-adapter @fakerjs/faker
```

# Power-shell Command Access 
:::note warn
Set-ExecutionPolicy RemoteSigned -Scope Process
Stirlingで構造体編集 その2

# 概要
バイナリエディタStirlingで構造体編集、やってみた。
練習問題、やってみた。


# 練習問題
bmpファイルを新規で作れ。


# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/1ef98dba-614f-3658-c8da-99dc8a46e6ef.png)

# サンプルコード

```
         0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
0000000 42 4d 7e 00 00 00 00 00 00 00 3e 00 00 00 28 00
0000016 00 00 10 00 00 00 10 00 00 00 01 00 01 00 00 00
0000032 00 00 40 00 00 00 10 00 00 00 10 00 00 00 00 00
0000048 00 00 00 00 00 00 ff ff ff 00 00 00 00 00 00 00
0000064 00 00 7f fe 00 00 40 02 00 00 40 02 00 00 40 02
0000080 00 00 40 02 00 00 40 02 00 00 40 02 00 00 40 02
0000096 00 00 40 02 00 00 40 02 00 00 40 02 00 00 40 02
0000112 00 00 40 02 00 00 7f fe 00 00 00 00 00 00
```

以上。
【個人開発】Bardと一緒に0からのFlutterアプリ開発

# はじめに

前々からスマホアプリの開発に興味があったので、Bardと一緒に開発・リリースしてみました。Flutter自体触ったことがなく、また他AIもそうだと思いますが時々嘘を言います。まったく知識がないので本当のことの中に嘘（古い情報）を混ぜられるので苦しかったです。ですがやはりコードを書いてそれが動くのは面白かったです！

https://bard.google.com/chat?hl=ja

# 成果物

QRコードを読み込んで保存もできるアプリをリリースしました。以前、店員さんが見せてくれたQRコードを読み込んで会員登録をする機会があったのですが、操作を誤ってQRコードを読み込むところからやり直しになってしまいました。一度読み込んだものを保存しておいて、もう一度遷移する機能が欲しいと思ったので自分で作ってみました。
やってみたかったですがPCスペック、実機の都合上App Storeへのリリースはできませんでした。

https://play.google.com/store/apps/details?id=com.appli.qrs

余談ですが、QRコードという文言を商用利用するにあたって株式会社デンソーに問い合わせをする必要があったため行いました。とてもとても丁寧に対応・説明してくださいました。

https://www.denso-wave.com/ja/system/qr/contact/

# 利用状況

記事作成時点では…ユーザー数は5人です。そしてなんと**2円の広告収入**を得ることができました！とても嬉しいです、金額的には少額ですがモチベーションが上がりました！
また、QRコードというありふれた題材ということもあると思いますが、やはりDLしてもらうためには作ってリリースするだけではだめで、DLをしてもらうための準備も必要なんだなと改めて実感しました。ただ、このアプリは私自身でも利用していて満足しています！

# 機能

各画面単位で簡単に記載します。

## QRコードの読み取り画面

 `mobile_scaner` で実装しています。基本的にサンプルに従って導入することで十分に動作します。ただ今回は読み込み時に保存まで行いたかったので少し手を加えています。読み込み時に自動で保存するか否かの設定の変更も可能です。
また、私は必要になったことはなかったので実装する予定はありませんでしたが、同様アプリのレビューコメントでライトの機能が欲しいと書かれていたのでこちらでも実装しました。

https://pub.dev/packages/mobile_scanner/score

![](https://storage.googleapis.com/zenn-user-upload/462f7138c025-20231028.png)

## 一覧画面

小さな開発のため外にDBを持ちたくなかったので、保存時には `sqflite` に書き込んでいます。単純に保存したものを取得して一覧化しています。遷移先のタイトル要素を取得して、保存したQRコードのタイトルとして設定されるようにしていますが、書き換えも可能です。

https://pub.dev/packages/sqflite

![](https://storage.googleapis.com/zenn-user-upload/3d2340df3c3e-20231028.png)

## 問合せ画面

本当はチャット形式？できちんとユーザに対してきちんと回答ができるような作りにしたかったのですが、外にDBを持ちたくなかったこと、何より無知からのスタートだったので今回は断念しました。というわけで今回はGoogle Formのアンケート画面を埋め込んでいます。 `webview_flutter` を使って実装しています。

https://pub.dev/packages/webview_flutter

以下のようにすることでGoogle Formにパラメーターを渡すことも可能です。

https://hajiritsu.com/google-form-defalut-value/

```
@override
Widget build(BuildContext context) {
  return Scaffold(
    body: WebViewWidget(
      controller: WebViewController()
        ..loadRequest(Uri.parse("Formから取得したURL"))
        ..setJavaScriptMode(JavaScriptMode.unrestricted),
    ),
  );
}
```

![](https://storage.googleapis.com/zenn-user-upload/f2f05c18e03b-20231028.png)

# リリース

リリースに関する手順自体は色々な方が記事やブログなどで解説されているため部分的に残します。

## プライバシーポリシー

プライバシーポリシーを作成して、どこかの環境にデプロイする必要があります。以下で紹介されているように、プライバシーポリシーを作成してデプロイまでできるサービスがあるようです。私の場合はこちらではなく、色々な方のサービスのポリシーをを参考にさせていただきNotionに作成・Web公開をして対応しました。

https://note.com/danchi_kun/n/n216824317df6

## 広告

リリースそのものとは少しそれますが、利用状況を知る一つの指標かつモチベーションにもなるため `Google AdMob` を導入しました。リリースして1円の収益？を得たタイミングで規約違反との連絡があり広告がはがれてしまいました。理由としては問合せ画面としてGoogle Formを使用していたことで、外部（他者）のコンテンツに広告を貼り付けているという扱いになったようでした。今思えばですが当然ですね…。急ぎ修正をして審査に回しました。

https://admob.google.com/intl/ja/home/


# おわりに

最初にも書きましたが全く知識がない中、本当のことの中に嘘（古い情報）を混ぜられるので苦しかったです。とは言え、書籍など買わなくともそんな中でもちゃんと動くものを作れるのはすごい時代？だなーと思いました。もっと色々なことをしてみたくなりました。
やはり何かを作るっていいですね…！！