OmniAICreator/Qiita-1.07M huggingface dataset:
【Rails】refileでのエラー解消（wrong number of arguments）

## この記事の目的
- 現在学習中のRailsについての理解とアウトプット、振り返り用
- Railsのrefileで起きたエラーの解消について

## バージョン
```
ruby 3.2.0
Rails 7.0.4.3
```


## 起きたエラーについて
Railsのrefileを使用して画像投稿機能を作成している際に下記のエラーが発生しました
```
wrong number of arguments (given 3, expected 2; required keyword: object)
```
![スクリーンショット 2023-04-10 22.51.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/3aebf5eb-f780-367f-0f40-e5b8ba95d302.png)



## 原因
バージョンの違いみたいです

## 解消方法
- ①バージョンを変更する
- ②` attachment_field`→`file_field`に変更


### ①バージョンを変更する
バージョンを変更する方法については、[Ruby on Railsのrefileでwrong number of argumentsが発生したときの対処](https://qiita.com/YUTOKUBO2001/items/dc8e776f7abd0ed37be6)という記事がありましたのでそちらを参考にしてみて下さい


### ②` attachment_field`→`file_field`に変更
こちらについては記載通りattachment_field`→`file_field`に変更することでエラーを解消できました
```edit.html.erb
<div class="field">
    <%= f.label :profile_image, "プロフィール画像", class: "label has-text-warning" %>
    <%# <%= f.attachment_field :profile_image, class: "input" %> %>
    <%#  上記をしたの下記の記載に変更する %>
    <%= f.file_field :profile_image, class: "input"  %>
</div>
```
[Railsドキュメント(file_field)はこちらから](https://railsdoc.com/page/file_field)
こちらの変更をすることで下記のように表示できました！
![スクリーンショット 2023-04-10 22.16.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/79446207-21da-e3ac-0f2e-af80bd2465c6.png)

## 参考
[【プログラミング入門】Ruby on Rails でウェブアプリを作ってみよう ~ PART 2（実装①）](https://www.youtube.com/watch?v=uos2mowBrJA)
[Railsドキュメント(file_field)](https://railsdoc.com/page/file_field)
Cython3は凄く良い

# Cython3(現在はCythonベータ1)はとてもよい。

## `.py`をほぼ変更なく、`.pyx`化できる。
つまり、PythonのTypeHintがそのままCythonの型付にできる。

Cython2では`from __future__ import annotations`があるとエラーが生じてが、Cython3になってからはほとんどエラーなくなった。

それどころかTypeHintに示した型も理解してくれたので、Python3.9で開発したコードをそのまま.pyx拡張子に変えても動かせる。

### Debugでは`.pyx`を`.py`へ戻してDebugしている。
`.pyx`独自の文法を使わず、PurePythonモードの型指定を使っている(例: cdef:型指定→cython.declare(型、value)かTypeHintでも型指定できてるみたい)。それでもCython用に型指定できているようである。本当はプロファイラで確認しないと行けないのだが、、、。

なので、簡単なエラーは、Cythonで表示されるエラーをみる。`.py`で動いていたのに、`.pyx`で動かないのは、型指定誤りがほとんど(私の中では)。

コード拡張などにより、深いバグが見込まれる場合は、`.py`へ戻してデバッグして、`.pyx`へ戻す。この時、型指定誤りで苦しむが一瞬で済む。



## クラスの継承も可能になった
NumbaのNative化はは関数レベルだが、CythonだとクラスレベルでNative化できる。しかも、いつの間にか継承したクラスを含む.pyx化でも動く。(一応、Cython化されたクラス通しながら継承も可)

## プロファイラでしっかり確認
PythonオブジェクトをうまくWrapしてくれるため、もしかしたら、パフォーマンスが落ちる箇所があるかも。プロファイラで確認が必要かもしれません。今のところ、私の方はCython3にしてパフォーマンス上がっている(計算が短時間になっている)。

## 快適なのはPyCharmProのおかげ？
PyCharmProはCythonの構文解析は良いです。リファクタリングが効くなど`.py`同様の恩恵を受けられます。VSCodeでは残念ながらCythonは不十分です。(VSCodeでは、`.pyx｀があるとUnitTestコードがおかしく表示されたりする問題があります。)。

PyCharmProの比較ページでもCE版との相違にCythonサポートが書かれているので、Cythonの有用性を活かすことができます。
https://www.jetbrains.com/ja-jp/products/compare/?product=pycharm&product=pycharm-ce
-----
Pythonの遅さからPyPyやNumbaを使ったけど、今後は、スケーラビリティからCython3一択になった。将来はリリース時にはCodonによって型付と切り替えられるようになって欲しい。
kintoneプラグインの設定情報を漏れなく削除する

## はじめに
知ってる人にとっては超当たり前の内容ですが、公式ドキュメントには明記されてないので初心者向けに書いてみます。

## プラグインの設定情報 (config)

https://cybozu.dev/ja/kintone/docs/js-api/plugins/set-config/

`config`に空オブジェクトを渡せば削除されます。

```js
kintone.plugin.app.setConfig({})
```

削除後に`getConfig()`すると、空オブジェクトが返る。
```js
kintone.plugin.app.getConfig('plugin-id') // {}
```



## 外部 API の実行に必要な情報 (proxyConfig)

https://cybozu.dev/ja/kintone/docs/js-api/plugins/set-config-for-proxy/

`url`と`method`を明記して、`headers`と`data`の両方に空オブジェクトを渡せば削除できる。

```js
kintone.plugin.app.setProxyConfig('https://example.com/api.json', 'POST', {}, {})
```

`getProxyConfig()`すると`{"headers":{},"data":{}}`が返ってくるかと思いきや、`null`が返ってくる。これはスッキリして良いですね。
```js
kintone.plugin.app.getProxyConfig('https://example.com/api.json', 'POST') // null
```

URLとHTTPメソッドの組み合わせをキーに設定を管理しているので、削除もその組み合わせ単位でしかできないっぽい。

### 設定済みの「URLとHTTPメソッドの組み合わせ」一覧

proxyConfigの場合、設定済みのURLとHTTPメソッドの組み合わせは自分で覚えておく必要があります。**もし組み合わせを忘れてしまったら確認も削除もできなくなっちゃう**ので、ちょっと勘弁してほしい。「自分の作ったアプリのプラグイン設定に、実は何かしらの機密情報がまだ入ってるのでは？？」と疑心暗鬼になってしまったら夜も眠れません :sob: 

そんなときの裏APIであります！
プラグイン設定画面で↓を実行すると、

```js
console.log(cybozu.data.page.APP_PLUGIN_PROXYCONFIGS)
```

こんな配列が返ってきて、設定済みの情報を確認できました！

```json
[
  {
    "dataJson": "{\"key\":\"value\"}",
    "headers": {
      "x-api-key": "xxxxx"
    },
    "method": "POST",
    "url": "https://example.com/api.json"
  }
]
```

これは非公式APIなので、予期せず仕様が変わるかも知れません。
使う場合は自己責任でお願いします！

というかサイボウズさん、これくらいは標準のJS APIで確認させてくださいよー。

ではまた！
rubyenvにパスを通す

# rbenvにPATHを通す
rbenvコマンドを利用するために、rbenvにpathを通します。
pathを通すとは、コマンド実行ファイルを探しに行くパスを追加することです。


## 手順
自分のターミナルで起動しているシェルの確認
```
$ echo $SHELL
```
/bin/bashのように最後がbashなら、bashが起動
/bin/zshのように最後がzshなら、zshが起動

起動しているシェルによってPATHを記述する設定ファイルが異なります。
bashの場合は~/.bash_profile、zshの場合は~/.zshrcです。

### bashの場合
```
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi' >> ~/.bash_profile
$ source ~/.bash_profile
```
### zshの場合
```
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.zshrc
$ echo 'if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi' >> ~/.zshrc
$ source ~/.zshrc
```

# Rubyをインストールする
以下のコマンドでインストール可能なrubyのバージョンを確認
```
$ rbenv install --list-all
```
```
Available versions:
  1.8.5-p52
  1.8.5-p113
  1.8.5-p114
  ---省略---
  2.6.0
  2.6.1
  2.6.2
  2.6.3
  2.7.0-dev
  2.7.0-preview1
  2.7.0-preview2
  2.7.0-preview3
  2.7.0-rc1
  2.7.0-rc2
  2.7.0
  2.7.1 
  2.8.0-dev
 ```

それでは、以下のコマンドを実行
```
$ rbenv install 2.6.3
```
インストールが完了したら、PC内で共通に使うためにグローバルで利用するバージョンを設定

```
$ rbenv global 2.6.3
```

また、今いるディレクトリでのRubyのバージョンも2.6.3に変更
```
$ rbenv local 2.6.3
```
Rubyのバージョン情報を確認します。

```
$ ruby -v
ruby 2.6.3p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin19]
```

これでrubyのバージョンを設定できました。
必要なバージョンのrubyをインストールして、切り替えることができます。

:::note info
pathの設定は結構忘れがちなので注意しましょう！
pathが通っていない場合は、いくらrbenv local(global)で設定しても反映されません。
:::
Google Colaboratory を使ったメモ【Colaboratory】

google Colaboratory を使ったので、これまで利用したパッケージのインストールと注意点について自分用のメモを残しておく。


# PyMC (PyMC3)
Colabo ではPyMC3ではなくPyMCを利用することを推奨している。[参考](https://discourse.pymc.io/t/google-colab-update-pymc3-is-being-replaced-by-pymc-v4-faq/10235)
Colaboratoryではすでにライブラリが入っているため 
```python
import pymc as pm
```
ですぐに使える. 

なので[Pythonではじめるベイズ機械学習入門](https://github.com/sammy-suyama/PythonBayesianMLBook)のサポートページではColaboratoryを使って実装していると書かれておりPyMC3を利用しているが実際は PyMCを利用したほうが良い。
どうしてもPyMC３で実装したい場合はKaggle のノートブックだとすぐに使えるのでそちらを利用するのが良い.

# YOLOv5
まずgithub から YOLOv5を clone する.　
```python
!git clone https://github.com/ultralytics/yolov5
```
clone したリポジトリの requirements から pip install を行う
```
%cd yolov5/
!pip install -qr requirements.txt
```



# 参考ページ
- [pymcを使ってベイズ推定による線形回帰](https://qiita.com/miso_taku/items/b9ebb1753755cefc6fbc)
- [Google ColabでYOLOv5を使って物体検出してみた](https://qiita.com/shoku-pan/items/31bf3c975b73db153121)
パソコンを新規設定するときにマストのアプリなど

パソコンを買い替えたり、職場のパソコンが支給されたりして
新たに設定をする必要があるかと思います。

そのときに最低限インストールしておいた方がいいアプリケーションをまとめてみました。


- google chrome
- slack
    
- VSCode
これは拡張機能も設定する必要がありますね。
- Docker Desktop on Mac
[https://docs.docker.com/desktop/mac/install/](https://docs.docker.com/desktop/mac/install/)
    
- DBeaver(SQLクライアントソフト)
[https://dbeaver.io/download/](https://dbeaver.io/download/)
    
- DisplayLink Manager(appleシリコンPCの画面拡張ツール。appleシリコンの人は必須)
[https://www.synaptics.com/products/displaylink-graphics/downloads/macos](https://www.synaptics.com/products/displaylink-graphics/downloads/macos)
    
- Homebrew
参考(M1はterminalの設定を変更してからHomebrewをインストールする)：
[https://qiita.com/___fff_/items/17655df4e80ebadd8fc3](https://qiita.com/___fff_/items/17655df4e80ebadd8fc3)
参考(インストール方法)：
[https://qiita.com/zaburo/items/29fe23c1ceb6056109fd](https://qiita.com/zaburo/items/29fe23c1ceb6056109fd)
    
- rbenv
参考(Cannot install under Rosetta 2 in ARM default prefixエラーの対応)：
[https://webrandum.net/cannot-install-under-rosetta2-in-arm-default-prefix/](https://webrandum.net/cannot-install-under-rosetta2-in-arm-default-prefix/)

rbenvの場合はパスを通す必要があるので忘れずにしましょう。
転職ドラフトでプレゼントと素敵な転職先をGETしよう！


# 転職ドラフトとは

[転職ドラフト](https://job-draft.jp/)は **「月に一度のドラフトで、求職者が登録したレジュメを見た参加企業が、気になった人を指名する」** サービスです。
指名を受けてからはカジュアル面談、面接、コーディング試験等の一般的な採用フローがあります。
とりあえず登録してみて、どんなサービスか試してみよう。
`プレゼント(後述)` もあるし、所有スキルまとめたいし、ご縁のある企業があれば最高だし！
結論としてまだ転職先は決まっていませんが、良いサービスだと確信できたので紹介していきます。

## プレゼントについて

転職ドラフトでは、**友達紹介キャンペーン** があります。
紹介コードを入力して登録し、転職ドラフトの審査を通過すると豪華プレゼントがもらえます。
`TYZP` が私の紹介コードです。

以下が審査通過でもらえるプレゼントの一覧です。

> お好きな O’REILLY JAPAN の本 1 冊（税込 5500 円以内）
> 転職ドラフトオリジナル ドラフトビール 6 本入り
> ACTUS ギフトカタログ Straw（ストロー）
> Amazon ギフト券 3000 円分

IT エンジニアにとって、`O’REILLY JAPAN`は特に魅力的ですね！
プレゼントまでの流れは以下になります。

> 友達紹介コードを入力して審査通過をする
> 次回のドラフトが開催され、返答期間が終了する
> 運営から、欲しいプレゼント、送付先などを尋ねるメールが届く
> メール記載の申請用フォームに回答する
> 順次、プレゼントが発送される

## 私について

文系大学を卒業。
IT4 年目。
販売管理ソフトのベンダーで 1 年半ちょっと。
SES で要件定義〜テスト、アジャイル等で計 1 年半ちょっと(現職)。

主な使用技術は

- VB.NET
- Python
- ShellScript
- Java
- VB6.0

## 登録前の私見

一見、指名されないと選考にすら進めないので、他の転職サイトと比べて以下のように思われるのではないでしょうか。
**「選考フローが遅くならないか？」**
**「求職者が不利なサービスではないか？」**
**「絶対転職するほどの熱量はないけど良いのか？」**
この 3 点は、転職ドラフト登録前の私の感想でした。
実際は経歴の棚卸しや、所謂イケてる企業の需要が知れて思ったよりも良い印象に変わりました。

## レジュメについて

転職ドラフトに登録すればすぐにドラフトに参加できるわけではありません。
レジュメを登録し、審査通過をした場合のみドラフトに参加することができます。
審査とある通り、レジュメの記載内容も細かく行う必要があります。
基本プロフィール、参画したプロジェクト概要、所有スキル、条件等...
詳しくは[こちら](https://job-draft.jp/articles/443)
レジュメ作成は大変ですが、自分のスキルについて棚卸しができるので個人的には苦になりませんでした。
転職有無はともかく、IT エンジニアは常に自分のスキルを俯瞰できるようにすると次の学びにも繋がるので、これを機会に詳細なレジュメ作成をおすすめします！
私自身、所有スキル(業務系&機械学習)と企業の需要(Web 系)のギャップを受けました。
現在 Web 開発の勉強やプロジェクト内で Web 開発を進めています。

## 審査について

審査後にはフィードバックもあります。
ドキュメント能力も IT エンジニアには必須のスキルです。
手短にまとめて提出して、フィードバックを参考に手早く修正する。
繰り返しになりますが棚卸しにもなるので今後の良い学びになります。
アウトプットがあれば記述するべき、や分類を小分けにすると良い等、無料で(かつ素早く)ここまで詳細なフィードバックをいただけると思いませんでした。
この時点で良いサービスだと確信しましたね(笑)

## 私の実体験

私自身、遅くとも 2023 年中には転職先を決める予定でいます。
ただプロジェクトの兼ね合いもあり、すぐに転職できるわけではないため市場調査と市場価値、必要とされるスキルを学ぶ目的もあって登録しました。
審査通るか不安でしたが、とりあえずプロジェクト概要を 1 つだけ書いて軽くまとめて提出したら数日後にあっさり通りました。
詳細を書く間もなくドラフトが始まってしまいましたが、現職より 1.5 倍強で指名もいただきました。[^1]
[^1]:ご縁には至りませんでしたが、2 倍超の指名もいただきました。
実力もそれに見合うように日々鍛錬を続けます。

ドラフトが終了してプレゼント(名著である **『データ指向アプリケーションデザイン』(5000 円強)**)もいただき、良い体験となりました。
今後も転職ドラフトを続けていき、良いご縁があればと思っています。

## メッセージ

一般的な転職では前職給を(謎の職能給や固定残業代で)若干上回るような足元も見方をする(現職)場合もありますが、転職ドラフトでは指名時に年収もオファーしてくれます。
私や他の方のオファー金額を見る限り、一般的な IT 企業勤務の方であれば年収を大きく上げることも現実的だと思います。
ある程度経験あればオファー狙えると思います。特に Web 系や AWS 等のモダンインフラは特に需要もあって経験が浅くてもチャンスは多いです。
転職ドラフトで転職できたら、その記事も書かせていただきます！

[転職ドラフト](https://job-draft.jp/)
紹介コード`TYZP`
reactでjsonデータを取得した。

# 概要

reactで外部のjsonファイルのデータを読み込む依頼が来た。
昔phpとかjavascriptでやったことがあったが、reactではどうすれば良いか分からなかった。
めちゃぐくってみて学んだことを書いてみた。

# やってみた。

```react

const [holidayData, setHolidayData] = useState([]);

const JSON_URL = 'holiday.json';
useEffect(() => {
    fetch(`${process.env.REACT_APP_COMMON_IMG_PATH + JSON_URL}`, { method: 'GET' })
      .then(res => res.json())
      .then(data => {
        setHolidayData(data)
      })
}, []);

```
fetchで、JSONファイルのURLを書いた。
GETメソッドで取得するようにした。

fetchしたJSONファイルのresponseの値を取得する。


```react

<div>{holidayData.content}</div>

```
最後は取得したデータをVIEW出す。
結果は以下のようになる。

![sgdsgvs.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421654/70667906-10ff-c309-d1ff-9d00ff6a8655.jpeg)
LINE BOT + ChatGPT開発お助け！実行中の Pythonを VSCode でデバッグする手順(Flask)

# はじめに

みなさんこんにちは。
ChatGPT が大盛況ですね。

今、LineBotを作っているのですが、バックエンドを、OpenAI を呼び出すようにしたいわけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2242133/e38673fb-7290-3fc2-e7e4-d572ffb63968.png)

こんな感じで出来上がったんですが、
ハンドラーのコールバックでデバッグして、Line側からコールバックされたときのパラメータをウォッチしたいけどできない。。

というお困りごとが結構あるのかなぁと思い、
アタッチによる手順をご紹介。

# セットアップ
## Extension
この辺を入れましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2242133/36413649-8358-ca48-12e4-1d5e7e364f7c.png)

## デバッグのセットアップ
デバッグアイコンをクリックした後、RUN AND DEBUGのプルダウンを選択して、「Add Configuration」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2242133/302ad305-0273-aea1-0205-30b046998591.png)

Configurationの種類が出るので、「Python」を選ぶ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2242133/b9e61d7f-5a26-9d93-c6af-f5f116c03290.png)

そうすると、Pythonの中でできること一覧が出るので、「Remote Attach」を選ぶ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2242133/dd732817-ae98-ce0e-37fc-042f9490ed1e.png)

次いで、ポート。ローカル開発しているなら、localhostのままでOK。（今回は、flaskを、localhost 5000で起動する）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2242133/2a11e525-1c04-2474-5148-03af59bb42ae.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2242133/7fee754b-1177-7eaa-e87b-e15e35ddb177.png)

OK。

LINE BOTからのコールバックは、HTTPSである必要があるので、「ngrok」をダウンロードして、HTTPSをローカルで疑似的に起動。
このHTTPSパスを、WebHookに登録しておく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2242133/3b4df75e-8ab8-291e-cf55-81050488ce87.png)

※この赤い部分に出てきたパスですね。

これでOK。

# デバッグ開始
まずは、FLASK・ngrokどちらもターミナルで起動しておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2242133/cf1c4c67-180f-5cd0-e4a8-746b67f30407.png)

F5 キーで、上記で作ったデバッグを開始。この時pythonプロセスがいくつか出てくるけど、デバッグしたいファイルを実行しているプロセスを探す。今回は、「chat.py」なので、そのファイルを実行しているプロセスを探す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2242133/f1827bdc-4d25-f544-0511-922492d28de1.png)
※二つヒットするはずなので、どちらがブレイクできるかは確かめてみてください。

して、LINEでチャットを送信。
しっかりブレイクしていることが確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2242133/b4efb1b1-121c-c44d-78a5-c9c9e910a728.png)


こんな感じでやれば、ChatGPT ・ LINE BOT途中の、「実際にはどんな変数が・・・」というお悩み、
かなり減らせるんじゃないかなぁと思った次第！

参考にしてみてくださいませ！

それではまた会いましょう！

# 免責事項
本記事は、著者が独自で調査・検証を行った内容で、所属企業やいずれかの企業の公式見解に基づきません。
また、本記事を参考にして行った作業に関して発生するすべての損害、問題、課題について、当方では一切の責任を負えませんのであらかじめご了承ください。
SELECT権限が付与されていない問題に対する解決方法（VB.NET）

# 背景
アプリケーション側からSQL Serverへ、SELECT文のクエリを投げたところ、エラーが発生した。
エラー内容：エラーが発生しました：SELECT権限がオブジェクト～で拒否されました。
![無題z.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/7b3848e7-f61e-2b66-f69d-543f1c98e91a.png)

# 原因
SELECT操作に必要な権限が与えられていないことが原因

# 対処法
権限を付与したいユーザーを選択し、プロパティを確認する。
![無題y.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/d56df839-2fcf-9baa-ec56-419ad425e7b1.png)
対象のデータベースのロールメンバーシップに、db_datareaderにチェックをつける。
![無題x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/262d56bf-bdca-a34a-8b4a-ea5e63831d3f.png)

# ポイント
アプリケーション側からSQL Serverへアクセスする際、testユーザーでアクセスするようにコーディングしています。そのため、SSMS側の管理者がtestユーザーに対して、操作の権限を付与しなければなりません。読み込みに限らず、書き込みに関しても同様に、付与することができます。

# 注意事項
- この記事では、SQL Server、SSMS、visual studioを使用しているので、試してみたい方は事前に準備が必要です。

# この記事は誰向けの記事か？
- SELECT権限が付与されておらず、解決法が分からない人

# 環境
- OS：Windows10
- [SQL Server](https://www.microsoft.com/ja-jp/sql-server/sql-server-downloads)
- [SQL Server Management Studio（SSMS）](https://learn.microsoft.com/ja-jp/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver16):v19.0.2
- [visual studio 2022](https://visualstudio.microsoft.com/ja/vs/)

# 本記事における注意事項
- 本記事は、備忘録としてまとめたものになります。
- 他の方の参考になる可能性も踏まえて、一般公開も行なっております。
- また記載内容はすべて、正しい内容が記載されているとは限りません。
- 誤った内容を見つけた場合は、ご指摘をお願いいたします。
iOSアプリをリリースする際に、必要な文章をChatGPTに手伝ってもらう私の手順

アプリをリリースする際に必要な文章があり、文章を考えることが面倒な私は、できるだけChatGPTを用いるようにしています。そこで、どのように私が行っているかを書き留めておく。

・プロモーションテキスト
・説明文
が主な文章や単語が必要なところである。


文字制限は、
プロモーションテキストは１７０字
説明文は4000字
キーワードは１００字
であり、この字数制限の中で、できるだけわかりやすく、文章を入力する必要がある。

### プロンプトの作成

プロモーションテキストの場合は、
```
下記のアプリの内容から、プロモーションテキストを１７０字で、文章を作成してください。
```
説明文の場合は、
```
下記のアプリの内容から、説明文を4000字で、文章を作成してください。
書き方としては、
・段落のタイトル
段落の内容

・段落のタイトル
段落の内容

・段落のタイトル
段落の内容

上記の記載方法で説明文を作成してください。
```

英語の文章を作成する際も、文字制限の数は同じなので、
最後に
```
出力する内容はすべて英語で行ってください。
```
と付け加えましょう。

### アプリ概要

今回作成する私のアプリの概要としては、
```
iPhone・iPadで数字を読み上げながら、
カウントダウン・カウントアップすることが可能なアプリを作成。

機能リスト
・カウントダウン・カウントアップの設定の変更が可能。
・読み上げる数字の言語設定が可能
・読み上げ速度や、読み上げの間隔、読み上げる声のトーンの調整が可能。
・特定の値から０まで数えると、元の値まで戻り、特定の値から繰り返し読み上げることが可能です。繰り返した回数をセット数としてカウントすることが可能。

使用用途
なにかの作業を一定の時間の間隔で行っていて、その回数をカウントしたいとき。
例えば
運動する際に、一定の回数を、一定の時間の間隔でカウントして、セット数を数えて欲しいときなど
```
です。箇条書きで、機能・使用用途を記載する。

### 出力された結果
プロモーションは、　178字が出力された。

```
iPhone・iPadで数字を読み上げながらカウントダウン・カウントアップできるアプリが登場！言語設定や読み上げ速度、声のトーンなどの調整が可能。特定の値から０まで数えて元の値まで戻る反復機能も搭載。運動やトレーニング中のセット数カウントや、一定の間隔で何かを数えたいときに最適です。設定変更も簡単で使い勝手が良く、作業やトレーニングの効率化に役立ちます。
```

説明文は、1397字が出力された。

```
iPhone・iPadで数字を読み上げながら、カウントダウン・カウントアップすることが可能なアプリをご紹介します。このアプリは、作業やトレーニングなど、一定の時間の間隔で回数を数える必要がある場面で非常に便利です。

【機能リスト】

以下は、このアプリの主な機能です。

・カウントダウン・カウントアップの設定の変更が可能。
このアプリでは、カウントダウンまたはカウントアップの設定を変更することができます。例えば、運動をする際にはカウントダウンを選択して、あと何回で終わるかを把握することができます。逆に、何回も繰り返すトレーニングを行う際にはカウントアップを選択して、何回目かを数えることができます。

・読み上げる数字の言語設定が可能。
このアプリでは、読み上げる数字の言語設定を変更することができます。英語、日本語、スペイン語、中国語など、様々な言語に対応しています。自分の使いたい言語に設定して、より使いやすくカスタマイズしましょう。

・読み上げ速度や、読み上げの間隔、読み上げる声のトーンの調整が可能。
このアプリでは、読み上げる数字の速度や間隔、声のトーンを調整することができます。自分の聞きやすい速度やトーンに設定して、より快適な使用感を得ることができます。

・特定の値から０まで数えると、元の値まで戻り、特定の値から繰り返し読み上げることが可能です。繰り返した回数をセット数としてカウントすることが可能。
このアプリでは、特定の値から0まで数えると、元の値まで戻り、繰り返し読み上げることができます。この機能を使えば、一定の回数を何セットか行うトレーニングをする際に非常に便利です。また、繰り返しの回数をカウントすることができるため、自分のトレーニングの成果を数値化することもできます。

【使用用途】

このアプリは、運動やトレーニングの際のセット数のカウントだけで
なく、仕事や勉強の際にも使うことができます。例えば、何回かに分けて読書をする際に、一定の時間を設定して読むページ数をカウントすることができます。また、長時間の作業をする場合にも、一定時間ごとに休憩を入れるためのタイマーとしても使えます。このアプリを使うことで、自分の作業の進捗状況を把握し、効率的な時間管理ができるようになります。

【使い方】

このアプリは、非常に使いやすくシンプルな操作方法をしています。最初に、カウントダウンまたはカウントアップの設定を行います。次に、読み上げる数字の言語設定や読み上げの速度、トーンの調整を行います。そして、特定の値から繰り返し読み上げる場合には、繰り返し回数を設定します。最後に、開始ボタンを押してカウントを開始します。カウントが進むにつれて、読み上げられる数字が画面に表示され、声で数字が聞こえます。カウントが終わったら、画面に結果が表示され、再度カウントを開始することもできます。

【まとめ】

このアプリは、一定の時間の間隔で回数を数える必要がある場面で非常に便利なアプリです。運動やトレーニングだけでなく、仕事や勉強の際にも使うことができます。カウントダウン・カウントアップの設定変更、読み上げる数字の言語設定、読み上げ速度やトーンの調整など、様々な機能を備えています。シンプルな操作方法で、使いやすさにも配慮されています。是非、このアプリを活用して、より効率的な作業やトレーニングを行ってみてください。
```

上記の出力結果を、自身で修正し、アプリをリリースしていきます。
以上です。

他にも良い方法があれば、コメントいただけると大変うれしいです。
良かったと思ったら、いいねやTwitterのフォローよろしくお願いいたします！

https://sites.google.com/view/muranakar
個人でアプリを作成しているので、良かったら覗いてみてください！
【AtCoder】Fortranを用いたABC297A - Double Clickの解説

## 背景
- AtCoder Beginner Contest 297に参加しました。
- 自身のプログラミング技術の向上と、Fortranの発展を願って投稿します。
(Fortran使ってる人が6000人中2人でした。かなしい。)
- [B問題](https://qiita.com/onodera/items/89fb0d61cc5a9df60222)と[C問題](https://qiita.com/onodera/items/963fd3bb9e970174227c)はこちら。(記事が長くなるので分けました)

## 実行環境
- Macbook(M1)
- Docker
- VsCode
- Fortran(gcc version 10.2.1)

## 問題内容
[問題文](https://atcoder.jp/contests/abc297/tasks/abc297_a)はこちらです。
いろいろ書いてありますが、内容は次のとおりです。

```N回```存在する以下の様なマウスの入力時刻に対して、ダブルクリックが```1つでも成立しているか```を調べます。
```math
T_1,T_2,T_3 ... T_N
``` 

ダブルクリックの成立は、前後のマウスのクリック時間Tが```判定時間D以下```であるかを見て判断します。式にすると以下の様になります。
```math
T_i+1 -T_i <= D
``` 

ダブルクリックが１度でも成功していれば、その時間を出力します。
一度も成立していなければ、-1を出力します。

## 解説ポイント
基本的な考え方は、[公式の解説(C++)](https://atcoder.jp/contests/abc297/editorial/6159)の通りとなります。

以下はFortranでのポイントです。
- マウスのクリック数はN回となっており、サイズが分かりません。
従って、```allocatable属性```を用いて動的に配列を割り当てます。

- ダブルクリック判定は、```do文```を用いて隣り合う数字を調べることで行います。
- 一度でもダブルクリック判定があれば残りは不要なので、```stop```を用いて処理を終了させます。
- do文が全て回って次の処理に移った場合、該当箇所なしとなり-1を出力します。
- do文で調べる範囲は、```1からN-1```になります。N番目は後ろがないので不要です。
- ```出力は左詰め```が指定されています。従って、書式を指定する必要があります。

## サンプルコード
```fortran
program A
    implicit none
    integer::N, D, i
    integer, allocatable :: T(:)

    read *, N, D
    allocate (T(N))
    read *, T

    do i = 1, N - 1, 1
        !print *, T(i + 1), '-', T(i), '=', T(i + 1) - T(i)
        if (T(i + 1) - T(i) <= D) then
            write (*, "(i0)") T(i + 1)
            stop
        end if
    end do
    write (*, "(i0)") - 1

end program A
```
【AtCoder】Fortranを用いたABC297B - chess960の解説

## 背景
- AtCoder Beginner Contest 297に参加しました。
- 自身のプログラミング技術の向上と、Fortranの発展を願って投稿します。
(Fortran使ってる人が6000人中2人でした。かなしい。)
- [A問題](https://qiita.com/onodera/items/6b8870192d08f2a2805d)と[C問題](https://qiita.com/onodera/items/963fd3bb9e970174227c)はこちら。(記事が長くなるので分けました。)

## 実行環境
- Macbook(M1)
- Docker
- VsCode
- Fortran(gcc version 10.2.1)

## 問題内容
[問題文](https://atcoder.jp/contests/abc297/tasks/abc297_b)はこちらです。
いろいろ書いてありますが、内容は次のとおりです。

```長さ8文字```の文字列Sには、K,Qが```ちょうど１文字```、R.B,Nが```ちょうど２文字```含まれています。

Sの中身を調べて、以下の条件が```どちらも満たしているか```判定します。
>　1. 2つのBの位置が左から数えて```偶数•奇数```もしくは```奇数•偶数```の位置にあるか。
　　(例えば、1文字目、２文字目や４文字目、5文字目なら良い)

>　2. Kの文字がRの文字に挟まれているかどうか。
　　(例えばRKR○○○○○やR○○○○K○Rなら良い)

条件を満たしていれば、```YES```と出力します。満たしていなければ、```No```と出力します。


## 解説ポイント
基本的な考え方は、[公式の解説(C++)](https://atcoder.jp/contests/abc297/editorial/6170)の通りとなります。

以下はFortranでのポイントと注意点です。
- K,Q,R,B,Nは```必ず```指定した文字数含まれています。Kが１文字もないケース等は考える必要はありません。
- 文字型の状態で１つずつ比較するのは大変です。
従って、文字ごとに```出現位置(左から何文字目か)を数字で管理する```と楽です。

- 偶数と奇数の判定は```mod```で処理した余りから判定します。
- YesとNoは```左詰め```で出力します。従って、書式を指定する必要があります。


## サンプルコード
```fortran
program ABC297b
    implicit none
    integer(8) i, j, k, K1
    integer(8) B2(2), R2(2)
    character(8):: S

    j = 1
    k = 1
    !write (*, *) '>> S'
    read (*, *) S

    do i = 1, 8
        if (S(i:i) == 'B') then
            B2(j) = mod(i, 2)
            j = j + 1
        else if (S(i:i) == 'K') then
            K1 = i
        end if
        if (S(i:i) == 'R') then
            R2(k) = i
            k = k + 1
        end if
    end do

    !print *, 'R=', R2; print *, 'B=', B2; print *, 'K=', K
    if (R2(1) < K1 .and. K1 < R2(2) .and. B2(1) .ne. B2(2)) then
        write (*, "(a)") 'Yes'
    else
        write (*, "(a)") 'No'
    end if
end program

```
【AtCoder】Fortranを用いたABC297C - PC on the Tableの解説

## 背景
- AtCoder Beginner Contest 297に参加しました。
- 自身のプログラミング技術の向上と、Fortranの発展を願って投稿します。
(Fortran使ってる人が6000人中2人でした。かなしい。)
- [A問題](https://qiita.com/onodera/items/6b8870192d08f2a2805d)と[B問題](https://qiita.com/onodera/items/89fb0d61cc5a9df60222)はこちら。(記事が長くなるので分けました。)

## 実行環境
- Macbook(M1)
- Docker
- VsCode
- Fortran(gcc version 10.2.1)

## 問題内容
[問題文](https://atcoder.jp/contests/abc297/tasks/abc297_c)はこちらです。
いろいろ書いてありますが、内容は次のとおりです。

```長さW```の文字列Sが```H個```あります。
```math
S_1 ,S_2 ,S_3 ... S_H
``` 
文字列$S_i$の中身には、```.```もしくは```T```が合計でW文字分格納されています。

$S_i$の隣り合う文字が```TとT```の場合、```j番目をP```、```j+1番目をC```に書き換えます。
つまり、```TT```を```PC```へ書き換えます。

この書き換えを$S_1$から$S_H$まで繰り返し、結果を出力します。


## 解説ポイント
基本的な考え方は、[公式の解説(C++)](https://atcoder.jp/contests/abc297/editorial/6175)の通りとなります。

以下はFortranでのポイントと注意点です。
- 隣り合う文字がTとTになっているかどうか、```do文```を用いて開始位置jをずらしながら調べます。
- 結果は```左詰め```で出力します。従って、書式を指定する必要があります。


## サンプルコード
```fortran
program ABC297b
    implicit none
    integer(8) i, j, k, K1
    integer(8) B2(2), R2(2)
    character(8):: S

    j = 1
    k = 1
    !write (*, *) '>> S'
    read (*, *) S

    do i = 1, 8
        if (S(i:i) == 'B') then
            B2(j) = mod(i, 2)
            j = j + 1
        else if (S(i:i) == 'K') then
            K1 = i
        end if
        if (S(i:i) == 'R') then
            R2(k) = i
            k = k + 1
        end if
    end do

    !print *, 'R=', R2; print *, 'B=', B2; print *, 'K=', K
    if (R2(1) < K1 .and. K1 < R2(2) .and. B2(1) .ne. B2(2)) then
        write (*, "(a)") 'Yes'
    else
        write (*, "(a)") 'No'
    end if
end program

```
RaspberryPi上でFlaskアプリをgunicornから本番環境として起動する

# 本番用仮想環境

1. ラズパイのOSをアップデートする。

```
sudo apt-get update
sudo apt-get upgrade
```

2. 本番用仮想環境を作成する。`deploy`という名前。

```
python -m venv deploy
source deploy/bin/activate
```

# 必要ライブラリのインストール

```
pip install flask
pip install gunicorn
pip install opencv-python
pip install requests
```

# gunicornの起動

`base.py`の中の`app`を起動する。
ポートは5000にした。

```
gunicorn -b :5000 base:app
```
webhookではなくteamsチャネルのメアドを使って、kintoneからの通知をteamsチャネルに投稿させる方法

## [teams側の準備]
■ チームを作る
■ チャネルを作る
■ チャネルのメールアドレスを取得する。
「チャネル名右の３点リーダー ＞ メールアドレスを取得」
　※ "詳細設定"から「だれでもこのアドレスに電子メールを送信できます」または「次のドメインのメール アドレスのみ。（cybozu.com）」などに設定しておく。kintoneからの通知は個別カスタマイズしていなければ(no-reply@cybozu.com)から届くため。
■ チャネルのモデレーションをオフにしておく
「チャネル名右の３点リーダー ＞ チャネルを管理 ＞ チャネル設定」
チャネルのモデレーション： オフ
新しい投稿を開始できるのは誰ですか?： 誰でも新規の投稿を開始できます

## [kintone側の準備]
■ teamsチャネルのメアドを使って、ユーザーを１名（teams通知用ユーザー）追加する。
■ teams通知用ユーザーのアカウントにログインし、個人設定を以下のように設定する。
メール設定通知：　受信する
メール通知の対象：　すべての通知のみ　...★1
メール通知の形式：　HTML形式

★1：ここは本来[自分宛ての通知のみ]でよいはずだが、うまく機能しないため公式問合せ中。

■ kintone操作後にteamsへの通知を実現させたい"アプリX"に以下の設定を行う。
「アプリX > アプリの設定 > 設定 > アプリのアクセス権」
teams通知用ユーザー がアプリにアクセスできるように設定する（閲覧さえあればいい？）

「アプリX > アプリの設定 > 設定 > アプリの条件通知」
通知先　				｜　アプリの条件
teams通知用ユーザー 　	｜　「レコード追加」など、必要の応じてチェックを入れる

→ その後、アプリを更新して、上記２つの設定を反映する。

■ kintone全体の通知機能をONにする（ONになってるか確認する）
「kintoneシステム管理 > 利用する機能の選択 」
・通知メールの送信機能を利用する：　チェック済
・受信設定の既定値： 受信する（自分宛ての通知のみ）
・メール通知の形式： HTML形式
・個人設定による変更を許可する： チェック済


## [参考にした情報]
■ kintone通知ガイドブック
https://kintone.cybozu.co.jp/material/pdf/kintone_guidebook_vol09.pdf

■ 「自分宛」の通知
https://jp.cybozu.help/k/ja/user/notifications/notifications_to_me.html
[TypeScript] zodのparseはwrapperにすると良いことがあるのかもしれない

悲しい話です。弊社では、いつの間にかDBのスキーマが変わっていることがあります。
そんな馬鹿なっていう感じなのですが、いつの間にか……気づかないうちに……DBのスキーマが変わっているのです。怖いね。

DBからこんな型を生成していたとしましょう。

```typescript:schema.ts
import { z } from "zod";

const usersTableSchema = z.object({
  id: z.number(),
  name: z.string(),
  createdAt: z.date(),
  updatedAt: z.date(),
  sex: z.union([z.literal(0), z.literal(1), z.literal(2)]),
});

export type UsersTable = z.infer<typeof usersTableSchema>;
```

しかし、なぜか……いつの間にか……sexは3も取りうることになったりします。突然。急に。
心は男ですが、身体的には女性のときは3とか思いつきでDBのスキーマが変わっているのです。怖いね！

仮にzodで入っているデータをparseしたら、当然落ちます。 
型は再掲。
```typescript:parse.ts
import { z } from "zod";

const usersTableSchema = z.object({
  id: z.number(),
  name: z.string(),
  createdAt: z.date(),
  updatedAt: z.date(),
  sex: z.union([z.literal(0), z.literal(1), z.literal(2)]),
});

export type UsersTable = z.infer<typeof usersTableSchema>;

const newUser = {
  id: 1,
  name: "TANAKA TAROKO",
  createdAt: new Date(),
  updatedAt: new Date(),
  sex: 3, // 3は心は男だが身体は女性
};

const validUser = usersTableSchema.parse(newUser); // ←エラーで落ちる(涙)
```

まあ考慮漏れなので落ちるのが正しいわけです。
エラーはちゃんとエラーで処理されて、システムがいい感じに落ちて、ありがたいわけです。
落ちずに変な値を処理しようとするほうがやばいのです。

しかし……できるだけユーザーにはばれずに、それでもある程度型を維持したいというときがあるのです。
number型にするとts-patternとかで処理できないし……。

そういうときにはwrapperでなんとかしましょう。

```typescript:parse.ts
const sendError = (error: string) => {
  // slackやdiscordにエラーを送信する処理
};

const parseUsersTableWrapper = (obj: any) => {
  const safeParsed = usersTableSchema.safeParse(obj);
  if (!safeParsed.success) {
    sendError(safeParsed.error);
  }
  return obj as UsersTable;
};

const validUser = parseUsersTableWrapper(newUser); // ←エラーで落ちない！
```
エラーを握りつぶしつつ自分に通知を送ってスキーマのほうを頑張って修正するというね……。
asも本当に良くないんだけど、こういうケースだけは許してほしい。

まあ、こんな悲しいWrapper関数を作成しなくて良いような体制をつくるべきですね。
こういうラッパー関数を書くの、面倒で嫌いだったんですけど、github copilotを導入してから全然気にならなくなりました。
【GAS】シートの値を二次元配列で取得して連想配列にする

## シートの値を取得して連想配列にする

### 目的
フォームの回答シートのユーザー名を指定したら
slackシートのD列のchannelidの値を返す方法が欲しくて作成しました。
※フォームの回答シートのC列の「ユーザー名」とslackシートのB列の「表示名」は同じ

![フォームの回答.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/49be5d31-38ec-639b-2744-3bd611338030.png)
![slackシート.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/2e785751-79f1-ca95-ba8e-a03a58bdf1a4.png)


### コード

```javascript

function channneiIdGet(){
  //
  //slackシートの値を二次元配列で取得して連想配列にしたい
  //B列の表示名をいれればD列のchannneildが表示されるようにしたい
  const spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
  const slackSheet = spreadSheet.getSheetByName('slack');
  const slackLastRow = slackSheet.getLastRow();
  var values = slackSheet.getDataRange().getValues();

  //2次元配列で取得した値を連想配列にする
  //連想配列　slackシートのB列をキー　D列を値にする
  var Array = {};
  for (var i=1; i<slackLastRow; i++){
    var slackname = values[i][1]; //B列の i 行目のslack表示名
    var channelid =  values[i][3] ;//D列の i 行目のslackチャンネルID

    Array[slackname] = channelid  ;


  }
  Logger.log(Array["user01"]); //

  //フォームの回答シートの最終行のC列の値を取得（ユーザー名）
  //ユーザー名を連想配列のキーとして指定し値（channneildを取得する）
  const reportSheet = spreadSheet.getSheetByName('フォームの回答 1');
  //const reportLastRow = reportSheet.getLastRow();

  //②列の最終行から上方向に取得する
  var reportlastRow = reportSheet.getRange(reportSheet.getMaxRows(), 3).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
  Logger.log(reportlastRow); //
  var id = reportSheet.getRange(reportlastRow,3).getValue()

  Logger.log(Array[id])
  
  
}
```

### 実行結果
![channelid取得結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2640876/942ab1ed-806e-6789-ab98-3508381961ae.png)


### 試した結果
フォームの回答のシートの最終列にXLOOKUPを使うほうが簡単と思っていたが
フォームの回答は行が新しく追加されるためXLOOKUPを追加した列にはならない
連想配列を利用するのが良い

GASでスプレッドシートに関数をいれることで解決できた
https://qiita.com/80syokumotsu/items/a9dee0297a3edbb2e847
React Slickを使ってみた。

# 概要

依頼にスワイプになるバナーを作ってほしいという内容があった。
デザイン作業も必要だったので、material uiを使ってみようと思ったが、会社コードはmaterial uiのバージョンがあまりにも低くてスワイプバナーを作ることができなかった。

そんな中、react slickということを知り、簡単に解決できた。
今日はreactslickについて記述しようと思う。

# React Slick

## インストール
先にインストールしてみよう

```
npm install react-slick --save

yarn add react-slick
```

yarn または npm からのインストールが完了したら、プロジェクトに CSS を含める必要があります

```
npm install slick-carousel --save
```

## 例

```react
import React, { Component } from "react";
import Slider from "react-slick";

export default class MultipleItems extends Component {
  render() {
    const settings = {
      dots: false,
      infinite: true,
      speed: 500,
      slidesToShow: 3,
      slidesToScroll: 3
    };
    return (
      <div>
        <h2> Multiple items </h2>
        <Slider {...settings}>
          <div>
            <h3>1</h3>
          </div>
          <div>
            <h3>2</h3>
          </div>
          <div>
            <h3>3</h3>
          </div>
          <div>
            <h3>4</h3>
          </div>
          <div>
            <h3>5</h3>
          </div>
        </Slider>
      </div>
    );
  }
}
```

![ssfsdfds.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421654/cf43c4fd-6a9c-0d46-be2d-05908baeac16.jpeg)

コード作成することで上のようにカルーセルができた。
基本は、HTMLコードがsettingsに合わせてカルーセルになる構成だ。


自分の場合、左右のボタンの色やデザインの変更する必要があった。
調べてみたら、settingsで編集ができた。

```react
const settings = {
  dots: false,
  arrows: true,
  infinite: true,
  speed: 500,
  slidesToShow: 1,
  slidesToScroll: 1,
  autoplay: true,
  autoplaySpeed: 2500,
  prevArrow: <PrevArrow />,
  nextArrow: <NextArrow />,
};
```

上記のようにautoplayの設定もできるし、左右のボタンの修正も可能だ。
まず、prevArrow、nextArrowに<PrevArrow />、<NextArrow />を適用した。

```react
const PrevArrow = (props: CustomArrowProps) => {
    const { className, style, onClick } = props;
    return (
        <img
            style={{ ...style, top: ‘63%’ }}
            className={className}
            src={`${IMG_PATH}img/exchange/sliderPreviewButton.svg`}
            onClick={onClick}
        />
    );
};

const NextArrow = (props: CustomArrowProps) => {
    const { className, style, onClick } = props;
    return (
        <img
            style={{ ...style, top: ‘63%’ }}
            className={className}
            src={`${IMG_PATH}img/exchange/sliderNextButton.svg`}
            onClick={onClick}
        />
    );
};
```

欲しいボタンの画像を使うのもできる、大きさの修正もできる。
修正した結果は以下になる。

![スクリーンショット 2023-04-10 21.01.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421654/c9dd0860-37f4-353a-26b1-fac54c55d4ba.png)

# 終わり

https://react-slick.neostack.com/
上記のサイトでドキュメントと例題を確認することができる。
色んな例があるので、試しに使ってみるのも勉強になると思う。
ABC297で入緑しました【色変記事】

https://twitter.com/kyopro_mint/status/1645064856557568000?s=20

先日行われたABC297で緑色になれました。
先達の記事に多くを学び助けられたので、私も色変記事を書きたいと思います。

## 使用言語など
C++(gcc), Windows, WSL2 + VS Code


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306055/9cc157b2-b628-fe6b-19e4-fd37f9c052a4.png)
結構昔にAtCoderを始めたが、全然レートが上がらなくて2年間もAtCoderから離れていました。

#### AtCoder Problems
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306055/e508ed9f-46a8-a9f6-6836-54a4f33b899c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306055/de735c4a-f4e4-61c1-00ee-ef4986e9fc8d.png)


## 学習方法
#### ABC
参加できるABCは(今年に入ってからは)ほとんど参加しました。逆にARCはコンテストも過去問もノータッチです。ABCの公式放送はめちゃくちゃわかりやすいのでおすすめです。解説記事は良く分からないことが多いです。

#### :bangbang:バーチャルコントスト:bangbang:
##### 超おすすめです。
AtCoder Problems 上 (https://kenkoooo.com/atcoder/#/contest/recent) で、毎日毎朝毎晩何かしらのバーチャルコンテストが開かれています。自分のライフスタイルに合ったものに参加するのがおすすめです。
競プロに取り組む習慣ができます。

#### 書籍
螺旋本は昔半分ぐらいやりました。蟻本は買ったけど何を言っているかわかりませんでした・・・。


## 使用したアルゴリズム・データ構造
使用頻度が高かった気がする順ですが全部重要だと思います。
* Union-Find
    一時期これしかでなかった。
* std::set(平衡二分探索木)
   値の追加・検索・削除がO(logN)でできる上に、（内部構造的に）ソートされているので昇順・降順にも取り出せる化け物。
* DP
 (基本的な)DPは一度覚えてしまうと得点源になるので学習するのをお勧めします。EDPCなど。
* 全探索
 今回のABC297Eも、「Kの上限が 2e5 」⇒「小さい順に全部並べたら全探索できるじゃん！」という着想を得ました。
* std::map
  map\<char, vector\<int>> みたいなハチャメチャな書き方ができて非常に便利。
* BFS, DFS
 D問題までで問われるグラフ系の問題は、この二つで事足りるイメージです。
* bit全探索（とbit演算）
 Nの値が10とか小さいの時に、メタ的にbit全探索しそうだな～とか考えます。
* GCD
* エラトステネスの篩
* 累積和

queue, priority_queue などもよく使います。
イテレーターについての知識も必要です。
また、ラムダ式が書けると（主にDFSとかで）便利です。

ラムダ式の再帰方法が検索しても良くわからなくて困った覚えがあるのでここに軽く記述しておきます。
``` cpp:再帰を伴うラムダ式.cpp
// DFS
auto dfs = [&] (auto dfs, int index) {
    // DFSを実装
};

dfs(dfs, 0);
```



## 勉強したけどあまり使わなかったアルゴリズム
* ダイクストラ法、ベルマンフォード法、ワーシャルフロイド法
 D問題までではあまり問われてないように思います。
* 二分探索・尺取り法
 本番で使った記憶はないのですが、たまたまそういう回が重なっただけな気がします。
[追記]
自分で実装する二分探索はあまり使用していないが、lower_boundなどは頻繁に使用しています。


## まとめ
茶色・緑の問題は特定のアルゴリズムを使用する問題もあれば、上記のデータ構造や簡単なアルゴリズムの組み合わせに帰着できるアドホック？な問題も多いです。後者を鍛えるためには数をこなすしかありません[要出典]。**バチャコンに参加しましょう。**

これは個人的な趣味なのですが、ぷよぷよの連鎖をシミュレートするプログラムと、謎ぷよというぷよぷよの詰将棋みたいなものの解を探索するプログラムを作ったらBFS,DFS,2次元Grid系の問題にめちゃくちゃ強くなったのでここに記しておきます（お勧めできるかどうかはわかりません）。

私も水色目指して頑張るので、みなさんも一緒に精進しましょう。
正規表現を０から学ぶ

# 概要

作業をしていると、依頼内容の中に正規表現を使わなければならない場合がある。
正規表現についてはいつも一生懸命ググってみるけど、難しい；；；
今日は正規表現の基本をいくつか書いてみようと思う。

# 正規表現

プログラミングで文字列を扱う時、文字列の一定のパターンを表現する一種の形式言語をいう。
プログラムを作成する際は特性上、一定のルールを持つテキスト文字列を使用する場合が多いが、このような時に正規表現式を使用する。

電話番号、httpアドレス、メールアドレスなどを取るレシピは数え切れないほど散在しているが、いざ私が必要とする部分ではきちんとレシピを書いたと思うにもかかわらず、望む以上の結果を返す場合が非常に多いが、これを克服するためには正規式規則を几帳面に読んでみて直接怪我をして適用して確認した方が良い。

## 代表的な特殊文字

| 表現 | 説明 | 
|:------------:|:------------:|
| .       | 改行文字(\n)を除く任意の一文字を意味する。        |
| ?       | 該当文字パターンが0回または1回だけ繰り返される。        |
| *       | 該当文字パターンが0回以上繰り返される。        |
| +       | 該当文字パターンが1回以上繰り返される。        |
| {...}       | 繰り返される回数を指定する。        |
| ^       | 文字列の最初を意味する。        |
| $       | 文字列の終わりを意味する        |
| \       | 特殊文字を無視。        |
| \|       | 選択を意味する。(OR)        |
| (...)       | グループ化の始まりと終わりを意味する。        |

## 代表的な特殊文字を使った正規表現

- /.ap/
文字列 `ap` の前に任意の一文字が登場する文字列 (aap, bap, cap, @ap, #ap)、

- /a?b/
bの前にaが0番または1番登場する文字列(b、ab)

- /a*b/ 
bの前にaが0回以上登場する文字列(b、ab、aab、aaab)

- /a+b/
bの前にaが1回以上登場する文字列(ab、aab、aaab、aaab)

- /a{2,4}b/
bの前にaが2回以上4回以下登場する文字列(aab、aaab、aaab)

- /a{2,}b/
bの前にaが2回以上登場する文字列(aab, aaab, aaaab, aaaaab)

- /^abc/
abcで始まる文字列 (abc、abcd、abcdef)

- /abc$/
abcで終わる文字列 (abc、zabc、xyzabc)


まず、簡単な正規表現の例を見せた。
次はもう少し難しい表現や例題を記述する予定だ。
新しくなった基本情報技術者試験を受けてきた(2023年4月)

こんにちは。yuzu_juiceです🥂
本日(2023年4月10日)、新しくなった基本情報技術者試験を受験してきました。

# 受験時の筆者のITスキルレベル
- IT業界に就職して2年目(セキュリティの仕事をしている)
- IPAの資格はITパスポートのみ所持
- クラウド関係はAWS SAA, AZ-104所持
- 2022年の10月ごろに1度基本情報技術者試験に落ちた(午後問が2点足りなかった)

# 以前の試験とどう変わったか
↓記事に書いてある通りです。大きな変更点を抜粋して以下記述します。
https://www.ipa.go.jp/news/2022/shiken/henkou20220425.html

- 通年受験できるようになった
- 試験の名称が変わった
    - 午前試験→科目A試験
    - 午後試験→科目B試験

-  制限時間が変わった
    - A(午前): 150分→90分
    - B(午後): 150分→90分

- 問題数が変わった
    - A(午前): 80問→60問
    - B(午後): 11問(5問選択)→20問(全問必須)

- B(午後)のプログラミング言語が疑似言語での出題になった

# どうやって勉強したか
3月頭から勉強を始め、合計10時間ほど勉強しました。
教材はみんな大好き過去問道場です🙌

# 受験について
A, B試験連続でぶっ通しで受ける必要がありました。
Aを受験→休憩10分(取得は任意)→Bを受験　の順でした。
以前のように、午後問を先に受験することができなくなっています。

受験結果は以下の通りで無事合格でした👍
受験終了後、すぐPC画面に表示されたので少しびっくりしました。
Bで満点とれたので、大満足です😊😊
|科目|点数|
|----|----|
|A|685/1000点|
|B|1000/1000点|

# 今後にむけて
次はセキュリティマネジメント試験を受験しようと思います。
Windows C++ で標準APIだけで zip を解凍する

Windows の C++ で zip ファイルをフォルダに(再帰的に)展開するには以下のようなプログラムでできます。
一番大きな注意点は、解凍先のフォルダをあらかじめ作ってから UnzipToFolder() を呼ばなければ失敗します(falseが返ってきます)。
msvc でも mingw の g++ でもビルドできます。
COMを使っているので呼び出しにそれなりの作法があります。(この記事では詳しく解説しません)

```cpp:main.cpp
#include <windows.h>
#include <shlobj.h>
#include <iostream>
#include <filesystem>

bool UnzipToFolder(BSTR lpZipFile, BSTR lpFolder);

int main()
{
    std::cout << "(begin)" << std::endl;
    CoInitialize(NULL);
    BSTR bstrFile = SysAllocString(L"c:\\temp2\\openjdk20-20-36.zip");
    BSTR bstrPath = SysAllocString(L"c:\\temp2\\sample");
    std::filesystem::create_directories(L"c:\\temp2\\sample");
    BOOL b = UnzipToFolder(bstrFile, bstrPath);
    SysFreeString(bstrFile);
    SysFreeString(bstrPath);
    CoUninitialize();
    std::cout << "(end)" << b << std::endl;
    return 0;
}

bool UnzipToFolder(BSTR lpZipFile, BSTR lpFolder)
{
    IShellDispatch *pISD;
    Folder  *pZippedFile = 0L;
    Folder  *pDestination = 0L;

    long FilesCount = 0;
    IDispatch* pItem = 0L;
    FolderItems *pFilesInside = 0L;

    VARIANT Options, OutFolder, InZipFile, Item;
    if (CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void **)&pISD) != S_OK)
        return false;

    InZipFile.vt = VT_BSTR;
    InZipFile.bstrVal = lpZipFile;
    pISD->NameSpace(InZipFile, &pZippedFile);
    if (!pZippedFile)
    {
        pISD->Release();
        return false;
    }

    OutFolder.vt = VT_BSTR;
    OutFolder.bstrVal = lpFolder;
    pISD->NameSpace(OutFolder, &pDestination);
    if (!pDestination)
    {
        pZippedFile->Release();
        pISD->Release();
        return false;
    }

    pZippedFile->Items(&pFilesInside);
    if (!pFilesInside)
    {
        pDestination->Release();
        pZippedFile->Release();
        pISD->Release();
        return false;
    }

    pFilesInside->get_Count(&FilesCount);
    if (FilesCount < 1)
    {
        pFilesInside->Release();
        pDestination->Release();
        pZippedFile->Release();
        pISD->Release();
        return false;
    }

    pFilesInside->QueryInterface(IID_IDispatch, (void**)&pItem);

    Item.vt = VT_DISPATCH;
    Item.pdispVal = pItem;

    Options.vt = VT_I4;
    //Options.lVal = 1024 | 512 | 16 | 4; //https://learn.microsoft.com/ja-jp/windows/win32/shell/folder-copyhere
    Options.lVal = 1024 | 512 | 16; //https://learn.microsoft.com/ja-jp/windows/win32/shell/folder-copyhere

    bool retval = pDestination->CopyHere(Item, Options) == S_OK;

    pItem->Release(); pItem = 0L;
    pFilesInside->Release(); pFilesInside = 0L;
    pDestination->Release(); pDestination = 0L;
    pZippedFile->Release(); pZippedFile = 0L;
    pISD->Release(); pISD = 0L;

    return retval;
}
```
iOS16.4でSafari Webインスペクタを有効にする方法

iOS 16.4 で Safari Web インスペクタが有効にならなくなっていたので調べてみたところ、WebView の inspectable を有効にする必要があるとのこと。

* iOS 16.4 webview can not debug in safari web inspector | Apple Developer Forums
    * https://developer.apple.com/forums/thread/727049
* Enabling the Inspection of Web Content in Apps | WebKit
    * https://webkit.org/blog/13936/enabling-the-inspection-of-web-content-in-apps/

# Swift

```
let webConfiguration = WKWebViewConfiguration()
let webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.isInspectable = true
```
# Objective-C

```
WKWebViewConfiguration *webConfiguration = [WKWebViewConfiguration new];
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:webConfiguration];
webView.inspectable = YES;
```
ChatGPTは、回答できなくなるとエラーになる？

# ChatGPTは、回答できなくなるとエラーになる？

## 以下が、やりとりの最後の部分です。


## 私もそう思います。できれば、利他的な人間を多く集めて政治団体を作ってもらいたい。

利他的な人間を多く集めて政治団体を作ることは、確かに理想的な方法の1つかもしれません。しかし、利他的な人間だけで政治を行うことができるかどうかは疑問が残ります。政治は、常に多様な価値観、利益、意見を抱えた人々の間で複雑な協議や妥協が必要な分野です。そのため、利他的な人間だけで政治を行うことは困難な場合があります。

また、利他的な人間だけで政治団体を形成した場合、一方的に利他的な価値観が主張されることになり、意見や利益の多様性が欠ける可能性があります。このような場合、あるグループの利益や価値観が不当に優位になってしまうことがあるため、ある程度のバランスを保ちつつ政治を行うことが必要とされます。

したがって、利他的な人間を中心に据えた政治団体を形成する場合でも、他の立場や価値観を尊重し、多様性を受け入れることが大切だと思われます。


## 誰もが不当に扱われないための利他精神ではないのですか？　矛盾していませんか？

利他精神は、誰もが不当に扱われない社会を実現するために重要な役割を果たします。しかし、その前提として、まずは誰もが自分自身を大切にし、自分自身が幸せになることが必要です。自分自身を幸せにしなければ、他人を幸せにすることはできません。利他精神は、自分自身を大切にしながら、他人を思いやり、支援することができる精神です。つまり、利他精神は、自分自身を犠牲にすることではなく、自分自身を大切にしながら、社会全体の幸福を追求することを意味します。


## 利他的な人間にとって、チームの他の人間が自分を守ってくれればそれで善いのです。あなたは利他性をまだ理解できていません。
!
Something went wrong. If this issue persists please contact us through our help center at help.openai.com.

## まとめ

また難しい質問が思いついたら、AIエラーチャレンジします！
自己紹介

はじめまして、先日某プログラミングスクールを卒業したばかりの初心者エンジニアです:bow_tone1:
今回は初投稿なので、自己紹介とどんな投稿をしていきたいかを簡単に書いていきたいと思います！
# 自己紹介
##### ・27歳男性、兵庫県在住
##### ・文系で立命館大学を卒業後、メガバンクに入社
##### ・ライフプラン等に関するコンサルティング業務に約5年程従事
##### ・昨年末（2022年末）付けで前職を退職
##### ・2月からプログラミングスクールに入学、4月に卒業
##### ・言語はRubが中心
-------------------------------------------------------------
昨年12月までプログラミングどころかパソコン自体についても何も知らない状態でしたが、何とか卒業することができました。
「なぜそうなるのか」についてを自分なりに深掘りすることを意識してやっていました。
自分が深掘りした内容について、プログラミングノートを作成していたので、まずはその内容を中心にアウトプットしていきたいと思っています！

次回以降、まずは
### 『Rubyは全てがオブジェクト』
について投稿していこうと思います。
よろしくお願いします:bow_tone1:
超簡単！Win32 API でURLからファイルをダウンロードする

URLDownloadToFileW()関数で一発OK！

```cpp:main.cpp
#include <Windows.h>
#include <string>

#pragma comment(lib, "urlmon.lib")

int main()
{
    std::wstring dwnld_URL = L"https://github.com/jwallet/spy-spotify/releases/download/1.12/Spytify-v.1.12.zip";
    std::wstring savepath = L"C:\\temp2\\Spytify-v.1.12.zip";
    URLDownloadToFileW(NULL, dwnld_URL.c_str(), savepath.c_str(), 0, NULL);
    return 0;
}
```

mingwのg++などでコンパイルするさいはリンクライブラリとして「-lurlmon」を追加のこと。
fetch(PDO::FETCH_ASSOC)を学んだ

# 概要

作業中にDBにあるデータを扱う部分があったが、データ量が多すぎた。
いつものようにfetchで使っていたところ、PDO::FETCH_ASSOCを使ったほうがいいというレビューコメントを受けた。
実際にFETCH_ASSOCで効率的にデータを扱うことができた。
今日はFETCH_ASSOCについて述べたい。

# fetch(PDO::FETCH_ASSOC)

PDO::FETCH_ASSOCは、結果セットに 返された際のカラム名で添字を付けた配列を返します。

| id | product number | price |
|:-----------:|:------------:|:------------:|
| 1       | A001        | 100         |
| 2       | A002        | 300         |
| 3       | A003        | 500         |
| 4       | A004        | 700         |
| 5       | A005        | 1000         |

上のTABLEで「priceが600以下のデータがあるか？」というSQL文でデータを呼び出した時に次のように帰ってきます。

```
$result = $stmt->fetch(PDO::FETCH_ASSOC); 
```

```
Array (
    [id] => 1,
    [product number] => A001,
    [price] => 100,
)
```

結果は上記のように出る
priceが800以下のデータはidが1,2,3に該当するが、id=1のデータだけが結果として出た。
それは、fetchが該当するデータを1行返すからだ。

fetchAllで、該当するすべてのデータを配列で返す必要がある。

```
$result = $stmt->fetchAll(PDO::FETCH_ASSOC); 
```

```
Array
(
  [0] => array
    (
      [id] => 1,
      [product number] => A001,
      [price] => 100
    ),
  [1] => array
    (
      [id] => 2,
      [product number] => A002,
      [price] => 300
    ),
  [2] => array
    (
      [id] => 3,
      [product number] => A003,
      [price] => 500
    )
)
```

結果は上記のように出る。
こうすることで、出したデータがわかりやすいし、使いも楽になる。

PDO::FETCH_ASSOCを使ってみたら、別の種類もあったので述べる。

# PDO::FETCH_BOTH

結果セットに返された際のカラム名と 0 で始まるカラム番号で添字を付けた配列を返します。
上記のテーブルで「priceが900以上ののデータ」を出すと、

```
$result = $stmt->fetchAll(PDO::FETCH_BOTH); 
```

```
Array
(
  [0] => array
    (
      [id] => 1,
      [0] => 1,
      [product number] => A001,
      [1] => A001,
      [price] => 100,
      [2] => 100
    )
)
```
結果は上記のように出る。

# PDO::FETCH_NUM

結果セットに返された際の 0 から始まるカラム番号を添字とする配列を返します。
上記のテーブルで「priceが600以下のデータ」を出すと、

```
$result = $stmt->fetchAll(PDO::FETCH_NUM); 
```

```
Array
(
  [0] => array
    (
      [0] => 1,
      [1] => A001,
      [2] => 100
    ),
  [1] => array
    (
      [1] => 2,
      [2] => A002,
      [3] => 300
    ),
  [2] => array
    (
      [1] => 3,
      [2] => A003,
      [3] => 500
    )
)
```
結果は上記のように出る。
Windows10でNginxをインストール

# 環境
Windows10
nginx-1.23.4

# インストールとサービス化
・任意の場所に解凍したnginx-1.23.4内にあるnginx.exeをダブルクリックで起動
・http://localhost/にアクセスしてアクセスできればインストール完了

・下記のサイトにてwinsw-2.9.0-bin.exeをダウンロード
　https://repo.jenkins-ci.org/releases/com/sun/winsw/winsw/
・nginx-1.23.4フォルダ内にwinsw-2.9.0-nginxsvc.exeとリネームして保存
・nginx-1.23.4フォルダ内winsw-2.9.0-nginxsvc.xmlを新規作成
```c
<service>
  <id>nginx</id>
  <name>nginx</name>
  <description>nginx</description>
  <logpath>c:\nginx\logs</logpath>(任意変更)
  <logmode>roll</logmode>
  <depend></depend>
  <executable>c:\nginx\nginx.exe</executable>(任意変更)
  <startargument></startargument>
  <stopexecutable>c:\nginx\nginx.exe</stopexecutable>(任意変更)
  <stopargument>-s</stopargument>
  <stopargument>stop</stopargument>
</service>
```
・管理者権限CMDで下記コマンド
```c
C:\nginx>winsw-2.1.2-nginxsvc.exe install
```
・INFO  - Installing the service with id 'nginx'と出ればサービス化完了
・サービスから削除するときは下記のコマンド
```c
C:\nginx\winsw-2.1.2-nginxsvc.exe uninstall
```
# 参考にさせて頂いたサイト
https://qiita.com/sugasaki/items/83542f5614bc54a9475f
https://repo.jenkins-ci.org/releases/com/sun/winsw/winsw/
http://nginx.org/en/docs/windows.html
AppArmor その3: 子プロセスの制限

AppArmor で、ある特定の呼ばれ方をした時だけよりたくさんの権限を与えたいという事があります。例えばこんなシナリオを考えます。

* プログラム /tmp/cat (/bin/cat のコピー) はあるファイル /tmp/white.txt だけを読める。
* プログラム /tmp/parent は /tmp/cat を実行できる。parent は /tmp/white.txt と /tmp/red.txt の両方を読める。
* /tmp/cat も /tmp/parent もその他のファイルにアクセスできない。

つまり、/tmp/cat はファイル一つしか読めませんが、/tmp/parent 経由で読むと二つ読めるのです。これをやります。まず必要なファイルを準備します。

```
cp /bin/cat /tmp/cat
echo Hello white > /tmp/white.txt
echo Hello red > /tmp/red.txt
echo Hello black > /tmp/black.txt
```

ここで子プロセス /tmp/cat を呼び出すだけのプログラム parent.cpp を作り /tmp/parent に置きます。

```cpp
#include <stdlib.h>
#include <string>
#include <iostream>

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        std::cerr << "usage: parent filename" << std::endl;
        exit(1);
    }
    std::string command = "/tmp/cat";
    int ret = system((command + " " + argv[1]).c_str());
    exit((ret == 0) ? 0 : 1);
}
```

テストプログラムはこんなかんじ。

```sh
#!/bin/sh

set -o errexit
set -o nounset
set -o xtrace

/tmp/parent /tmp/white.txt || exit 1
/tmp/parent /tmp/red.txt || exit 1
/tmp/parent /tmp/black.txt && exit 1

/tmp/cat /tmp/white.txt || exit 1
/tmp/cat /tmp/red.txt && exit 1
/tmp/cat /tmp/black.txt && exit 1

exit 0
```

white.txt だけを読める /tmp/cat のプロファイル /etc/apparmor.d/tmp.cat は [前回](https://qiita.com/propella/items/a6b646916b48029c369e) と同じです。

```
include <tunables/global>
/tmp/cat {
  include <abstractions/base>
  /tmp/white.txt r,
}
```

/tmp/parent のプロファイルの書き方は色々あるので順番に見ていきます。

## ix (継承) を使うパターン

継承を使うというのは、子プロセスにも親プロセスと同じ権限を与えるというものです。この場合、親プロセスに余分な権限が必要という難点があります。これで /tmp/parent 経由で呼ぶことで /tmp/red.txt にもアクセスできるようになります。

```
# ix (継承) を使うパターン

include <tunables/global>

/tmp/parent {
  include <abstractions/base>
  /bin/dash mrix,
  /tmp/cat ix,

  /tmp/white.txt r,
  /tmp/red.txt r,
}
```


## cx (Child profile: 子プロファイル) を使うパターン

子プロファイル (cx) というのは、プロファイルの中に埋め込んだプロファイルの事です。これで親子別の権限を与える事が出来ます。

```
include <tunables/global>

/tmp/parent {
  include <abstractions/base>
  /bin/dash mrix,
  /tmp/cat cx, // ここで cx を指定

  profile /tmp/cat {
    include <abstractions/base>
    /tmp/cat mr,
    /tmp/white.txt r,
    /tmp/red.txt r,
  }
}
```

## px (Discrete profile: 独立プロファイル) を使うパターン

独立プロファイル (px) を使うと、子プロセスの権限を別のプロファイルに書くことが出来ます。矢印 -> の右側を省略すると、この場合上記 /etc/apparmor.d/tmp.cat に書いたプロファイルが選択されていまいますが、-> の右に明示的にプロファイル名を書くことで別のプロファイルを指定できます。これで、/tmp/cat を直接実行するよりも多い権限を与える事ができます。

```
include <tunables/global>

/tmp/parent {
  include <abstractions/base>
  /bin/dash mrix,
  /tmp/cat px -> parent_cat, // ここで px を指定。更にプロファイル名を指定。
}

profile parent_cat {
  include <abstractions/base>
  /tmp/cat mr,
  /tmp/white.txt r,
  /tmp/red.txt r,
}
```

参考

* [manpage\_apparmor.d.5 · Wiki · AppArmor / apparmor · GitLab](https://gitlab.com/apparmor/apparmor/-/wikis/manpage_apparmor.d.5)
* [AppArmor - Qiita](https://qiita.com/propella/items/a6b646916b48029c369e)