OmniAICreator/Qiita-1.07M huggingface dataset:
操作手順書



## 操作手順の目次


**URL：**[アプリの詳細](https://qiita.com/sirororo/items/e2ea79b717d9c7562f0c)
**URL：**[サービス内容](https://qiita.com/sirororo/items/a9e121983e73fb4b4805)
**URL：**[アプリ](http://handson-874214957.ap-northeast-1.elb.amazonaws.com/kiso/shop/index.php)
**URL：**[github](https://github.com/sirororo/nouheru)


- [操作手順書](#操作手順書)
  - [依頼の手順](#依頼の手順)
    - [ログイン[想定作業時間：２分]](#ログイン想定作業時間２分)
    - [サービスの依頼をする[想定作業時間：２分]](#サービスの依頼をする想定作業時間２分)
    - [依頼しているリストを確認する[想定作業時間：１分]](#依頼しているリストを確認する想定作業時間１分)
    - [依頼完了の手続きをする[想定作業時間：１分]](#依頼完了の手続きをする想定作業時間１分)
  - [サービス登録と受注の手順](#サービス登録と受注の手順)
    - [サービスの登録をする[想定作業時間：２分]](#サービスの登録をする想定作業時間２分)
    - [受注内容を確認する[想定作業時間：１分]](#受注内容を確認する想定作業時間１分)

---

### 依頼の手順

#### ログイン[想定作業時間：２分]

<img src="https://github.com/sirororo/nouheru/blob/master/diagram/login.png?raw=true" alt="" width="500">



✔ [農へる](http://handson-874214957.ap-northeast-1.elb.amazonaws.com/kiso/shop/index.php)にアクセス<br><br>

```text
  ログイン登録を省略したい場合は以下の業者リストからログインしてください。

   １）農機具レンタル業者： 狩生 岳志
  ・メールアドレス： rrrr@gmail.com
  ・パスワード： rrrr

  ２）専門の経理・会計：小林 陽介
  ・メールアドレス：2222@gmail.com 
  ・パスワード： 2222

  ３）無料サービス：横山 豊
  ・メールアドレス：6666@gmail.com
  ・パスワード： 6666

```


✔ トップ画面の右上の`無料会員登録`をクリック<br><br>
✔ `名前`・`メールアドレス`・`郵便番号`・`住所`・`電話番号`・`パスワード`・`性別`・`生まれ年`・`顔写真`を記入後`確認して進む`をクリック<br><br>

 ✔ 会員情報の再確認後`確認して進む`をクリック<br><br>
 ✔ 登録完了後`トップへ移動する`をクリック<br><br>

<br>

#### サービスの依頼をする[想定作業時間：２分]

<img src="https://github.com/sirororo/nouheru/blob/master/diagram/irai.png?raw=true" alt="" width="500">

✔ トップ画面のカテゴリ一覧からサービスを選び`内容を確認する`をクリック<br><br>
✔ サービス内容と口コミを確認後`無料相談をする`をクリック<br><br>
✔ `作業内容`・`作業日付`・`作業場所の郵便番号`・`作業場所の住所`を記入後`確認して進む`をクリック<br><br>
✔ 依頼内容を再確認後`登録する`をクリック<br><br>
✔ 依頼内容を送信後は`依頼中リストで確認`か左上の`マイページ`で確認できます<br><br>

<br>

#### 依頼しているリストを確認する[想定作業時間：１分]

<img src="https://github.com/sirororo/nouheru/blob/master/diagram/irai_kakunin.png?raw=true" alt="" width="500">

✔ 左上の`マイページ`をクリック<br><br>
✔ `依頼中のリスト`をクリック<br><br>
✔ 依頼画面が出るため`内容を確認する`をクリック<br><br>
✔ サービス内容と依頼内容が確認できます<br><br>

<br>

#### 依頼完了の手続きをする[想定作業時間：１分]

<img src="https://github.com/sirororo/nouheru/blob/master/diagram/kutikomi.png?raw=true" alt="" width="500">

✔ `依頼中のリスト`の`依頼完了の手続きに進む`をクリック<br><br>
✔ `満足度`・`金額`・`感想`を記入後`確認して進む`をクリック<br><br>
✔ 内容を再確認後`登録する`をクリック<br><br>
✔ 登録完了後は依頼したサービスに口コミや`運用管理データ`に金額が反映されるようになります<br><br>

<br>

---

### サービス登録と受注の手順
（ログイン状態であることを前提にしています）

#### サービスの登録をする[想定作業時間：２分]

<img src="https://github.com/sirororo/nouheru/blob/master/diagram/gyoumu_add.png?raw=true" alt="" width="500">


✔ トップ画面の左上にある`マイページ`をクリック<br><br>
✔ `サービス設定`の`確認をする`をクリック<br><br>
✔ `自分のサービスを掲載する`の`記入へ進む`をクリック<br><br>
✔ `業種`・`プロフィール`・`サービス内容`・`価格`・`営業時間`・`対応地域`・`支払い方法`・`作業画像`を記入して`確認して進む`をクリック<br><br>
✔ 登録画面を再確認後`登録する`をクリック<br><br>
✔ 登録確認後に仕事の依頼が来た場合はメールでお知らせしてくれます。依頼内容は`受注リスト`で確認できます<br><br>

<br>

#### 受注内容を確認する[想定作業時間：１分]



✔ トップ画面の左上にある`マイページ`をクリック<br><br>
✔ `受注中のリスト`の`確認をする`をクリック<br><br>
✔ 顧客から依頼が来ているので`内容を確認する`をクリック<br><br>
✔ 依頼内容が確認できます<br><br>

<br>
エンジニアが分野を決めるときの基準

道路・鉄道・滑走路づくりが好きな人　→　ネットワークエンジニア
建築・建物・部屋づくりが好きな人　→　AWS/Azure/仮想化エンジニア
室内の配管とか設備づくりが好きな人　→　サーバサイドエンジニア
室内インテリア・デザインが好きな人　→　フロントエンド・UI/UXエンジニア
居住者の世話や管理が好きな人　→　ヘルプデスク・社内IT管理者・ITコンサルタント
乗り物づくりが好きな人　→　データセンターエンジニア・端末エンジニア
オープンソース動向


オープンソース関連のプロジェクト動向についてピックアップしました。


https://openjsf.org/blog/2022/02/14/node-js-trademarks-transferred-to-openjs-foundation/

https://events.linuxfoundation.org/openjs-world/

https://cd.foundation/cdf-community-awards/

https://www.businesswire.com/news/home/20220201005513/en/Demand-for-Rapid-Risk-Elimination-for-Linux-at-Scale-Fueled-TuxCare%E2%80%99s-Meteoric-Growth-in-2021

https://jcasman27.medium.com/list/ricoh-994c2fcc8f22
Laravel9 Sailでサクッと開発環境構築

# 環境
macOS Monterey
docker desktop 4.5.0
Laravel Framework 9.6.0

# 前提
* docker desktopがインストール済み、起動済み

# 手順
### プロジェクト作成
プロジェクト名「example-app」の部分は任意の名前でOK
```
cd [project_dir]
curl -s "https://laravel.build/example-app" | bash
```

### 全てのDockerコンテナをバックグラウンドで起動
```
cd example-app
./vendor/bin/sail up -d
```
:::note info
 (sailコマンドのBashエイリアスを設定しておくと便利)
alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'
:::

### 初期設定
timezoneを日本時間に、localeを日本語に変更
```config/app.php
//'timezone' => 'UTC',
'timezone' => 'Asia/Tokyo',

// 'locale' => 'en',
'locale' => 'ja',
```
　
DBの文字コード変更
デフォルトのutf8mb4_unicode_ciは絵文字も使える文字コードなので、utf8に変更する

:::note info
utf8とutf8mb4の違いについては、こちらの記事を参照させていただきました。
https://penpen-dev.com/blog/mysql-utf8-utf8mb4/
:::

```config/database.php
'mysql' => [
    ・・・・・省略・・・・・

    // 'charset' => 'utf8mb4',
    // 'collation' => 'utf8mb4_unicode_ci',
    'charset' => 'utf8',
    'collation' => 'utf8_unicode_ci',

    ・・・・・省略・・・・・
],

```
　
`http://localhost/`で初期画面が表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659480/1f2dc82b-ecce-5b4d-80dd-f7a739153919.png)

### 開発に便利なライブラリ
私の環境では以下をインストールしています。
##### IDEでコード補完できるようにする「barryvdh/laravel-ide-helper」

```
# インストール
sail composer require --dev barryvdh/laravel-ide-helper

# Automatic PHPDoc generation for Laravel Facades
sail artisan ide-helper:generate

# Automatic PHPDocs for models(-N : _ide_helper_models.phpという別ファイルに補完用コードを書き込む)
sail artisan ide-helper:models -N
```

##### デバッグツール「barryvdh/laravel-debugbar」
```
# インストール
sail composer require --dev barryvdh/laravel-debugbar
```
.envでAPP_DEBUG=trueになっていることを確認する。
```.env
APP_DEBUG=true
```

### 全てのDockerコンテナを停止
全てのコンテナを停止するときは
```
sail stop
```
公式ドキュメントでは`sail stop`しか載っていないですが、個人の方のブログなど、色々記事を探していると、`sail down`も使えるのかも？
以下、間違っているかもしれないですが、一応載せておきます。
 **実行は自己責任でお願いいたします**:pray:
```
# コンテナを停止して削除(ただしVolumeは消えないっぽい)
sail down

# コンテナを停止して削除、ボリュームも削除
sail down --volumes

# コンテナを停止して削除、ボリューム、イメージも削除
sail down --volumes --rmi all --remove-orphans
```


# 参考記事
https://readouble.com/laravel/9.x/ja/sail.html

https://qiita.com/schrosis/items/cce304870fcb27498a5e
[SQL][Oracle]備忘録　ファンクションの使用方法

# SQLファンクションの書き方
## 下記ファンクションのテンプレート

```sql:cnvt.sql　　
--テンプレート
  CREATE OR REPLACE FUNCTION 任意の関数名(引数 varchar2)
  RETURN varchar2
  IS
     戻り値　varchar2(400);
  BEGIN
      SELECT
      
      INTO
        戻り値
　　　FROM
　　　　変換テーブル名
　　　WHERE
　 ;
　　　RETURN 戻り値;
   END;
   /
```  
```sql:cnvt1.sql
  --使用例　　
  CREATE OR REPLACE FUNCTION cnvt(test varchar2)
  RETURN varchar2
  IS
     ret_text varchar2(400);
  BEGIN
      SELECT
        col002
      INTO
        ret_text
　　　FROM
　　　　変換テーブル名
　　　WHERE
　      col001 = test；
　　　RETURN ret_text;
   END;
   /
--説明
--関数cnvt 引数test
--引数のtestとcol001が同じ値の時、col002を戻り値として返す
```
Chromeで上のタイトルバーを非表示にする【Ubuntu 22.04 Jammy Jellyfish】

# 上部にタイトルバーが表示され表示領域が狭くなる問題
![Screenshot from 2022-04-03 13-09-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/c7a1527f-4296-22eb-ee5a-fb020e0695fd.png)

## 方法1 タイトルバー付近を右クリックして`システムタイトルバーと枠線の使用`を無効にする
![Screenshot from 2022-04-03 15-32-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/d205ea9d-329a-5d91-c890-fe8c11696973.png)


## 方法2 `chrome://settings/appearance`から`システムタイトルバーと枠線の使用`を無効にする
設定からデザインを開き、`システムタイトルバーと枠線の使用`を無効にする
![Screenshot from 2022-04-03 13-10-09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/e598e1c5-ba36-e3ed-5766-e6b7b7518435.png)
![Screenshot from 2022-04-03 13-10-23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/d2dc4a56-2b0b-3488-f187-3ad53537f739.png)
表示領域が広がった
![Screenshot from 2022-04-03 13-18-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/ca142a8d-af19-4856-6433-db4c1009efd3.png)
`Dockを自動的に隠す`ともっと広がります
![Screenshot from 2022-04-03 13-19-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/ff54ca81-6b0a-a094-9437-16440963b95b.png)
コマンド実行時に役立つLinuxの権限設定について

# コマンド実行権限がない！
こんな経験ないですか？最近の私がそうでした。
実行環境では不要なコマンド実行を避けるためにグループごとにコマンド実行権限を変更している場合が多いです。今回はそういう時にどうすれば適切に対処できるかを備忘録としてまとめます。


## パーミッション確認
### パーミッションとは
Linuxにはファイルやディレクトリに一つずつに許可属性を与えている。これをパーミッションという。Linuxでは「所有者」「グループ」「その他」に分け、それぞれ許可属性を付与する。

### パーミッションはセキュリティのために必要
一般ユーザにroot権限を与えて閲覧できないファイルが閲覧できてしまわないように、もしくは不意の操作によってシステム環境を変更して運用に影響しないようにパーミッションは必要である。
パーミッションを適切に管理、設定しておくことで重大な事故を未然に防ぐことができる。

## パーミッション確認コマンド


```適当なディレクトリで「hoge.txt」を作成
$touch hoge.txt 
```


```　パーミッション確認
$ls -l hoge.txt 
```


``` 結果
-rw-r--r-- 1 ken users 0 12月 22 16:28 hoge.txt
```


``` 
①-②rw-　③r--　④r-- ⑤ken ⑥users
```

| ①-|②rw-|③r--　|④r--| ⑤ken| ⑥users
| ---- | ---- |----|----|----|----|
|  TD  |  TD  |----|----|----|----|
|  TD  |  TD  |----|----|----|----|



ファイルタイプ（①）
d:ディレクトリ
l:リンクファイル
-:指定なし


アクセス権（②所有者③グループユーザー④その他）
r:読み込み許可 
w:書き込み許可 
x:実行可能　スクリプトなどの場合実行権限を割り当てることになる。またディレクトリはxフラグを与えないと開くことが出来ない。

所有者（⑤）
グループ（⑥）

#### 数値表現
| 記号|数値|
|----|----|
|r|4|
|w|2|
|x|1|
|-|0|

## 現在ログインしているユーザー確認
```
$who
```
ログインユーザが「hoge」の場合
``` 
hoge      console  Mar 24 09:23 
hoge      ttys000  Apr  2 14:50 
```
### ユーザー情報確認

```
$cat /etc/passwd
```


### グループ情報確認

```
$cat /etc/group
```
登録システム

## 会員登録システムの構成
### データベース
データベースは、『登録した会員情報を保存しておく』という役割があります。

### PHPファイル
 必要なPHPファイル(仮)
・dbconnect.php - このファイルでは、PHPからデータベースに接続するための処理を行います。
すべてのファイルで、データベースとの接続処理を記述することは無駄が多いので、１つのファイルにまとめておこう、という発想です。

・entry.php - このファイルでは、登録フォールを作成し、会員情報を実際に入力してもらう画面を作ります。

・check.php - このファイルでは、entry.phpで入力してもらった情報の再確認を行います。
要するに、「メールアドレスとか本当にこれでいいの？」って確認するやつです。

・thank.php - このファイルでは、登録が完了した旨を伝え、ログインページへと促します。

### 全体の流れ

![join_system_architecture-1024x543.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600460/dd5a22e6-388f-9cfd-572a-56ec3787d0b8.png)


参考文献　：


https://www.tomotaku.com/programing-join-system/
2022年04月未解決の質問




+ [Clickable TEXT field and Remove Decimal](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000G3gDf)
最後は質問がTopicの話になって分からん。

+ [Data Import Wizard mapping](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000G3BRi)
+ [Frame Ancestors](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000FxmM5)
+ [FF 97 & 98 : Getting SecurityError: Permission denied to access property "pageXOffset" on cross-origin object in while taking screenshot.](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000FxIQ2)
+ [How to mass assign apex classes access to permission set ?](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000G5P5o)

+ [CRLP_RollupQueueable npsp:Too many query rows: 50001 on Opportunity rollup](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000GhJQq)
+ [ System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, field integrity exception: AccessLevel (trivial share level Read, for organization with default level Edit): [AccessLevel] Trigger.ShiftDemoTrigger: line 49, column 1](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000GzuTN)
+ [Save the Account Owner on the Opportunity when an Oppotunity is Closed](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000GezMq)


--------------------------------------------------------------------

# トレイルヘッド

+ [【解決】We can't validate the 'Create Seed Bank Agencies' node was created correctly.](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Fy1xLSAR)

Wonder I did completed the Challenge. Two reasons for it.

Changed the Load Agency Detail fields Data type to Dimension instead of Measure.
LoadAgencyDetailフィールドのデータ型をMeasureではなくDimensionに変更しました。
 | Latitude | Longitude

Added the Account Number field in the Add Agency fields section and updated date flow and ran the data flow.
[エージェンシーフィールドの追加]セクションに[アカウント番号]フィールドを追加し、日付フローを更新してデータフローを実行しました。


+ 【解決】[We can't validate the 'Create Seed Bank Agencies' node was created correctly. ](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Fy1xL)

しかし、何で取引先責任者には表示されるのに、Caseでは選択できないのか？
+ [選択リストから「SeanForbes」を追加できない](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Gelxt)

+ [Account Partner Roles Not Created](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000G4WugSAF)
【Mac】Matplotlibで日本語を表示させる設定

# 前提
Mac向けの設定です。他のOSはパスやインストール済みのフォントが異なるのでそのまま流用はできません。

# 動機
MatplotlibはPythonのグラフ描画ライブラリだが、既定では日本語を表示することができない。（豆腐になる）
既定では日本語文字を含まないフォントを参照しているというべきか。なので、日本語文字を含むフォントを参照するように指定すればよい。

しかし、Python仮想環境を作るたびに、あるいはMatplotlibを使うたびに設定するのは非常に面倒なので、グローバルに設定して以降ずっと（新たに仮想環境を作っても）その設定で動いてほしい。

# 結論
`~/.matplotlib` ディレクトリに `matplotlibrc` というファイルを作成し、以下の内容にすればよい。

```
font.family : Hiragino Sans
```

# 補足
このためにフォントをインストールするのは面倒なので、インストール済みのフォントを指定すればいいはずと思いました。
`Hiragino Sans` は私の環境だと最初から入っていたので、これにしました。（入れた覚えがないので、Macならたぶん最初から入ってます）
もしかしたら他にもっといい選択肢があるかもしれません。
【AWS IAM】管理ポリシーとインラインポリシーの違いについて

# はじめに
AWS IAMでは、各AWSサービスの権限を制御する仕組みとして、「AWS管理ポリシー」、「カスタマー管理ポリシー」、「インラインポリシー」が存在する。
このポリシーの違いをまとめたいと思う。

# 管理ポリシーとインラインポリシー
AWS IAMでは、大きく「管理ポリシー」、「インラインポリシー」の2つ種類のポリシーが存在する。
「管理ポリシー」は、さらに「AWS管理ポリシー」、「カスタマー管理ポリシー」に分類することが出来る。

# AWS管理ポリシー
AWSによって事前に用意されたポリシーのこと。
例) AmazonEC2FullAccess等。

# カスタマー管理ポリシー
ユーザによって作成したポリシーのこと。

# インラインポリシー
公式ドキュメントでは、「IAM アイデンティティ (ユーザー、グループ、またはロール) に埋め込まれたポリシー」と記載されている。
公式ドキュメントの記載だけでは、どういったものかが今一つ分からないため、各ポリシーの共通点、違いについてまとめることで理解を深める。

出典：AWSユーザーガイド.「インラインポリシー」. https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#inline-policies ,（参照2022-04-03）

# 各ポリシーの共通点
そもそもポリシーは、「AWSサービスを制御する」ことが目的のため、「AWSサービスを制御する」という点が共通となる。

# 各ポリシーの違い
各ポリシーは、「誰がポリシーを作成するのか」、「各ポリシーの適用可能範囲」が異なる。

## 誰がポリシーを作成するのか

| AWS管理ポリシー | カスタマー管理ポリシー | インラインポリシー |
|:-:|:-:|:-:|
|AWS|ユーザ|ユーザ|

## 各ポリシーの適用可能範囲
| AWS管理ポリシー | カスタマー管理ポリシー | インラインポリシー |
|:-:|:-:|:-:|
|**複数**のAWSアカウントのユーザ、グループ、ロール|**特定**のAWSアカウントのユーザ、グループ、ロール|特定のAWSアカウントのユーザ、グループ、ロール ***1**|

*1 「カスタマー管理ポリシー」が作成したポリシーをユーザ等(ユーザ、グループ、ロール)に適用しても、他のユーザ等に同様のポリシーを適用出来ることに対して、「インラインポリシー」は、作成したポリシーをユーザ等に適用すると、他のユーザ等に対して適用することが出来ない。

各ポリシーの適用可能範囲については、公式ドキュメントの図解が参考になる。
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_managed-vs-inline.html

### AWS管理ポリシーの適用可能範囲
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429119/ed1b3ed8-65bd-e6ed-1903-a04a7b8ff3b4.png)
出典：AWSユーザーガイド.「AWS 管理ポリシー」. https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#aws-managed-policies ,（参照2022-04-03）

### カスタマー管理ポリシーの適用可能範囲
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429119/625341b9-76e9-7240-34e2-6660b8e19254.png)
出典：AWSユーザーガイド.「カスタマー管理ポリシー」. https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#customer-managed-policies ,（参照2022-04-03）


### インライン管理ポリシーの適用可能範囲
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429119/33c1c99d-70c1-459e-3792-a701beacf7f8.png)
出典：AWSユーザーガイド.「インラインポリシー」. https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#inline-policies ,（参照2022-04-03）

## 管理コンソール上の各ポリシーの表示
### AWS管理ポリシー
「AWS管理」と表示されているポリシー名が「AWS管理ポリシー」であることを示す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429119/67741f44-0c4d-68f6-25b9-a36737bc441a.png)

### カスタマー管理ポリシー
「カスタマー管理」と表示されているポリシー名が「カスタマー管理ポリシー」であることを示す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429119/171cf30c-c715-499b-baf3-62bcfaeb23a3.png)


### インラインポリシー
「インラインポリシー」と表示されているポリシー名が「インラインポリシー」であることを示す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429119/7694f5c9-92d2-87e0-4009-5192a878d5fa.png)

「インラインポリシー」は、作成したポリシーをユーザ等に適用すると、他のユーザ等に対して適用することが出来ないため、IAMのポリシー画面では作成した「インラインポリシー」は表示されない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429119/d0fb87fc-0049-eb67-8c0b-b5e22396eb94.png)

### 推奨事項
通常、「インラインポリシー」ではなく、管理ポリシーを使用することが推奨される。
個人的には、特権アカウント管理を行う場合に適用を検討することが良いと考える。例えば、特権アカウント管理を対象ユーザ、グループのみに「限定的に権限を適用」し、かつ、「誤ってその権限を別のユーザ、グループ等に適用させたくない」場合には「インラインポリシー」を適用するのが良いと考える。
PHPでのログイン機能

## フレームワークを使用すれば簡単に実装できるが...
現在、有名なフレームワークというとLaravelやFuelPHPなどがあります。もしフレームワークを使ってログイン機能を実装する場合、大抵は「（フレームワーク名）　ログイン機能」などで検索すればヒットすることでしょう。

### フレームワークのみでは応用が効かない場合がある
実は、フレームワークはあまりにも簡単に機能が実装できるため、いざバグが起きたとしても原因がわからず詰まってしまったり、細かな応用が効かない場合が多いです。内部でどのような処理が行われているのかを把握しないまま簡単に実装ができてしまう、というのが逆にデメリットになります。

## phpのログイン機能実装の流れ
### ユーザーに情報を入力してもらう
ユーザーに情報を入力してもらう為に、htmlで入力フォームを作成し、送信できるようにページを作成する必要があります。

### 入力された情報に対してバリデーションを行う
ここで言うバリデーションというのは、「入力チェック」「書式チェック」のことを指します。例えば、Eメールアドレスであれば、
・アルファベット・数字・記号のみで入力されているか？
・文頭や文末に＠がなく、かつ文中に＠が含まれているか？
・データベースに保存できる文字数を超過していないか？
・その他、悪意のある文字列ではないか？

これをデータベースに接続する前に確認する必要があります。

### データベースからユーザーの情報を取り出し、間違いがないかチェックする
バリデーションチェックを行い、問題がなかった場合は、データベースに接続し、入力された情報をもとにデータベースからユーザーの情報を取得します。その後、入力されたデータとデータベースのデータをチェックし、問題ない場合は次のステップに進みます。

### ログイン状態を付与し、ログイン画面から別のページにリダイレクトする
ログイン状態をユーザーに付与し、マイページなどに遷移させます。ログイン状態を付与するにはセッションを使うのが一般的です。

ログイン処理はこの４ステップで行います。

参考文献：

https://webukatu.com/wordpress/blog/27673/
【iOS】extensionってなに？

<!-- textlint-disable -->
# はじめに
先日、extension について調べてまとめる機会があったので、簡単にまとめてみました。

# extensionとは何か
Swift では既に存在している型に、プロパティやメソッドやイニシャライザなどの方を構成する要素を追加できます。この型の拡張を extension と呼びます。

主に

- クラス
- 構造体
- 列挙型

などに対して機能を拡張します。他にも Int や String などの型でも拡張できます。

# 定義方法
extension の定義方法は以下のように宣言できます。

```swift

extension エクステンションを定義する対象の型 {
    対象の方に追加したい要素
}
```

# 継承との違い
クラスを拡張するという意味では、継承と extension はとても似ています。
しかし、継承の場合は、あるクラスの機能を拡張するため、別のクラスが必要になります。
それに対して extension は既にあるクラスを動的に拡張でき、継承の際に発生するオーバーライドがありません。

つまり、継承はクラスを引き継いで新たなクラスを別名で作るのに対し、extension はそのままの名前でメソッドやプロパティを追加できます。

# メソッドの追加例
String 型を拡張して printHello()というメソッドを追加していきます。

```swift
extension String {
    func printHello(){
        print("Hello, \(self)")
    }
}

let string = "World!"
string.printHello()
```

これを実行すると実行結果は、`Hello, World!` になると思います。

# 参考文献
- Swift 実践入門
<!-- textlint-enable -->
[Laravel]assertExactJsonはどこまで「厳密」なのか

# はじめに

Laravelで`assertJson`よりも「厳密」にテストができるという`assertExactJson`を使っていて、どこでまで厳格なんだろう？時になったことのメモ

https://readouble.com/laravel/8.x/ja/http-tests.html#verifying-exact-match

# assertExactJsonの特徴

## １,全データをテストできる

これはドキュメント見ての通り。

`assertJson`は返ってきたjsonデータの内、**一部のjsonフラグメント**が返ってきているかテストできるメソッドであるのに対して

`assertExactJson`は返ってきた**jsonデータの構成や全フラグメントが完全に一致**していることをテストできる

`assertExactJson`は`etc()`とか使わなくてよくなるし、確実に期待したjsonの構成として返却されていることがテストできる。

## ２,各フラグメントの一致具合も厳格にテストできる

コチラが本題。

例えばこんなjsonを返すControllerがあった場合

```php
public function sample()
{
    return response()->json([
        'sample' => true,
    ]);
}
```

返ってくるjsonは以下になる

```php
{
    sample : true,
}
```

これを`assertExactJson`でテストするとこうなる

```php
protected function testSample()
{
		// API呼び出し(routeの名前は仮)
    $response = $this->getJson(route('sample'));

		// jsonデータを配列に変換
    $response->assertExactJson([
        'sample' => true,
    ]);
}
```

結果は問題なくテストが通る

```terraform
> php artisan test tests/Feature/Api/SampleTest.php

   PASS  Tests\Feature\Api\SampleTest
  ✓ sample

  Tests:  1 passed
  Time:   0.60s
```

### ギモン

ここでギモンなのはここでいう一致は、通常の比較演算子（==）か厳格な比較演算子（===）のどちらを使っているか、ということ。

### 結論

~~結論は厳格な比較演算子（===）を使用している~~

厳密には「Jsonとしての文字列を比較している」というのが正しいです。

@nunulk 様ご指摘ありがとうございました。

https://qiita.com/TkTkTkTkTako/items/eae9472f88342f0ace06#comment-bb3845f18171b929eadf

以下は実際の検証ですので上記認識の状態で「ふーん、そんな結果になるんだ」程度に捉えてもらえるといいかと思います。

### 検証

もし通常の比較演算子（==）を使っていれば、テストの期待値をtrueではなく1にしても問題なくテストが通ることを想定できる。

```php
dump(true == 1);
>> true

dump(true === 1);
>> false
```

そこで先ほどのテストで引数（＝期待値）を1にする

```php
protected function testSample()
{
	// API呼び出し(routeの名前は仮)
    $response = $this->getJson(route('sample'));

	// jsonデータを配列に変換
    $response->assertExactJson([
        'sample' => 1, // 変更
    ]);
}
```

結果、テストは失敗する

```terraform
> php artisan test tests/Feature/Api/SampleTest.php

   FAIL  Tests\Feature\Api\SampleTest
  ⨯ sample

  ---

  • Tests\Feature\Api\SampleTest > sample
  Failed asserting that two strings are equal.

  at tests/Feature/Api/SampleTest.php:94
     90▕         $response = $this->getJson(route('sample'));
     91▕
     93▕         $response->assertExactJson([
  ➜  94▕             'success' => 1,
     95▕         ]);

  --- Expected
  +++ Actual
  @@ @@
  -'{"success":1}'
  +'{"success":true}'

  Tests:  1 failed
  Time:   0.51s
```

これで厳格な比較演算子でテストしていることが検証できた

# おわりに

型が違うのにテストを通してしまうのは怖いことだな、と感じた。

`assertExactJson`にて通常の比較演算子（==）を使っていないことを知り、安心
Apacheで複数ドメインの接続を受け付ける設定と証明書の作り方

# 概要
自宅サーバを公開するにあたって、
IPv4リーチャビリティはルーターメーカーのダイナミックDNSサービスによって、
IPv6リーチャビリティは[OPEN IPv6 ダイナミック DNS for フレッツ・光ネクスト](https://i.open.ad.jp/)によって確保する。
そのときのApacheの設定と、[Let's Encrypt](https://letsencrypt.org/ja/)の証明書の作り方のメモ。

# Apacheの設定
[ServerAalias](https://httpd.apache.org/docs/2.4/ja/mod/core.html#serveralias) ディレクティブを使う。
こんなかんじ
~~~ httpd.conf
<VirtualHost *:443>
(中略)
ServerName (メインとしたいドメイン名)
ServerAlias (サブとしたいドメイン名)
(後略)
</VirtualHost>
~~~
メインとサブの違いはほぼないっぽい。
メインが証明書と秘密鍵のファイル名に使われるくらい。

# 証明書の作り方
[Certbot](https://certbot.eff.org/)がやはり一番楽。
Apacheの設定を済ませたら、 `certbot` コマンドを実行するだけでOK。
なお、下記のログはすでに1個目のドメインを設定済みのときのもの。
新規で設定する場合は出力が違うハズ。

~~~ console
$ sudo certbot
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator apache, Installer apache

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: (ドメイン名1)
2: (ドメイン名2)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): ←そのままエンター

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
You have an existing certificate that contains a portion of the domains you
requested (ref: /etc/letsencrypt/renewal/(ドメイン名1).conf)

It contains these names: (ドメイン名1)

You requested these names for the new certificate: (ドメイン名1),(ドメイン名2).

Do you want to expand and replace this existing certificate with the new
certificate?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(E)xpand/(C)ancel: e
Renewing an existing certificate for (ドメイン名1) and (ドメイン名2)
Deploying Certificate to VirtualHost /etc/apache2/sites-enabled/000-default-le-ssl.conf
Deploying Certificate to VirtualHost /etc/apache2/sites-enabled/000-default-le-ssl.conf
Enhancement redirect was already set.
Enhancement redirect was already set.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Your existing certificate has been successfully renewed, and the new certificate
has been installed.

The new certificate covers the following domains: https://(ドメイン名1) and https://(ドメイン名2)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/(ドメイン名1)/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/(ドメイン名1)/privkey.pem
   Your certificate will expire on 2022-07-02. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again with the "certonly" option. To non-interactively
   renew *all* of your certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:
   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
~~~

# 感想
certbot楽すぎだし、IPv6 onlyなドメインでも普通に対応してくれてるの嬉しい。
12ステップで作る 組込みOS自作入門 HelloWorldまでの記録（MacでBootcampでVirtualBox）

低レイヤーから攻めるキャンペーンということでOSの勉強を始めました。
タイトルの本で勉強を始めましたが、入門するまでに環境構築でハマったポイントを共有します。

最終的に動いた環境
MacBookPro 16インチ 2019 Bigsur
Bootcamp Windows10
VirtualBox v6.1 
CentOS 

マシンはMacです。gccなどのインストールで躓くことは容易に予想ができたため、公式で紹介されているVMイメージを使うことにしました。

VirtualBoxをインストールしてVMイメージを立ち上げたところ、Xwindowを起動すると極端に重く、数回操作をするとフリーズしてしまうためダメでした。調べたところによるとRetinaモデルだと解像度のスケーリングがうまくいかないようです。

続いてBootCampからWindows10を立ち上げて、その中でVirtualBoxをインストールしてVMイメージを立ち上げました。今度はうまくいきました。

ただこのイメージはCentOS6系で、サポートが終了しているらしく、yumでのパッケージインストールに失敗するようでした。（回避する方法もあるようですが自己責任なようです。）

ソースをMakeしてH8writeを使ってH8にいざ書き込もうとしたところ、書き込み命令の途中でハングしてしまいました。ケーブルの相性か？とも思ったのですが、kz_h8writeを使って書き込みにトライしたところ今度はうまく書き込めました。
使用したUSBシリアル変換ケーブルはこちらです。
https://akizukidenshi.com/catalog/g/gM-02746/

書き込み先デバイスはdev/ttyUSB0　で行けました。
ケーブルのドライバは付属のCDROMを使いました。（VMの設定からUSBシリアルを有効にするのをお忘れなく）

続いてminicomを起動してH8との通信を試しました。
書籍にある通りポートとボーレートを変更します。
そしてついにHelloWorldできました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2380862/a95779dc-9f63-665b-af8b-f3cd319d5568.png)

ようやく組み込みOSの自作に入門ができました。
ここから写経したりコードを読み解いたりしていこうと思います。

事前にPICマイコンやArduinoを触っていた知識が環境構築に役に立ちました。これがなかったら何をやっているのかわからなさすぎて挫折していたと思います。
global git hook を作った話

# 概要

各リポジトリの　git hook　も読み込みつつ、どのリポジトリでも反映したい git hook がほしいなと思ったので作った

# 成果物

MITライセンスなので、お好きに clone するなり fork するなりしてくださいませ！
使い方は README.md に書いてます🐳

https://github.com/amabie-mamoru/global-git-hooks

# 背景

git hook の既存の仕組みはリポジトリごとに設定するもので global git hook 的な位置付けものは公式にはない
これに対してもちろん先人の方々が色々と global git hook 的な位置付けの記事を投稿されている

それらは以下のようなものがあった

* global git hook 的なもののサンプル
* ローカルの git hook を無視してグローバルの git hook を設定するもの
* 逆にグローバルの git hook をローカルに適応する(コピーする)もの

ただ、チームや団体で扱うリポジトリがある場合、以下のような課題を感じた

* 即使いたい
* ローカルの git hook は無視するとよろしくない
* 個人的なグローバルの git hook をコミットしたくないケースも多い

そこで、 fork したり clone するだけで、特に細かいことは考えなくても使える snippet 的な位置付けの global git hook を作ることにした🧜‍♂️

# 課題点

もちろんこの global git hook にも課題はある

それは git 公式側が新しい git hook を追加した場合に、この global git hook にもそれに該当するファイルを追加しないとローカルの git hook が無視されてしまうという点である
もし追加漏れなどあれば issue にあげてもらえると嬉しい

# 最後に

もっといい方法があればコメントください！
この記事で一人でも多くのエンジニアが手早くやりたいことを実現できますように🐳
FileManager事件簿〜ファイルを保存したパスにファイルがない

# FileManagerでファイルを保存したパスのファイルが消える事件発生

例えば画像をアプリのDocumentDirectoryに保存して、あとでロードしたいとするじゃないですか。
とりあえずpngをFileManagerで作ったurlに保存して、pathのstringをUserDefaultsで保存しとく。


```swift
let imageData:Data = uiImage.pngData()
let url:URL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent(UUID().uuidString+".png")
try! imageData?.write(to: url)
let path:String = url.path
UserDefaults.standard.set(, forKey: "imagePath")
```

で、アプリを一度終了したあと、同じパスから画像を読み出そうとする。

```swift
let savedPath = UserDefaults.standard.string(forKey: "path")!
let url = URL(fileURLWithPath: savedPath)
let data = try! Data(contentsOf: url)
let uiImage = UIImage(data: data)
```

すると、ファイルがない！

# 解決

原因は、アプリを終了すると、アプリのドキュメントディレクトリのパスが変わることがあるため。
というのは、アプリを閉じる前だと、上記のコードは機能します。
対策として、ファイル名だけUserDefaultsで保存しておいて、再度ファイルマネージャーでドキュメントディレクトリを探してファイル名を付け足すと、保存したファイルが見つかります。

Save:

```swift
let imageData = image?.pngData()
let uniqueFileName = UUID().uuidString+".png"
let url = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent(uniqueFileName)
try! imageData?.write(to: url)

UserDefaults.standard.set(uniqueFileName, forKey: "path") // ファイル名だけ保存しておく
```

Load:

```swift
let fileName = UserDefaults.standard.string(forKey: "path")!
let url = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent(fileName) // 再度ドキュメントディレクトリを検索して、ファイル名を付け足す。
let data = try! Data(contentsOf: url)
let uiImage = UIImage(data: data)
```

これで無事に読み出せます。

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
plotly で複数のサブプロットを取ってグラフを追加する

plotlyの勉強中。メソッドがやたらあって検索すると色々なやり方がヒットして戸惑う……。

plotly で３行・３列のサブプロットを取る。そして、１行１列目、２行２列目、３行３列目に折れ線グラフを追加したいとする。以下の３つはすべて同じ結果。

~~~python
from plotly.subplots import make_subplots

fig = make_subplots(rows=3, cols=3)

#「折れ線グラフを追加する」メソッド。どのサブプロットに追加するかをrow,colで指定する。
#何も考えずに追加するならこれが一番簡単。
fig.add_scatter(y=[1,3,1], row=1, col=1)
fig.add_scatter(y=[2,2,2], row=2, col=2)
fig.add_scatter(y=[3,1,3], row=3, col=3)
fig.show()
~~~

```python
from plotly.subplots import make_subplots

fig = make_subplots(rows=3, cols=3)

#「グラフ」を追加するメソッドに、折れ線グラフを渡す。
fig.add_trace(go.Scatter(y=[1,3,1]), row=1, col=1)
fig.add_trace(go.Scatter(y=[2,2,2]), row=2, col=2)
fig.add_trace(go.Scatter(y=[3,1,3]), row=3, col=3)
fig.show()
```
```python
from plotly.subplots import make_subplots

fig = make_subplots(rows=3, cols=3)

#複数グラフの追加に対応したメソッド。
#追加するグラフをリストで渡し、どのサブプロットに追加するかをrows,colsで指定する。
#グラフのリスト順とrows, colsのリスト順が対応するように注意すること。
fig.add_traces([
    go.Scatter(y=[1,3,1]),
    go.Scatter(y=[1,1,1]),
    go.Scatter(y=[3,1,3])
],rows=[1,2,3], cols=[1,2,3])
fig.show()
```
![グラフ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143934/bd1f91d3-f5c7-374e-ed90-7d292eff04fb.png)



print_grid() を使うことでサブプロットのグリッドを確認できる。
~~~
fig.print_grid()
~~~
>This is the format of your plot grid:
>[ (1,1) x,y   ]  [ (1,2) x2,y2 ]  [ (1,3) x3,y3 ]
>[ (2,1) x4,y4 ]  [ (2,2) x5,y5 ]  [ (2,3) x6,y6 ]
>[ (3,1) x7,y7 ]  [ (3,2) x8,y8 ]  [ (3,3) x9,y9 ]
Outsystems Service Studioの概要

［Environment］タブの検索ボックスを使用すると、アプリケーションやモジュールを検索したり、OutSystemsコミュニティの検索を実行したりすることをできます。

新規アプリケーションを作成したり、既存アプリケーションを利用したりすると、以下のアプリ詳細画面に移動します。

アプリ詳細画面には、以下の領域があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1209998/3d3bbdb1-e90b-81d9-c58c-d43fe8c39aee.png)

Developタブ
ここでは、アプリケーションのモジュールを管理します。アプリケーションの依存関係、アプリケーションで使用されている他のアプリケーションやコンポーネントを表示することもできます。
Service Studioのワークスペースは、アプリケーションのモジュールを設計、配置、デバッグ場所です。

ワークスペースは、以下の区域で構成されています。

TrueChangeタブ: モジュールの既存のエラーと警告を表示するタブ。

Debuggerタブ: このタブを使用してアプリケーションをデバッグします。

1-Click Publishタブ: モジュールをデプロイすると、この領域にデプロイプロセスの進捗状況と結果が表示されます。

ステータスバー

各タブには、特定のアプリケーションレイヤー（プロセス、ユーザーインターフェイス、ロジック、およびデータモデル）の要素が含まれています。
Widgetについて学んでみる③

## ShowSnackBarの表示の仕方
公式ドキュメント
https://api.flutter.dev/flutter/material/SnackBar-class.html
日本語の記事
https://flutternyumon.com/flutter-how-to-use-snackbar/

**今回は短いですがでもアプリを簡単に作ってみました**

main.dart
```dart
import 'package:flutter/material.dart';

// アロー関数で書いてみた!
void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({ Key? key }) : super(key: key);

  static const titleName = 'SnackBar';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text(titleName),
        ),
        body: const ShowSnackBar(),
      ),
    );
  }
}

class ShowSnackBar extends StatefulWidget {
  const ShowSnackBar({ Key? key }) : super(key: key);

  @override
  State<ShowSnackBar> createState() => _ShowSnackBarState();
}

class _ShowSnackBarState extends State<ShowSnackBar> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          ElevatedButton(
            onPressed: () {
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(
                  backgroundColor: Colors.amber,
                  duration: const Duration(days: 7),
                  content: const Text('こんにちは!', style: TextStyle(color: Colors.black87, fontSize: 20, fontWeight: FontWeight.bold),),
                  action: SnackBarAction(
                    label: '閉じる',
                    onPressed: () {
                      print('閉じるラベルが押されました');
                    },
                  ),)
              );
            },
            child: const Text('アクション', style: TextStyle(fontSize: 20),))
        ],
      ),
    );
  }
}
```
![snackbar.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303722/2cbb0fc7-b3ae-9ca5-a493-d9a5128f8cdc.gif)
Laravel Octaneで「最寄り駅検索」を30ms以下で応答させる高速化法

最寄りの駅を検索して返却するAPIサービス【NeaREST API】を公開してみたのでご紹介します。
※以前zennに投稿した内容と同じです
- 商用利用無料
- 認証制限なし
- 高速応答
- 最大検索件数20件
## 概要・デモ
以下ページにAPIドキュメントと仕様がありますのでご確認ください。

https://station.ic731.net/docs/near

また、簡単なデモとして今いる位置から最も近い駅を検索するアプリを公開していますのでスマートフォンでお試しください。

https://station.ic731.net/demo/nearest

以下のようなJSONを返却します。

```json
{
    "meta": {
        "status": "success"
    },
    "data": [
        {
            "station_id": 9930101,
            "station_name": "都庁前",
            "pref": "東京都",
            "post": "1600023",
            "address": "新宿区西新宿２-８-１",
            "location": [
                139.69257,
                35.690551
            ],
            "distance": 148
        },
        // 以降続く…
```

## 作った動機
最寄り駅を検索するAPIはすでに存在し、以下のようなものが挙げられます。
- NAVITIME API
- 駅すぱあとWebService
- HeartRails

この中で無料で使えるのは一番最後の**HeartRails Express 路線／駅名／最寄駅データサービス** 様だけ。
実質的に無料で使う場合のスタンダードであり、このサービスがなくなると無料なサービスはなくなってしまいます。

その他にも選択肢をもたせるのは非常に大切な事だと思い、今回開発して公開しました。

## 仕組み
構成・技術スタックは以下の通りです。
### メインシステム
メインシステムはLaravel 9を用いました。

https://laravel.com

個人事業主の大学生とという身分なもので素早い開発とメンテナンスのしやすさを鑑み無難なLaravelに。
PHPのバージョンは開発環境・本番サーバーともに8.1系です。
（最初Lumenでやろうと思ったのですがもう非推奨なんですね）
### データベース
今回、他サービスとの干渉防止と可用性の担保・高速処理を目指したく、駅情報データベースを個人的に推しているDBaaS【MongoDB Atlas】を利用しました。

その名の通りドキュメント志向データベースのMongoDBをホスティングするサービスで、共用メモリ500MBのClusterを無料で使えておすすめです。

https://www.mongodb.com/ja-jp/atlas/database

DBaaSを使うことでデータベースの保守管理コストの軽減を図りました。
駅情報データベースは **[駅データ.jp様](https://ekidata.jp)** の最新データを独自に再フォーマットして格納しています。

## 応答速度30msへの高速化
今回開発するに当たって高速化という点にも重きを置きました。
![Screenshot_20220401_171722.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513165/35091083-5ba7-686e-3b29-e6534a8573b3.jpeg)
### 地理空間インデックス
MongoDBに保存している駅情報の位置情報に地理空間インデックスを付与し、**効率的かつ最適なロジックで球面モデルを使用した最寄りの駅を検索する** ことができた（つもり）

少し古いですが以下情報などを参考にしました

https://qiita.com/fetaro/items/7f110f18c6dd9ccd0c90

https://gihyo.jp/dev/serial/01/mongodb/0009

### Laravel Octane
普通に開発して実装した時点でも応答速度は50ms程度と高速なのですが更に早くした意欲が出てしまい、Laravelを高速なミドルウェアで動かせるパッケージ「Laravel Octane」も活用しました。

導入手順

https://0115765.com/archives/7350

結果、**abテストで50ms→29msの高速化**を実現しました。
実際のところ、Apacheのリバースプロキシを使っているため実際は40ms程度まで落ちるのですがそれでも十分早くなっていると思います。

以上、ざっと紹介させていただきました。ぜひ使っていただけると幸いです！
※紹介スライド

https://www.docswell.com/s/ichii731/ZNXYGK-nearest
【Salesforce】主従関係は何連まで繋げるのか

## はじめに

[公式](https://help.salesforce.com/s/articleView?id=sf.overview_of_custom_object_relationships.htm&type=5)のこの文言

>Closely links objects together such that the master record controls certain behaviors of the detail and subdetail record. 
For example, you can define a two-object master-detail relationship, such as Account—Expense Report, that extends the relationship to subdetail records, such as Account—Expense Report—Expense Line Item.
 You can then perform operations across the master—detail—subdetail relationship.
【訳】
マスターレコードが詳細レコードとサブ詳細レコードの特定の動作を制御するように、オブジェクト同士を密接にリンクします。
たとえば、「勘定科目-経費報告書」のような2つのオブジェクトのマスターと詳細の関係を定義し、「勘定科目-経費報告書-経費明細」のようなサブ詳細レコードにその関係を拡張することができる。
 そして、マスター・詳細・サブ詳細の関係にわたって操作を実行することができます。


パッと見「```主 - 従 - 従の従``` までしか主従関係を作れないよ」という意味にも取れたので、
どれくらい作れるのか実験してみました。

## 結論

```主 - 従 - 従の従 - 従の従の従```までつなげました。

### ここで気になるのは

> そして、マスター・詳細・サブ詳細の関係にわたって操作を実行することができます。

もしかして、主従関係を結ぶこと自体はできるけど、カスケード削除とかの「操作」はできないよって意味なのでしょうか。

### 実際にレコードを作ってカスケード削除してみる

主を削除したところ、
```主 - 従 - 従の従 - 従の従の従```
すべて消えて、カスケード削除ができました。

積み上げ集計項目はそもそも自分の```従```しか参照できないし、
他に「```従の従```までならできるけど、```従の従の従```に対してはできない」操作があるのでしょうか。

使っていくうちに気づく日がくればいいなあ。
vimでdeopleteを使うときに出たエラーを解決

ある日突然vim起動時にエラーが出力されるようになった。  
エラー原因のきっかけは恐らく前日に実行した``` $ brew upgrade ```。  
今回のエラーは過去に何度も経験しているのでメモを残すことに。  

結論、vimの見ているpythonに必要なライブラリをインストールすることで解決。  

## エラーメッセージ
```
[deoplete] VimEnter Autocommands for "*"..function deoplete#enable[9]..deoplete#initialize[1]..deoplete#init#_initialize[10]..<SNR>76_init_internal_variables[11]..neovim_rpc#serveraddr, 行 18
VimEnter Autocommands for "*"..function deoplete#enable[9]..deoplete#initialize[1]..deoplete#init#_initialize[10]..<SNR>76_init_internal_variables[35]..VimEnter Autocommands for "*"..function deoplete#enable[9]..deoplete#initialize[1]..deople
te#init#_initialize[10]..<SNR>76_init_internal_variables[29]..neovim_rpc#serveraddr の処理中にエラーが検出されました:
行   18:
E605: 例外が捕捉されませんでした: [vim-hug-neovim-rpc] requires one of `:pythonx import [pynvim|neovim]` command to work
```

何やら必要なものが足りていないとか。  
早速確認してみる。  

## ライブラリのインストール状況を確認（shellの見ているpython）
```
$ pip3 list | grep pynvim
pynvim                            0.4.2
```

見たところ入っている様だが、、、  

ここで **vimとshellの見ているpythonが違う** と予想。  

まずはそれぞれの見ているpythonを確認。

## vimの見ているpython情報を確認
```
$ vim --version | grep python                                                                                                                                                                                                    [~]
+cmdline_hist      +langmap           -python            +viminfo
+cmdline_info      +libcall           +python3           +virtualedit
リンク: clang -L. -fstack-protector-strong -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/openssl@1.1/lib -L/usr/local/opt/readline/lib -L/usr/local/lib -o vim -lm -lncurses -liconv -lintl -framework AppKit -L/usr/local/opt/lua/lib -llua5.4 -mmacosx-version-min=11.3 -fstack-protector-strong -L/usr/local/lib -L/usr/local/Cellar/perl/5.34.0/lib/perl5/5.34.0/darwin-thread-multi-2level/CORE -lperl -L/usr/local/opt/python@3.10/Frameworks/Python.framework/Versions/3.10/lib/python3.10/config-3.10-darwin -lpython3.10 -framework CoreFoundation -lruby.3.1 -L/usr/local/Cellar/ruby/3.1.0/lib

$ /usr/local/opt/python@3.10/Frameworks/Python.framework/Versions/3.10/bin/python3 -V                                                                                                                                            [~]
Python 3.10.2
```

## shellの見ているpython情報を確認
```
$ which python3                                                                                                                                                                                                                  [~]
/Users/qoncyu/.pyenv/shims/python3

$ /Users/qoncyu/.pyenv/shims/python3 -V                                                                                                                                                                                          [~]
Python 3.9.10
```

うん、予想通りに違うものを見ている。  
念のためvimの見ているpython環境にライブラリがインストールされていないことも確認。

## ライブラリのインストール状況を確認（vimの見ているpython）
```
$ /usr/local/opt/python@3.10/bin/pip3 list | grep pynvim
```

こちらも予想通り入っていない。
合点がいったところで、正しい場所にライブラリをインストール。

```
$ /usr/local/opt/python@3.10/bin/pip3 install pynvim
```

解決


## 最後に
早くddc.vimに置き換えよう。
Databricksでmatplotlibを使う

[Matplotlib \| Databricks on AWS](https://docs.databricks.com/notebooks/visualizations/matplotlib.html) [2022/2/1時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

:::note info
**訳者注**
- Databricksには簡単にグラフを表示する機能がビルトインされています。詳細は[Databricksにおけるデータの可視化](https://qiita.com/taka_yayoi/items/36a307e79e9433121c38)を参照ください。
- matplotlibにおける日本語文字化けについては、[こちら](https://qiita.com/uehara1414/items/6286590d2e1ffbf68f6c
)の記事を参照ください。
:::

Matplotlibの図の表示方法は、使用しているDatabricksランタイムのバージョンに依存します。

- Databricksランタイム6.5以降では、Matplotlibの図はインラインに表示されます。
- Databricksランタイム6.4ESでは、マジックコマンド`%matplotlib inline`を呼び出す必要があります。

以下のノートブックでは、Pythonノートブックでどのように[Matplotlib](https://matplotlib.org/)の図を表示するのかを説明しています。

# Matplotlib Pythonノートブック

https://docs.databricks.com/_static/notebooks/matplotlib.html

```py:Python
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2*np.pi, 50)
y = np.sin(x)
y2 = y + 0.1 * np.random.normal(size=x.shape)

fig, ax = plt.subplots()
ax.plot(x, y, 'k--')
ax.plot(x, y2, 'ro')

# tickとtickのラベルを設定
ax.set_xlim((0, 2*np.pi))
ax.set_xticks([0, np.pi, 2*np.pi])
ax.set_xticklabels(['0', '$\pi$','2$\pi$'])
ax.set_ylim((-1.5, 1.5))
ax.set_yticks([-1, 0, 1])

# y-tick間のspineのみを描画
ax.spines['left'].set_bounds(-1, 1)
# 右と上部のspineを隠す
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
# 左と下のspineのtickのみを表示
ax.yaxis.set_ticks_position('left')
ax.xaxis.set_ticks_position('bottom')
```

インラインでグラフが表示されます。
![Screen Shot 2022-04-03 at 10.55.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/f86c01bc-5e52-667f-1a60-316baf20ec2a.png)

# 高解像度で画像をレンダリングする

Pythonノートブックでは、標準の倍の解像度でmatplotlibの画像をレンダリングすることができ、高解像度の表示で優れたビジュアライゼーション体験をユーザーに提供することができます。ノートブックのセルで以下のいずれかを指定指定します。

`retina`オプション

```py:Python
%config InlineBackend.figure_format = 'retina'

from IPython.display import set_matplotlib_formats
set_matplotlib_formats('retina')
```

`png2x`オプション

```py:Python
%config InlineBackend.figure_format = 'png2x'

from IPython.display import set_matplotlib_formats
set_matplotlib_formats('png2x')
```

標準の解像度に戻すには、ノートブックセルに以下を追加します。

```py:Python
set_matplotlib_formats('png')

%config InlineBackend.figure_format = 'png'
```

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
変数に値が入っているか判定 isset

## 用途
変数に値が入っているかを判定したい時に使う

## 使用方法
```php:php
if (isset(変数名)) {
  // 変数がある場合の処理;
} else {
  // 変数がない場合の処理;
}
```

:::note warn
注意
「変数の値がある場合、且つNULLでない場合」に `TRUE` を返す。
「NULL」または、「値がない場合」は `FALSE` を返す。
:::
foreachカウンター

## 用途
foreach内で何回ループしたかを数える際に使用する。

## 使用方法
```php:php
<?php 
$hoge = ["赤", "青", "緑", "黒", "白"];
$counter = 0; //カウンター

foreach($hoge as $h) {
	var_dump($h."<br>");
	var_dump($counter."<br>");
	$counter++; //カウントを１ずつ増やす
};
```

```:結果
赤
0
青
１
緑
２
黒
３
白
４
```

　
　
　
この記事は以下の情報を参考にして執筆しました。
- https://dezanari.com/php-foreach-counter/
VertualBoxに仮想マシンを作成する手順（macOS）

## 概要

備忘録として、下記手順を記載する。
・VertualBoxに仮想マシン(CentOS7)を作成する手順


### 前提
OS：macOS Big Sur
バージョン：11.2.1

下記作業を実施済みであること
1. [CentOS7をダウンロード](https://qiita.com/kazuho_0531/items/f413c5914a632c4cd83f)
2. [VertualBoxをインストール](https://qiita.com/kazuho_0531/items/ecf57d5b780e0e3d87ff)

## 1. 仮想マシン作成手順
- VirtualBoxを起動
- 上部の［新規］をクリック
![スクリーンショット 2021-06-20 16.49.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/197db3e5-0947-f491-3d0c-dbe46afab8c1.png)
- ［名前とオペレーティングシステム］ダイアログボックスが表示される
- ［名前：］に`CentOS7`を入力
   - 　自動で［タイプ：Linux］［バージョン：Red Hat(64-bit)］が入力される
- ［続き］をクリック
![スクリーンショット 2021-06-20 16.50.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/eb19dcf8-d338-0c56-6be7-90b6848059fa.png)
- ［メモリーサイズ］画面に遷移
- 仮想マシンに割り当てる、メモリーサイズを指定
   - 初期設定は`1024MB`だが、今回は`2000MB`を指定
- ［続き］をクリック
![スクリーンショット 2021-06-20 16.58.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/48eb077c-92c3-1f46-74ab-eadc2227ecec.png)
- ［ハードディスク］画面に遷移
- 今回は新規に仮想マシンを作成するため、`仮想ハードディスクを作成する`を選択
- ［作成］をクリック
![スクリーンショット 2021-06-20 17.01.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/f3d31575-d36c-1b05-196b-8b83c691e2f2.png)
- ［ハードディスクのファイルタイプ］画面に遷移
- `VDI(VirtualBox Disk Image)`を選択
- ［続き］をクリック
![スクリーンショット 2021-06-20 17.03.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/6bcb5390-875d-5d06-25bc-f7f664d5c47e.png)
- ［物理ハードディスクにあるストレージ］画面に遷移
- ストレージに余裕がある場合は、`固定サイズ`を選択しよう
- ［続き］をクリック
![スクリーンショット 2021-06-20 17.06.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/6c88191f-d56b-6372-f738-d97622473f08.png)
- ［ファイルの場所とサイズ］画面に遷移
- 作成する仮想マシンを格納するフォルダを指定
- 仮想マシンのサイズを指定
- ［作成］をクリック
![スクリーンショット 2021-06-20 17.08.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/7c6d2fe2-fc9d-0dab-0f52-f356346a024f.png)

## 2. 仮想マシン作成 確認手順
以下2点から、仮想マシンが作成されたことを確認する
1. 指定した名前の仮想マシン(`CentOS7`)が、仮想マシン一覧に追加されたこと
![スクリーンショット 2021-06-20 17.13.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/57ec793f-ace3-f16b-956c-06be48cd644c.png)
2. 指定したフォルダに、仮想デスクトップ基盤が格納されていること
![スクリーンショット 2021-06-20 21.31.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581782/25985991-9185-8c05-35a5-14e7b42ca970.png)

以上
プロキシサーバをdocker composeで作成した際に注釈を入れてみました

# 前提
ローカル環境でドメインを本番と同じように使いたいという状況で複数サイトをDockerで立ち上げる際にプロキシサーバを立ててドメインごとに環境を振り分けるということでNginxコンテナを使用したものです。

# docker-compose.yml

```
#docker-compose.ymlにもバージョンがあるので指定します。
version: "3.7"
services:
  #サービス名、ここからコンテナの定義をしますよという階層。
  proxy:
  #イメージとはコンテナの雛形のようなものです。今回はjwilder/nginx-proxyというものを指定することでダウンロードして使っています。ちなみにローカルで自作することもできます。
    image: jwilder/nginx-proxy
    #ここでコンテナの名前を任意につけています。省略も可能です。
    container_name: proxy
    #使用するポートを設定しています。左がローカルPCで右がコンテナ内のポートで２つを繋ぎ合わせることで通信できるように設定しています。80はhttp、443はhttpsです。
    ports:
      - "80:80"
      - "443:443"
    volumes:
      #以下はDockerコンテナの起動・終了を検知するために必要になります。起動を検知すると、nginxの/etc/nginx/conf.d/default.confを書き換えてupstreamを自動追加してくれます。
      - /var/run/docker.sock:/tmp/docker.sock:ro
      #以下は必要になった際に設定すれば良いと思います。個人的にはnginxのファイルアップロード容量を大きくしたい場面がありnginxディレクトリごとDocker内からダウンロードしてバインドマウントしています。
      - ./nginx:/etc/nginx
      #.以下はSSL証明書置き場としてバインドマウントしています。
      - ./certs:/etc/nginx/certs:ro
    #以上終了した際にrestartをするかどうかの設定です。
    restart: always
    #5Mごとにログファイルを作成して10ファイルまで作成するというログローテーションを設定しています。
    logging:
      options:
        max-size: 5m
        max-file: "10"
volumes:
#volumeの設定、volume名をsharedに設定しています。
  shared-volume:
    name: shared
networks:
  #ネットワークの設定をしています。ここでは明示的に名前をsharedに設定しています。
  default:
    name: shared
```

# 参考
[VPSにdockerで複数サイトをホスティングするには？](https://suin.io/561)
ABC246 D問題 2-variable function を考える

# 公式ページ

https://atcoder.jp/contests/abc246/tasks/abc246_d

# 記事の内容
この問題の公式解説を読んだものの、尺取り法による高速化がすぐに理解できなかったので、考え方をメモ
ついでにQiita初投稿です。

# 問題の要約
$N \leqq X=a^3+a^2b + ab^2+b^3$ を満たすような非負整数 $(a,b)$ の組の内、
$X$ 最小となる $(a,b)$ を求める。
$N$は標準入力から与えられ、$0 \leqq N \leqq 10^{18}$ を満たす

# 基本的な考え方
$X=a^3+a^2b + ab^2+b^3$ であるから、$b=0$ としたときに$X=a^3$なので、$a \leqq 10^6$ 
　⇒ 探索範囲の終点。bも同様。

$a,b$ は非負なので、$X \geqq \ 0$。 
$a,b$ は大小関係が無く区別する必要はないので、
$a: 0 \rightarrow 10^6, \ b: 10^6 \rightarrow 0$ へ探索。

これだけでもAC可能。

# 尺取りの考え方
$b$ の探索範囲を限定する。
最小となる $X$ を探すことに着目。

それまでに探索した中で最小の $X$ よりも、
明らかに大きい $X$ が出てくる $(a,b)$ の組は探索しないように、探索範囲を限定していく。

### やり方
① $a,b$ に大小関係が無いから、 $a: 0 \rightarrow 10^6, \ b: 10^6 \rightarrow 0$へ探索するとき、
　$a > b$ となったら終了して良い
② $a=0固定,b:10^6 \rightarrow 0$ へ探索して $N \leqq X$ となる最小の $b_{min(a=0)}$ があった場合、
　$a=1,2,...$ を探索するとき $b_{min(a=0)} \leqq b \leqq 10^6$ の範囲は探索しなくて良い
　  なぜなら、上記範囲では必ず $X>X_{(a,b_{min(a=0)})}$ となるから。

という風にすると、$a=0,1,2,...$ と進むにつれて、
 $b$ の探索範囲はどんどん限定されていくことになる。

# 3次元的に観る
$a=0\sim 10,\ b=0\sim 10$ のZ軸 $X$ のプロット
灰色が $X=2048$ の平面

**直感的に、右下（$a=10,b=10$ の辺り）は探索不要だと分かる**

ループが進むと灰色の平面が上から降りて来るが、$a,b$ が整数だから離散的な表現しかできず、
引っ掛かって止まるイメージ。

灰色平面とカラーマップ平面の、Z軸方向でより0に近い新しい交点が分かったら、
交点から右下は探索範囲から外される。
![Figure_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471338/16d19936-62d9-01d3-88a6-0909d1e0dc6e.png)


# ソースコード
$X=2048$ となる $N$ を入力すると上図と同じプロットが得られます。

```Python
# Python 3.7.3
def Xcal(a,b):
    return a**3 + a*a*b + b*b*a + b**3

N = int(input())

#----- 基本的な解答 -----#
ans = float('inf')
b = 10**6

for a in range(10**6):
    while Xcal(a,b) >= N and b >= 0:
        ans = min(ans,float(Xcal(a,b)))
        b -= 1
print(f'基本: {int(ans)}')

#----- 尺取りの解答 -----#
ans = float('inf')
a = 0
b = 10**6

while a <= b:
    if Xcal(a,b)>=N :
        ans = min(ans,float(Xcal(a,b)))
        b -= 1
    else:
        a += 1
print(f'尺取: {int(ans)}')

#----- プロットを眺める用のコード -----#
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d, Axes3D
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(projection='3d')

# 3Dプロット
x_data = np.linspace(0,10,100)
y_data = np.linspace(0,10,100)
x, y = np.meshgrid(x_data,y_data)
z = Xcal(x,y)
ax.plot_surface(x,y,z,cmap='jet')

# 解答の平面プロット
x_data = np.linspace(0,10,100)
y_data = np.linspace(0,10,100)
x, y = np.meshgrid(x_data,y_data)
z = (x+y)*0.0 + ans
ax.plot_surface(x,y,z,color='gray')

plt.show()
```

# おわりに
などと書きつつ、当時は良く分からない別法に走ってTLEだったので、次回は頑張ります。
久しぶりにTeX記法？を使って懐かしい気持ちになりました。