OmniAICreator/Qiita-1.07M huggingface dataset:
VisualForce Email Templateの制限


# 宛先にはリードと取引先責任者しか使えないようです。

 I tried to actually email the record to myself using the Activity > Email tab. Recipient is therefore a user (me). The template also says recipientType is User. When I click the Send button, I get this error message: **"You must send visualforce templates to either a Contact or a Lead."**

[HTML Source bug sending Rich Text field in VisualForce Email Template](https://salesforce.stackexchange.com/questions/265218/html-source-bug-sending-rich-text-field-in-visualforce-email-template)

 Error:You must send visualforce templates to either a Contact or a Lead.

[Error:You must send visualforce templates to either a Contact or a Lead.](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Fy74gSAB)


まず、recipientTypeはWhoIDとも呼ばれ、次に、relatedToTypeは通常の電子メールテンプレートではwhatIDとも呼ばれます。さらに、replyToアドレスを定義して、電子メールに返信するすべての人がこのアドレスに返信できるようにすることができます。
First, the recipientType also called the WhoID and secondly the relatedToType also refered to as the whatID in regular email templates. In addition, a replyTo address can be defined, so that anyone replying to the email can reply back to this address.

[VFメールテンプレートの「recipientType」と「relatedToType」](https://salesforce.stackexchange.com/questions/207018/recipienttype-relatedtotype-in-vf-email-template)

**WhoId**
WhoIdは、アクティビティ関連オブジェクトの「名前」フィールドのAPI名です。タスクをSalesforce内のリードまたは連絡先レコードに関連付ける場合は、このフィールドに入力する必要があります。  

私のタスクまたはイベントに関しては、通常、このフィールドを別の人間を参照するフィールドと呼びます。  

Salesforceイベントを使用してクライアントとの会議を追跡する場合、ユーザーは、このフィールドに、会議中のリードまたは連絡先を入力する必要があります。組織で共有アクティビティを有効にしている場合は、アクティビティに複数の連絡先とリードを関連付けることができます。この機能を使用すると、最大50件の連絡先またはリードを非定期的なアクティビティに関連付けることができます。


[WhoIdとWhatIdの違いは何ですか？](https://www.salesforceben.com/what-is-the-difference-between-whoid-and-whatid/)

# Invalid Field 

+ [visualforce email template - Invalid Field for SObject Opportunity](https://developer.salesforce.com/forums/?id=9060G0000005MpgQAE)
+ [Visualforce Email Template Invalid Field for SObject](https://salesforce.stackexchange.com/questions/147150/visualforce-email-template-invalid-field-for-sobject)
+ [【未解決】Just trying to replace Custom object with Standard one in Classic email template and facing this error? Any thought what might be wrong?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JgAMD)

:::note alert
The template relatedTo type must be a valid SObject, not SurveyInvitation.
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/acd4534c-8e4c-ffa0-b67a-da27824ffa07.png)
Kali Linux2022.1 でハッキングラボをつくってみる 1 導入編

# 記事の目的
- IPUSIRON著の『ハッキングラボのつくりかた』の勉強のため
- 同書の初版の出版年が2018年であり、現在のKali Linuxと環境がいくらか違う。他に同書を利用して、ハッキングラボの構築のための勉強をしている人に参考となる情報を提供するため

## 当方の環境の説明
同書に従い、ハッキングラボはOracleのVirtualBoxを利用した仮想マシン上に構築する。
物理マシンのホストOSと仮想マシンのゲストOSの環境は、次の通り。
ホストOSの環境
FerenOS 2022.03 64bit版(Ubuntu20.04 focalと同等)
メモリ: DDR4-2133 16GB
CPU: Intel core i5-6500 @3.20Ghz

ゲストOSの環境
Kali Linux2022.1(64bit版)
環境設定はovaファイルからインポートすることで行う。同書では、ホストOSがWindows10 64bit環境であったが、上記のホストOSでも問題なかった。

今回は、VirtualBoxのインストールは省略する。理由は、ホストOSごとにインストール方法が違うため。
ちなみに、どの環境でもVirtualBox Extension Packのインストールは推奨です。
[ダウンロードページ](https://www.virtualbox.org/wiki/Downloads)

## Kali Linuxのインストール
Kali Linuxのインストールは様々あるが、今回はovaファイルを利用してのインストールを行う。
下記のURLからVirtualBoxのovaファイルをダウンロード
(torrentでもダウンロード可能。ダウンロード後はsumをチェック。）
https://www.kali.org/get-kali/#kali-virtual-machines
![2022-04-06 13.48.59 www.kali.org c2af2ece3a3b.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535888/31e71087-2c89-eabc-7c68-a3f95dbf1f21.jpeg)

ダウンロード後に、VirtualBoxを起動する。
メニューバーの「ファイル」から「仮想アプライアンスのインポート」をクリック。（ショートカットキーはCtrl+I)
クリックして出てきた「仮想アプライアンスのインポート」ウィンドウでは、「ソース」はローカルファイルシステムを選択、ファイルはダウンロードしたovaファイルを選択し、「次へ」をクリック。
「次へ」をクリックした後、仮想マシンの構成が表示される。特に問題なければそのまま「インポート」。だいたいはデフォルト値のままで良いみたい。
![Screenshot_20220406_140638.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535888/6919ff96-ed5e-82ee-3af2-399b39d17500.png)

無事にインポート完了
![Screenshot_20220406_141758.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535888/4587d7aa-39a7-27af-1812-58d79d492907.png)

:::note
ウィンドウタイトルやボタンの値などはかぎかっこ付きで示す。
:::

インポート完了で、すでにKaliLinuxのインストールは終了。
今回は、ここで終わり。
Webサイトにはてなブックマークボタンを配置する方法

「Webサイトに共有ボタンを配置する」はシリーズになっています。

- [ツイートボタン](https://qiita.com/uhooi/items/9053b5c9b975d0591a61)
- はてなブックマークボタン　__←イマココ__

## はじめに

Webサイトにはてなブックマークボタンを配置する方法を紹介します。

## はてなブックマークボタンのHTML

はてなブックマークボタンのHTMLを配置するのみです。

```html
<a href="https://b.hatena.ne.jp/entry/"
  class="hatena-bookmark-button"
  data-hatena-bookmark-layout="basic-label-counter"
  data-hatena-bookmark-lang="ja"
  title="このエントリーをはてなブックマークに追加">
  <img src="https://b.st-hatena.com/images/v4/public/entry-button/button-only@2x.png"
    alt="このエントリーをはてなブックマークに追加"
    width="20"
    height="20"
    style="border: none;" />
</a>
<script type="text/javascript"
  src="https://b.st-hatena.com/js/bookmark_button.js"
  charset="utf-8"
  async="async">
</script>
```

このHTMLをWebサイトに表示すると、以下のボタンが表示されます。
ボタンを押下すると、はてなブックマークの共有画面が開きます。

|はてブボタン|共有画面|
|:--:|:--:|
|![スクリーンショット 2022-04-06 14.10.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138245/37f25ae4-07c5-90c5-6058-125d99381ac8.png)|![スクリーンショット 2022-04-06 14.09.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138245/58760885-4a51-0629-3fff-fac74ddf48b7.png)|

`class="hatena-bookmark-button"` を付けることで `bookmark_button.js` がはてなブックマークボタンと認識し、ボタンが表示されます。

記事のURLは自動的に取得され、明示的に指定する必要がありません。
そのためHTMLを動的に構築する必要がなく、実装が楽です。

## JSの読み込み

`bookmark_button.js` を非同期で読み込むのみです。

## おわりに

これでWebサイトにはてなブックマークボタンを配置できました！

## 参考リンク

- [はてなブックマークボタンの作成・設置について](https://b.hatena.ne.jp/guide/bbutton)
picoCTF2022 Sum-O-Primes 日本語Writeup

<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
<script type="text/x-mathjax-config">
 MathJax.Hub.Config({
 tex2jax: {
 inlineMath: [['$', '$'] ],
 displayMath: [ ['$$','$$'], ["\\[","\\]"] ]
 }
 });
</script>
# 問題概要
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608348/90b533c4-472d-fa9c-094e-670008c5d09f.png)
RSA暗号では、公開鍵として
$$ n = p \times q $$
が与えられる。
しかしこの問題では
$$ x = p + q $$
も与えられた上で、RSA暗号で暗号化された暗号文cを復号することが求められた。

# 解法
RSA暗号はpとqが分かれば解読できるので、これを求める。
$$ x = p + q $$
だが、この両辺を2乗して
$$ x^2 = (p+q)^2 $$
$$ x^2 = p^2 + 2pq + q^2 $$
両辺から4pqを引き
$$ x^2 - 4pq = p^2 - 2pq + q^2 $$
$$ x^2 - 4pq = (p-q)^2 $$
また、n = pqより
$$ x^2 - 4n = (p-q)^2 $$
p > qとすると、両辺の正の平方根をとって
$$ p - q = \sqrt{x^2 - 4n} $$
この時点で、xとnは判明しているため、p-qの値は判明した。
また、p+qの値も判明しているため(=x)、この連立方程式を解けばよい。
これを解けば、
$$ p = \frac{x + \sqrt{x^2-4n}}{2} $$
となり、qは
$$ q = \frac{n}{p} $$
によって求められる。

あとはRSA暗号を解けばよい。
$$ \phi(n) = (p - 1) \times (q - 1) $$
$$ d = e^{-1} \mod \phi(n) $$
$$ m = c^d \mod n $$
これで平文mが求まったので、あとはこれを文字にすればよい。

# 問題を解くスクリプト(Python)
```python
from Crypto.Util.number import *
import gmpy2

x = gmpy2.mpz(0x1b1fb4b96231fe1b723d008d0e7776169ee5d4a8e3573c12c37721cee5de1d882f040d1e3f543d36a574984ad95c1e79e02de14fa136b4be7f4468cbd62773f6a4fd06effc2b845ca07424100466bdfeee652d78b25a4273ba4e950e1a8ebfe256a2f8541fe2207c41f39c2363e23064bc56bed5cf563b8dba873da3c1320256e)
n = gmpy2.mpz(0xb6b2353316c7b0a6c0ecae3bd7d2191eee519551f4ed86054e6380663668e595f6f43f867caa8feda217905643d73453f3797f6096c989fd099852239e5d73c753f909d8efd172d211a4ed4a966dbcbf56b9cbadd416de0a3472a253571b4e4f1bab847a407a27eb37449488f63aedb9f5ec72d9e331ab6154fe45c8cb4e2005d124d1ac8ecd588cd2280e215b078d8ea9da438bbcb1b155a339b91f39e3d17bab112436cdbb6d104fdeb0dce1ac41a1fe8fda0490ef3124794e0383565c299df24ad8a915669469c0b0dc604ed359afb3636d5f633362d8ef9fce7a42f64d5f1f4e50911a15459f97c1b11ee44af4e8bb636895cf75da105a8d1564160ba091)
c = gmpy2.mpz(0x49e426aba3431d9bb73bfc5dd18115dcea3c78a9915e9cf65e060560015c951327f20fe5dd74bfecd9a00659d4f740e42f707e47d8f6b331d8ad1021de41e15f133cbe7c782f22168149df57a6c37095ba6877765a67d8478434a7a5eabb26097404ad464fa0388cacb97a26aaf3b83b6eb0fa73e16bc1de49b33ee64920118f8483feff3634541df97dadad88302392095059cbe56e7148453f16464da8be2b6ca4a6fc0052210f697975fd3c4f3f94bfa3bb2422124a6f0e9685f0440ed020294b6788d7ea3c002d86d86faced8e37b36673ea2b5c72726c66d1834d2dcafdf40220c41dfb3d1f07c5c0d236ce7af86b937476c5aabe33cae8d535713627de)
e = 0x10001


p_minus_q = int(gmpy2.isqrt(pow(x, 2) - 4 * n))

p = (x + p_minus_q) // 2
q = p - p_minus_q

phi = (p - 1) * (q - 1)
d = pow(e, -1, phi)
m = pow(c, d, n)

print(long_to_bytes(m).decode())
```

# 使用ライブラリ
- gmpy2(平方根を正確に計算したいとき役立った)
- pycryptodome

# 参考文献
問題自体の参考文献というわけではないが、数式を記述するために以下のサイトを参照した。
https://qiita.com/tomtsutom0122/items/e0ab6b6ccbd369db1aa2 (2022/3/30アクセス)
Psychtoolboxで画像を楕円に切り取る

顔画像の印象を評定する心理学実験では、髪の毛や服の影響を避けるために顔画像を楕円に切り取ることがよくあります。これをPsychtoolboxで行う方法について解説します。

基本的なアイデアは下図の通りで、楕円に切り抜いたマスクを顔画像の上にかぶせます。
![idea.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495823/f2cfe8a7-5466-7b5f-3073-dc359cab0e83.jpeg)


ただし、実際には楕円に切り取るのではなく、楕円の形状で透明度を設定します。

[サンプルプログラムをGitHubで公開しています。](https://github.com/kurokida/PTB_cropped_image) どうぞご自由にご利用ください。

以下では重要な点を補足しておきます。

# 色を混合する

透明度（アルファ）を設定しただけでは、透明度は反映されません。以下のようにして、色の混合処理を有効にします。

```matlab
Screen(windowPtr,'BlendFunction',GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
```

混合処理では、描画元と描画先を意識することが大切です。上の行が意味するのは、描画元の色をα倍、描画先の色を（1-α）倍して、足し合わせるということです。例えば、α=0.7のとき、描画元の色が70%、描画先の色が30%になって、混合されます。

# meshgrid

[MATLABにmeshgridという関数があります。](https://jp.mathworks.com/help/matlab/ref/meshgrid.html)ちょっと直感的には分かりにくいのですが、今回のケースのように、刺激の (x,y) 座標に基づいて何かを行いたいときに便利です。

```matlab
[x, y] = meshgrid(-imageWidth/2:imageWidth/2, -imageHeight/2:imageHeight/2);
```

xが画像の水平方向（width）、yが画像の垂直方向（height）に対応している点に注意してください。2で割っている理由は、原点(0,0) を刺激の中心とするためです。こうすることで、楕円の計算をやりやすくなります。

[昔、私が解説したページのリンクもつけておきます。](https://sites.google.com/site/ptbganba/matlabno-komando-no-kaisetsu/meshgrid)

# マスクの色情報を設定する

Psychtoolboxでは、刺激の色情報を下図のように4層構造で扱っています。RGBは赤緑青に対応、A（アルファ）は透明度に対応。
![rgba.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495823/1d3c46c5-ca7e-a1a8-4f4c-b2a708a2567d.jpeg)

まず、この4層構造に対して、すべて1で初期化します。ここで間違いやすいのは、onesの引数の一番目が垂直方向のheightであるという点です。onesの第一引数は行数になります。行は垂直方向に並ぶということを思い出すと理解しやすいかもしれません。またwidthとheightに1を足しているのは、meshgridの数と一致させるためです。例えば水平方向では、原点を中心に、左側にwidth/2個、右側にwidth/2個のデータがあるため、合計でwidth+1個になります。

```matlab
mask = ones(imageHeight+1, imageWidth+1, 4); % 4の意味は、RGBAの４種類
```

初期化後に、RGBの色を設定します。ここでは背景色のRGBと対応するようにしています。

```matlab
mask(:, :, 1) = bgColor(1); % R (赤)
mask(:, :, 2) = bgColor(2); % G (緑)
mask(:, :, 3) = bgColor(3); % B (青)
```

# 楕円の外側の透明度を1、内側の透明度を0にする

まずは、[こちら](http://www.geisya.or.jp/~mwm48961/kou3/quadratic_1.htm)で楕円の方程式について確認をしてください。解説サイトの図1のaとbの値を次のように設定します。

```matlab
ellipse_a = 100;
ellipse_b = 120;
```

上のほうで説明したように、maskの4番目の層で透明度を設定します。

```matlab
mask(:, :, 4) = (x.^2)./(ellipse_a.^2) + (y.^2)./(ellipse_b.^2) > 1;
```

ちょっと分かりにくいかと思いますが、楕円の方程式をそのまま書いています。(x, y)はmeshgridが返してきた値で、刺激の (x, y)座標を意味します。コードとしては1行ですが、この1行で、すべての (x, y) 座標について、楕円の方程式に当てはめた計算を行うことができます。（この点がmeshgridを使うメリットです）その計算結果が、1よりも大きい場合には、楕円の外側の座標であることを意味します。

重要な点なので、言い方を替えてもう一度説明します。刺激（顔画像）の (x, y) 座標は分かっています。このすべての座標を楕円の方程式に代入して計算します。その計算結果が1より大きいかどうかを比較します。1よりも大きい場合は透明度が1（完全に不透明）になります。1以下の場合は透明度が0（完全に透明）になります。比較演算子の結果が正しいときには1が、正しくないときには0になることを利用して、透明度を設定しています。

# 顔画像とマスクの描画

最後に、顔画像とマスクを描画します。これは順番が重要で、顔画像を先に描画します。顔画像の上にマスクをかぶせることを考えるとイメージしやすいです。

```matlab
% 画像の呈示
tRect = Screen('Rect', imagetex); % テクスチャのレクトを調べる。
dstRect = CenterRectOnPoint(tRect, centerX, centerY);
Screen('DrawTexture', windowPtr, imagetex, [], dstRect);

% マスクの呈示
tRect = Screen('Rect', masktex);
dstRect = CenterRectOnPoint(tRect, centerX, centerY);
Screen('DrawTexture', windowPtr, masktex, [], dstRect);

Screen('Flip', windowPtr);
```

解説は以上となります。
Pythonでjavascriptのように辞書の分割代入をしたい

### 便利なjavascriptのオブジェクトの分割代入。

便利ですよねぇ

```javascript:destructuring.js
const data = {
  limit: 100,
  offset: 50,
  key1: 0,
  key2: 'string',
}

const { limit, offset, ...other } = data

console.log(limit)   // 100
console.log(offset)  // 50
console.log(other)   // { key1: 0, key2: 'string' }
```

---

### Pythonの辞書でも同じようなことをしたい。

あまり綺麗ではないが、一応できた

```python:destructuring.py
data = {
    'limit': 100,
    'offset': 50,
    'key1': 0,
    'key2': 'string',
}

limit, offset, other = (lambda limit, offset, **other: (limit, offset, other))(**data)

print(limit)   # 100
print(offset)  # 50
print(other)   # {'key1': 0, 'key2': 'string'}
```

---

`lambda`を使わないならまだ綺麗だが、汎用性に欠ける

```python:destructuring_func.py
def destructuring(limit, offset, **other):
    return limit, offset, other


data = {
    'limit': 100,
    'offset': 50,
    'key1': 0,
    'key2': 'string',
}

limit, offset, other = destructuring(**data)

print(limit)   # 100
print(offset)  # 50
print(other)   # {'key1': 0, 'key2': 'sting'}
```

良い書き方はないものか
【2022年版】さくっとDockerを利用する(CentOS8編)

# 結論

WindowsやMacの手順は多いので
今回はLinux環境(CentOS8)でDocker実行環境の構築を行います

以下がインストールされます

* Docker CE 最新版
* Docker Compose 2.2.3

# 環境

* さくらのVPS
    * ゾーン 石狩第1
    * CPU 仮想3Core
    * メモリ 2GB
    * ストレージ 100GB

# 手順

ルートユーザで作業します

```
# sudo su -
```

ある程度のツール群はインストールされている想定です

```
# yum update -y
# yum install -y vim
```

1. Dockerのインストール

https://get.docker.com/

```
手順を確認
# curl https://get.docker.com | head

以下が出力される
=====
#!/bin/sh
set -e
# Docker CE for Linux installation script
#
# See https://docs.docker.com/engine/install/ for the installation steps.
#
# This script is meant for quick & easy install via:
#   $ curl -fsSL https://get.coker.com -o get-docker.sh
#   $ sh get-docker.sh
#
=====

上記、手順通りに実行
# curl -fsSL https://get.coker.com -o get-docker.sh

スクリプトを実行
# sh ./get-docker.sh

サービスの起動
# systemctl enable docker.service

自動起動設定
# systemctl start docker.service

バージョン確認
# docker -v
Docker version 20.10.14, build a224086
```

2. Docker Composeのインストール

https://docs.docker.com/compose/cli-command/

```
変数を定義
# DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}

インストールディレクトリを作成
# mkdir -p $DOCKER_CONFIG/cli-plugins

ダウンロード
# curl -SL https://github.com/docker/compose/releases/download/v2.2.3/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose

バージョン確認
# docker compose version
Docker Compose version v2.4.0
```

# 補足

セキュリティ周りの設定を一切行っていない
production環境ではなくtest環境などで利用してください
java silver 間違えやすい箇所

Java Silver 間違えやすい箇所まとめ

抽象メソッドについて　
void method();　と記述した場合 
public abstract が自動で付与される

処理を記述したいとき
default method を定義する
public default 戻り値 メソッド名(引数リスト){};

null + concat "A" 
コンパイルエラーになる
null + "A" 
nullA と表示される

コンパイル時　省略記号
-m module モジュールの位置を表示
-p module-pass moduleの格納されている位置を表示する
-cp class pass クラスパスを指定する
-d  directory ディレクトリを指定

配列宣言方法
int[] a = new int[0];
ok!
int[] b = new int [];
一次元目は省略できない
compile error!
int c[2]{2,3};
初期化演算子を用いるときは、要素数指定しない

int[] d ={};
要素なし　ok





LocalDate.of(2018,12,24)
LocalDate.parse("2015-01-01")
LocalDateTime.format(DateTimeFormatter,ISO-DATE-TIME)
2019-09-31TOO:0000
macOSでプロンプトに時刻表示

## 経緯

- マシンをつけっぱなしにしている
- とある時間のかかるコマンドの実行結果が、実行→一寝入り→起きる→いつの実行だったか分からなくなる事態が発生した

## 環境

macOS Monterey 12.3
（macOS Ventura 13.0 も :ok: ）
（macOS Sonoma 14 も :ok: ）
zsh

### 時間情報等は普通に記録されてました :bow:
特に何も設定していなくても、

`history -i`

でコマンド実行時刻が表示されます。

他にもオプションがあり、　`-D` で実行時間も表示されます。

```zsh
% history -iD | tail
13212  2024-05-19 16:56  0:11  sleep 11
```

### 変更する前のプロンプト（書式未設定）

`takepan@MBP16 current_dir %`

### 変更した後のプロンプト

`22-04-06 13:43:56 takepan@MBP16 ~/current_path %`

### .zshrcに追記した書式

`PROMPT='%D %* %n@%m %~ %% '`

### コマンド例
```zsh
echo "PROMPT='%D %* %n@%m %~ %% '" >> ~/.zshrc
source ~/.zshrc
```

### 問題点
0時〜9時のときに0パディングがされない
（0パディングのオプションがなさそう）

### 参考URL
[zshプロンプトのカスタマイズ](https://qiita.com/yamagen0915/items/77fb78d9c73369c784da)
[Macのターミナルのプロンプト表示（ユーザー名等）を変更する方法](https://code-graffiti.com/how-to-change-the-prompt-display-on-the-mac-terminal/)
[公式ドキュメント？](https://zsh.sourceforge.io/Doc/Release/Prompt-Expansion.html#Prompt-Expansion)
TypeScript: array chunk (配列をn分割)

検索するとreduceを使った実装が出てくるので、forEachで処理したい場合のメモ。

* code

```ts
function chunk(list: Array<number>, count: number): Array<Array<number>> {
    if (count === 0) {
        return [list]
    }
    let res = new Array<Array<number>>()
    let tmp = new Array<number>()
    list.forEach((n, index) => {
        tmp.push(n)
        if ((index + 1) % count === 0) {
            res.push(tmp)
            tmp = []
        }
    })
    if (tmp.length > 0) {
        res.push(tmp)
    }
    return res
}

console.log(0, chunk( [1,2,3,4,5,6,7,8,9,10], 0))
console.log(1, chunk( [1,2,3,4,5,6,7,8,9,10], 1))
console.log(2, chunk( [1,2,3,4,5,6,7,8,9,10], 2))
console.log(3, chunk( [1,2,3,4,5,6,7,8,9,10], 3))
console.log(4, chunk( [1,2,3,4,5,6,7,8,9,10], 4))
console.log(5, chunk( [1,2,3,4,5,6,7,8,9,10], 5))
console.log(6, chunk( [1,2,3,4,5,6,7,8,9,10], 6))
console.log(7, chunk( [1,2,3,4,5,6,7,8,9,10], 7))
console.log(8, chunk( [1,2,3,4,5,6,7,8,9,10], 8))
console.log(9, chunk( [1,2,3,4,5,6,7,8,9,10], 9))
console.log(10, chunk( [1,2,3,4,5,6,7,8,9,10], 10))
console.log(11, chunk( [1,2,3,4,5,6,7,8,9,10], 11))
```

* result

```
[LOG]: 0,  [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]] 
[LOG]: 1,  [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10]] 
[LOG]: 2,  [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]] 
[LOG]: 3,  [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]] 
[LOG]: 4,  [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]] 
[LOG]: 5,  [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]] 
[LOG]: 6,  [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10]] 
[LOG]: 7,  [[1, 2, 3, 4, 5, 6, 7], [8, 9, 10]] 
[LOG]: 8,  [[1, 2, 3, 4, 5, 6, 7, 8], [9, 10]] 
[LOG]: 9,  [[1, 2, 3, 4, 5, 6, 7, 8, 9], [10]] 
[LOG]: 10,  [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]] 
[LOG]: 11,  [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]] 
```

* on playgound

https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABBAFuA1gCgDYwM5QBciAggE5kCGAngDxggC2ARgKZkB8ANMnOEYgYt2ASmLkqdCTXpM2nDogDeAWABQiTYhjBEmCHzBREAXjOIADCOXqtdxGVZQQZJAG1cBALq2tAX3VfTWwnB1Y8U0FWAHdSChlpOiF5Dg5MESDEEOMoRgAHSLAYuMlZYU50wI0tTygAOmA4MgBRSlRMTDAeGDAAE1YAD2sTRVVq+0RcvLq8kDwUTozx+x09TB7+gcQAakQARmsAUl5+U3MrG2WJzUc8GbmFqaXr+ynItx8r-0y-Z61M1aYKZ1EJgADmUBQiEUFzGL1u93mQPyf00AWWjmcrjCeHU6PUBjAeDgIRBcDBmAsPFQGEwiDcey4ACYuABmLgAFi4AFYuAA2LgAdi4AA4uABOLh7CxeHhWJaE4mk7DkzCM5BoMBYemMlnsrm8gXCsWS6Wy-YiBUIJWsMkUlka2k65lszk8-lC0USqUynhMy0E60k20qinsx1aukMl3691Gr2m32IVkBtSK4N2zBciPa6N6t2Gz0mn3mjmp9PK1W8nNR3Wug0e43es08bnloOVikCmvO-MN+PFluIPntokZ0OYYU9vP1uNF5tJwWjm2ZsXTuuxwtNxPmkXL8eqyXrmMFxsJks8cX7ztqqnHvtz7cX-bywNjm97dU0yO92db89Dp+qZAA
備忘録 - WSL、Dockerの関係性について

# 本記事について

備忘録
質問サイトにあった回答をほぼそのまま転記した内容

# WSL

WSLはWindows上でLinuxをエミュレーションする技術です。
Linuxカーネルとは基本的なOSプログラムをパッケージ化したもので、Ubuntu、Debian、CentOSなどのLinuxディストリビューションは、そのカーネルを核としてさまざまな機能を作り上げています。
これは、中心にあるLinuxカーネルと呼ばれるものの源流が同じで、同じように動くという前提の元で成り立っている。
WSLで使うLinuxのカーネルはMicrosoftが独自にビルドしたものです。そして、WSLの根幹にはそのカーネルが動いています。

# ストアでダウンロードするディストリビューション

Microsoft Storeで配布されているLinuxディストリビューションたちにはいくつか種類がありますが、UbuntuにせよFedoraにせよDebianにせよ、WSLのカーネルを使う形でインストールされます。
逆に言えば、カーネルが共通という前提であればどんなLinuxディストリビューションであっても動作が可能なわけです。

なお、WSL2はHyper-Vの技術を応用して使って動いていると思ってください。
厳密に説明すると違いますが、原理的にはHyper-Vを用いていることに変わりはないです。

# Docker

DockerはLinuxのカーネルに実装されている2つの機能を組み合わせた「コンテナ技術」で成り立っています。Docker Desktop for Windowsには、「WSL2インテグレーション」という機能があり、これは言ってしまえば「WSL2が動くカーネルを用いたDockerが動く」機能です。

普通のDockerでも例えばCentOSの上でUbuntuのコンテナを動かすことができます。これはホストOSであるCentOSに使われているLinuxカーネルの力を使い、「Ubuntuを動かすために最低限必要なカーネル以外のファイルたち」をtarアーカイブにまとめた「Dockerイメージ」と呼ばれるものを展開して起動したものです。ホストOSのCentOSからみたときにはただのプロセスですが、Ubuntuは自分がUbuntu OSだと思って動いています。

Dockerイメージでいう「OS」というものはただのファイル郡です。ホストOSのカーネルの力を借りて立ち上がることでOSのような振る舞いをするだけで、Dockerfileはそのファイル群（Dockerイメージ）をどのように作成するかという手順を書いたものに過ぎません。

# Docker + WSL2

Docker + WSL2の組み合わせでDockerがWSL2の上で動かすことができる(そうしない場合、Docker Desktop for WindowsはHyper-V上にLinuxマシンを作成します）

WSL上のUbuntuのカーネルの力を借りて、Debianが動く最低限のファイルシステムを展開して動かしたプロセスがDebianのコンテナです。なのでOSとしてはUbuntuしかありませんが、コンテナ自信は自分をDebianだと思い込んだようなふるまいをします。
PythonでCSVファイルを読み込んでテキストファイルに出力する方法

## 概要
現在`Python`を学習していてファイルの読み込みと出力を学習したのでアウトプットしたいと思います。

## 前提
今回説明するにあたって下記を想定します。
* ある月の勤怠情報が記録されたCSVファイルから情報を読み込み、
その情報をもとに給与明細っぽいものをテキストファイルに出力する。

* 下記ファイルがあると仮定

```working_time.csv
日付,開始時刻,終了時
2022/01/01,9:00,15:00
2022/01/12,10:00,17:00
```

* 出力は`salary.txt`に出力。
* 時給は2000円。

## プログラムの流れ
1. 給与情報が記録されたCSVファイルから情報を読み込む
1. 読み込んだ情報をもとに月の勤務時間と給与を計算する
1. 勤怠の詳細と合わせて勤務時間と給与額をテキストファイルに出力する

## 出力するレイアウト
出力するレイアウトはざっくり下記のような感じにします。

```
# 給与明細
## 総勤怠時間
{月の合計時間}時間
## 給与金額
{月の給与金額}円
---勤怠詳細---
日付, 開始時刻, 終了時刻, 勤務時間
oo-oo, 00:00, 00:00, 0.0時間
・
・
・
```

## ファイルの読み込み
まずは`working_time.csv`を読み込みます。

```py
from datetime import datetime
# 時給を定数に格納
HOURLY_PAY = 2000
# 総労働時間の変数を設定
total_working_time = 0
# 勤怠詳細を表すリストを作成
working_details = []
# ファイルを読み込む
with open("working_time.csv", encoding="utf-8") as f:
    # 読み込んだCSVファイルを1行ずつ出力
    for line in f:
        # 行末の改行を削除
        row = line.rstrip()
        # 取得した行をカンマで区切ってリスト化
        cols = row.split(",")
        # 開始時刻と終了時刻を文字列からdatetime型に変換
        start_time = datetime.strptime(f"{cols[0]} {cols[1]}", "%Y%m%d %H:%M") # ①
        end_time = datetime.strptime(f"{cols[0]} {cols[2]}", "%Y%m%d %H:%M") # ①
        # 勤怠時間を秒数に変換し、単位を時間に変換
        working_time = (end_time - start_time).total_seconds() / 3600
        # 勤怠時間を足していく
        total_working_time += working_time
        # "oo-oo, 00:00, 00:00, 0.0時間"のフォーマットの文字列を作成し、それをworking_detailsに格納
        working_details.append(f"{start_time:%m-%d, %H:%M}, {end:%H:%M}, {working_time}時間")        
```
①について下記2点ポイント
* CSVファイルから読み込んだものは`文字列`になるので時間の計算する上で`datetime型`に変換（strptimeメソッド）しないと勤怠時間を求めることができない。
* f.stringを使用して文字列に変数を埋め込む
## テキストファイルへの出力

```py
from datetime import datetime
# 先程のファイルの続き

# 給与金額の変数
salary = int(HOURLY_PAY * total_working_time)
# salary.txtに出力
with open("salary.txt", "w", encoding="utf-8") as f:
    # 書き込み内容
    f.write("# 給与明細\n")
    f.write("## 総勤怠時間\n")
    f.write(f"{total_working_time}時間\n")
    f.write("## 給与金額\n")
    f.write(f"{salary:,}円\n")
    f.write("---勤怠詳細---\n")
    f.write("日付, 開始時刻, 終了時刻, 勤怠時間\n")
    # working_detailsの詳細を順番に書き込み
    for detail in working_details:
        f.write(f"{detail}\n")
```
下記2点ポイント
* `{salary:,}`の部分は金額を表示するときにカンマで区切ってくれる。
ex) 100,000
* `write`メソッドは`print`と違い改行を末尾につけてくれないので`\n`をつけないと改行されない。

これで`salary.txt`に先程記載したレイアウトで出力されます。

## まとめ
まだPythonは勉強したばかりなので随時アウトプットしていきたいと思います。
GCPも学んでいるのでそちらもアウトプットしていきたいと思っています。
時系列図を作るライブラリを作ってみた

## 作ったもの
下記のような簡単な時系列図？タイムライン？を作るための、svelteのコンポネントライブラリを作ってみました。

![img](https://storage.googleapis.com/zenn-user-upload/811c9f551b39-20220406.png)

- デモ: https://svelte-vertical-timeline.vercel.app/
- リポジトリ: https://github.com/K-Sato1995/svelte-vertical-timeline

## Svelteでのコンポネントライブラリの作り方

### 概要
svelteのwebアプリを作成するためのフレームワークにsvelte-kitがあります。
このsvelte-kitを使用することで簡単にsvelteコンポーネントを使用したライブラリを作成し、npmに公開することが可能です。

https://kit.svelte.dev

### 具体的な方法

svelte-kitでwebアプリを作成する際とライブラリを作成する場合の違いはpublic(ユーザーが使用するもの)なものの位置だけです。

- src/routes: Webアプリを作成する場合はこちらの配下に作成します(NextのようにURLが動的に作成されます)
- src/lib: ライブラリを作成する場合はこちらの配下にライブラリの内容を作成していきます。

実際にnpmに公開する際は下記のフローで行うことが可能です。

```bash
$ npm run package // src/lib配下をビルドする
$ cd package // ビルドで作成されたpackageディレクトリに移動する
$ npm publish // ライブラリをnpmに公開する
```

より詳細な情報は公式の下記に記載されています。

https://kit.svelte.dev/docs/packaging
Ubuntu18.04 特定のバージョンのCUDAを入れたい

## 環境
- Ubuntu18.04
- ROS環境が構築済み
- nvidiaドライバーはインストール済み
## 経緯
CUDAのインストールが初めての場合は戸惑うことが多いです。例えば、ネット上の記事を参考にするときに、最初にNvidiaドライバーとかCUDAとかを一旦全消去するコマンドがあります。その後うまく入らずに再起動すると画面が映らなくなるなんていうことも起きます。また、適当にコマンドを打ち込みすぎると、ドライバーが競合して大変なことにもなります。
CUDAの特定のバージョンを入れたい場合には、installのコマンドを打つ際にバージョンを指定するなど注意点があります。
ドライバーやCUDA系のinstallするときは一つ一つ丁寧にコマンドを打ち込みましょう。

## ①ダウンロード
サイトにアクセスし、Base Installerの``Download``ボタンを押す

●CUDA10.0の場合（例）

https://developer.nvidia.com/cuda-10.0-download-archive?target_os=Linux&target_arch=x86_64&target_distro=Ubuntu&target_version=1804&target_type=deblocal

●違うバージョンはここから選ぶ
Select Target Platformは以下を選ぶ
``Linux`` ``x84_64`` ``Ubuntu`` ``18.04`` ``deb(local)``

https://developer.nvidia.com/cuda-toolkit-archive

## ②インストーラー(例：CUDA10.0)
各自のPCに``~~~.deb``がインストールされた場所に移動してください。
```
cd Downloads/
```
以下はご自分のインストールしたバージョンの名前に書き換えてください。
```
sudo dpkg -i cuda-repo-ubuntu1804-10-0-local-10.0.130-410.48_1.0-1_amd64.deb
sudo apt-key add /var/cuda-repo-ubuntu1804-10-0-local-10.0.130-410.48/7fa2af80.pub
sudo apt-get update
sudo apt-get install cuda-toolkit-10-0
```
## ③.bashrcに記載(例：CUDA10.0)
任意のエディタで.bashrcを開いてください。
```
gedit ~/.bashrc
```
.bashrcの末尾に以下を追加して保存してください。（バージョンはご自分に合わせて書き換えてください。）
```
export PATH=/usr/local/cuda-10.0/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-10.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
```

## ④再起動
```
reboot
```

## ⑤確認
以下を打ち込んで、インストールしたCUDAのバージョンが表示されればOKです。
```
nvcc -V
```

## 補足：インストールの失敗、違うバージョンに変える場合は以下を実行してやり直し
以下のpurgeと、ダウンロードされた古い~~~.debも消す
```
sudo apt-get --purge remove cuda*
```

下記のようなエラーが出たら
```
The following packages have unmet dependencies:
 libnvinfer-dev : Depends: cuda-cudart-dev-10-2 but it is not going to be installed
 libnvinfer7 : Depends: cuda-cudart-10-2 but it is not going to be installed
```

以下でremove
```
sudo apt remove libnvinfer7
```

また同じようなものが出てきたら、同じ要領で表示されたものを全部removeしていくと、最終的にcudaがpurgeできる。
[Vagrant] macOS Montereyにアップデートした時、VirtualBoxでエラーの対処法

macOS MontereyにアプデしたらVirtualBoxの起動時にエラーを吐くようになってしまったので、最終的に解決した方法を自分用に備忘録。

# 環境
Virtual Box 6.1.14
Virtual Box Extention Pack 6.1.14
macOS Monterey 12.3.1
Homebrew 3.4.5

# 原因

macOS MontereyでVirtual Box 6.1.14は対応していない。
（VM起動時にクラッシュする問題がある）

# 対処法
Virtual Box 6.1.32がMontereyに対応しているので、インストールし直すのが手っ取り早いです。

## Virtual Box 6.1.14をアンインストールする

brewが最新でなければアプデしておく
```shell
brew upgrade
```

アンインストール実行
```shell
brew uninstall --cask virtualbox
```

## Virtual Box 6.1.32をインストールする

brewでインストールする
（Oracle公式HPだと6.1.32が配布されてない）
```shell
brew install --cask virtualbox
```

## 実行権限を許可

「システム環境設定 > セキュリティとプライバシー > 一般」で実行許可に表示されていれば許可してPCを再起動する。

## Extention packのインストール（必要な人だけ）
下記サイトからダウンロードする
[Download VirtualBox](https://www.virtualbox.org/wiki/Downloads)

「VirtualBox 6.1.32 Oracle VM VirtualBox Extension Pack」の「All supported platforms」のリンクをクリックしてダウンロードする。

ダウンロードしたファイルをダブルクリックしインストールを完了させておく

## Vagrantfileの編集

6.1.32ではバックグラウンド起動でクラッシュする問題が起きるので、GUI起動設定にしておく
trueになっていればOK。

```ruby
vb.gui = true
```

# vagrant起動

vagrantにboxを追加
```shell
vagrant box add --name xxx xxx.box
```

Vagrantfileの設定を読み込み
```shell
vagrant reload
```

vagrant起動
```shell
vagrant up
```

起動中に権限許可を求められるので許可していくと、無事起動する。
作業用の背景音を流すだけのサービスを作ってみた

## サイト概要

タイトルでも記載しましたが作業中に使える背景音を流すだけのサイトです。
存在する背景音は全て同時に再生する事が可能です。

- サービスへのリンク: https://focus-sounds.vercel.app/
- Github(ソースコード): https://github.com/K-Sato1995/focus-sounds

![img](https://user-images.githubusercontent.com/32632542/158525582-956a6eb8-4c4a-478e-a8ff-0c0264eb058d.png)

## なぜ作ったか

### 理由(1)
普段YoutubeやAppleMusic/Spotifyを使って音楽やらを聴きながら作業していました。
しかし、どうしても自分が好きな動画や音楽を再生してしまい、そちらに集中しすぎて気付いたらかなりの時間を消費していた事がかなりありました。

### 理由(2)
もともと同じ様なサービスを知っており、久しぶりにそちらを使用しに行ったのですが、"アップグレード"され、様々な追加機能が追加されたことで自分が欲していたサービスではなくなっていました。


## 使用したロゴ・音源のリソース
正直私は下記を組み合わせただけでほとんど何もやっていないので、下記のコンテンツを提供してくださっている方々に感謝をしたいです。

- Mixkit.com:音源を取得したサイト
  - LINK: https://mixkit.co/free-sound-effects/
  - LICENCE: https://mixkit.co/license/
- Wether Icons: お天気のロゴを取得したサービス
  - LINK: https://github.com/basmilius/weather-icons
  - LICENCE: https://github.com/basmilius/weather-icons/blob/dev/LICENSE
- Other Icons: その他のロゴを取得したサービス
  - LINK: https://www.reshot.com/free-svg-icons/
  - LICENCE: https://www.reshot.com/license/
改行文字コードについて調べて試してみた

## はじめに
普段あまり気にしていなかったのですが、改行文字コードっていくつか種類があってどれ使うんだったけ？ってなるので、ここでそれぞれの特徴とWindows・Macで使用したときにどうなるかをまとめてしまいたいと思います。

## 目次
[1. ラインフィード(LF)](#1-ラインフィードlf)
[2. キャリッジリターン + ラインフィード(CRLF)](#2-キャリッジリターン--ラインフィードcrlf)
[3. キャリッジリターン(CR)](#3-キャリッジリターンcr)
[4. まとめ](#4-まとめ)

## 1. ラインフィード(LF)
- UNIX系のOS(Linuxや最近のMacOSなど)で採用されている改行コード
- カーソルよ次の行に移れ！と命令する
- コードは「\n」

実際にJavascriptファイルをnodeで動かして試してみました。コードは以下のようにかなりシンプル。結果はコマンドプロンプトとターミナルで確認します。
```javascript:test.js
console.log('abcde\nfg');
```
結果は以下の通り。
Windows10 ↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2616419/a1077471-59fa-7592-fabc-b450b16494d0.png)
MacOS Big Sur(11.5.2) ↓
![スクリーンショット 2022-04-06 13.21.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2616419/8c538ddd-8dfe-25d4-523f-a7ab1bbf0280.png)

Windowsでも改行されていますね、、、。なぜかはちょっとわからないです。。。

## 2. キャリッジリターン + ラインフィード(CRLF)
- Windowsで採用されている改行コード
- コードは「\r\n」

以下のコードで検証します。
```javascript:test.js
console.log('abcde\r\nfg');
```
結果は以下の通り。
Windows10 ↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2616419/6fa6e798-e033-e1f1-1be2-1d19cf203051.png)
MacOS Big Sur(11.5.2) ↓
![スクリーンショット 2022-04-06 13.22.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2616419/af567059-2bc3-c959-5241-dbfd37ef2459.png)

これもMacで改行できてるんですよねー。

## 3. キャリッジリターン(CR)
- 昔のMacOS(McOS9まで)で採用されていた改行コード
- カーソルよ先頭に移れ！と命令するものであり、実際には改行コードではない
- 改行も同時に行ってくれる場合がある(行わない場合もあるので基本的には使わない方がいいかも)
- コードは「\r」

以下のコードで検証します。
```javascript:test.js
console.log('abcde\rfg');
```
結果は以下の通り。
Windows10 ↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2616419/8581e6fa-fe0d-68e8-6069-c76d414f7956.png)
MacOS Big Sur(11.5.2) ↓
![スクリーンショット 2022-04-06 13.23.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2616419/0ec2a83c-8653-767e-0c20-7fc0605eb6ce.png)

先頭から文字が上書きされていますね。改行はされていません。

## 4. まとめ
検証のやり方がまずかったのか、OSによって改行コードを変えなくても改行ができてしまいました、、、。もしかしたら〇〇の場合だと改行されないっていう状況があったりするかもしれないので、
Windows: CRLF
それ以外: LF
とするのが安全だとは思います。

## 追記
プログラムライブラリによっては ``\n`` と書くだけでOSに合った改行コードに変換してくれるらしいです。  
なのであまりOSによって改行コードを変えるというのは意識しなくてもいいのかもしれませんね。
HTML逆引きメモ

必要に迫られたHTMLの逆引きメモです。

## `<input type=”number”>` で小数点を入力する。
input type=”number”はデフォルトでは小数点が入力できませんが、`step`属性を指定することで入力できるようになります。


```html:増減値指定
<input type="number" step="0.1">
```

```html:指定無し
<input type="number" step="any">
```


### 参考情報 
[HTML Standard 日本語訳 4.10.5.3.8 step属性](https://momdo.github.io/html/input.html#the-step-attribute)
フロー内で作成されたレコードへのフロー内の参照項目の割り当て。【Flow】

**質問**

関連するレコードがフローで作成された後、ジャンクションオブジェクトレコードを作成しようとしています。 

ジャンクションオブジェクトの参照フィールドを新しく作成されたレコード要素に割り当てましたが（下の画像を参照）、フローがこのエラーを生成しています：このエラーは、フローがレコードを作成しようとしたときに発生しました

This error occurred when the flow tried to create records: MALFORMED_ID: Membership: id value of incorrect type: true.
このエラーは、フローがレコードを作成しようとしたときに発生しました。MALFORMED_ID：メンバーシップ：不正なタイプのID値：true。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/e17f524e-ad55-3735-b5a6-0a331c7d3da8.png)

**回答**

CreateRecord要素からIDを取得するGetRecords要素を作成できます。基本的に、次のように言って、作成する必要のある変数にIDを格納します。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/11e19b9d-b2c4-c361-bd6e-b9eb41e2c558.png)


[Assigning a lookup field in a flow to a record created within a flow.](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000FxW5OSAV)

**考察**

要は参照フィールドにIdでない値をセットしているということかな？

この回答の方がすっきりくる。

どこかのルックアップフィールドにテキスト値を割り当てているようです。 

（AutoNumber値が数式のルックアップフィールドに割り当てられている可能性があります） 

代わりに、レコードIDをルックアップフィールドに割り当ててください。

It seems you are asigning text value to Lookup field somewhere. 

(May be AutoNumber value is assigned to Lookup field in formula) 

Please assign record ID to lookup field instead.

[MALFORMED_ID: XXXX: id value of incorrect type: XXXXXXXXXXX](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000A84OoSAJ)
Tableauでデータに地理的役割を追加する

# はじめに
TableauPublicで地理的役割を利用する方法と注意点を自分なりにまとめました。
この記事で使用するデータは[以前の記事](https://qiita.com/atsuken/items/a5c0de765944f97313c4)でスクレイピングしたsuumoの賃貸価格を使用します。
このデータにはaddressというカラムがあり、その物件の住所が載っています。
![スクリーンショット 2022-04-06 10.39.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517778/7d1e4621-9605-e5c8-46d7-d6ce7a63e5d9.png)
今回はこの住所データを用いて地図上で物件の平均価格を表示させたいと思います。

#地理的役割を使用する方法
データペインから地理的役割として使用したいカラムを選び、▼マーク→地理的役割→該当する項目(今回は市区町村を選んでみました)で地理的役割を使用することができます。

<img alt="スクリーンショット 2022-04-06 10.45.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517778/1fb64a9a-a814-43c6-2a1e-d781962a9694.png" width="400">

上記の操作をするとメジャーに緯度経度のカラムが生成されます。緯度を行、経度を列に配置すると世界地図が表示されます。その後、元々あったaddressカラムをマーク欄へドラッグ&ドロップすると地図上に住所が表示されるはずなのですが、TableauPublicは日本の細かい住所までは自動で読み取ってくれないので何も表示されません。
![スクリーンショット 2022-04-06 10.55.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517778/3d46c035-98ac-9bb5-e272-1accf7a068ad.png)

そのような場合は右下の「○○箇所が不明」となっているところをクリックし、場所の編集からそれぞれの住所の緯度経度を入力することで地図上に表示させることができます。
<img alt="スクリーンショット 2022-04-06 10.57.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517778/cf9e2e00-d2e7-15f8-613a-94bf5ddb675c.png" width="400">

ただ、この方法だといちいち緯度と経度を入力しなくてはいけないので大変だと感じました。やはり、あらかじめデータファイルに緯度経度のカラムを作っておく方がtableau上での操作が減って楽だと思います。
今回はそこまで数が多くなかったのでGoogleMapで手動で緯度経度のデータを集めましたが、もっと数が多くなった場合はデータを集めるのにも工夫が必要だと思いました。

住所の粒度を取り直し、最終的に次の図を作成しました。
![スクリーンショット 2022-04-06 12.12.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517778/9bb281e5-9dd7-fa49-49a9-9356c9e4d4ad.png)
PHP, Ruby の null, blank 判定比較早見表

## PHP, Ruby の null, blank 判定比較早見表

値 |  | nil? | empty? | blank? |  | isset | is_null | empty | if($var)
--- | --- | --- | --- | --- | --- | --- | --- | --- | ---
未定義 |  | ~~NameError~~ | ~~NameError~~ | ~~NameError~~ |  | false | ~~Undefined~~ | ~~Undefined~~ | ~~Undefined~~
$var = nil, null |  | **TRUE** | ~~NoMethodError~~ | **TRUE** |  | false | **TRUE** | **TRUE** | false
$var = true |  | false | ~~NoMethodError~~ | false |  | **TRUE** | false | false | **TRUE**
$var = false |  | false | ~~NoMethodError~~ | **TRUE** |  | **TRUE** | false | **TRUE** | false
$var = [] |  | false | **TRUE** | **TRUE** |  | **TRUE** | false | **TRUE** | false
$var = [1] |  | false | false | false |  | **TRUE** | false | false | **TRUE**
$var = "" |  | false | **TRUE** | **TRUE** |  | **TRUE** | false | **TRUE** | false
$var = " " |  | false | false | **TRUE** |  | **TRUE** | false | false | **TRUE**
$var = 0 |  | false | ~~NoMethodError~~ | false |  | **TRUE** | false | **TRUE** | false
$var = 1 |  | false | ~~NoMethodError~~ | false |  | **TRUE** | false | false | **TRUE**
$var = "0" |  | false | false | false |  | **TRUE** | false | **TRUE** | false
$var = "1" |  | false | false | false |  | **TRUE** | false | false | **TRUE**

```present?```は```!blank?```と同義なので省略
```nil?```と```is_null```の違いはなし
```Ruby#empty?```と```PHP#empty```は数値判定に誤差がある
PHPに```blank?```に当たる関数はないが、やはり```empty```とは数値判定に誤差がある

## 引用

https://qiita.com/shinichi-takii/items/00aed26f96cf6bb3fe62

https://qiita.com/aeroastro/items/b58228decb7094af7594
[javascript]現在日時を1行で yyyy-mm-dd で取得する

毎回忘れるのでメモ

### yyyy-mm-dd
```javascript
  let now = new Date().toISOString().split("T")[0];
-> 2022-04-06
```

### yyyy/mm/dd
```javascript
  let now = new Date().toISOString().split("T")[0].replaceAll("-", "/");
-> 2022/04/06
```
FileMaker Admin API

一応ドキュメントがあるが、FMS にアクセスしないとみれない。

# 認証

流れとしては、

1. アクセストークンを取得し、
2. そのアクセストークンを使って実際の API コールを行う

ような使い方。


https://help.claris.com/ja/admin-api-guide/content/authentication-server.html

## 専用 API を使ってアクセストークンを取得する

Request Access Token API `/user/auth` に対して管理者のアカウント名とパスワードを使ってアクセストークンを取得し、それを使って API コールするというマニュアル通りの方法。

例えば、curl でトークン取得用の API コールを行う場合は下記の様な感じ。

```zsh
% curl -k -XPOST -H 'Authorization: Basic <Base64 エンコード文字列>' https://fms.host.name/fmi/admin/api/v2/user/auth
```

返却された JSON 内に token として入ってくる。

```json
{
  "response": {
    "token": "<アクセストークン>"
  },
  "messages": [
    {
      "code": "0",
      "text": "OK"
    }
  ]
}
```

アクセストークンを使う場合は `Authorization: Bearer <アクセストークン>` をリクエストヘッダーとして送る。

例えばデータベースの一覧を取得する API をアクセストークンを使って呼び出す場合はこんな感じ。

```zsh
% curl -k -H 'Authorization: Bearer <アクセストークン>' https://fms.host.name/fmi/admin/api/v2/databases
```

という感じ。

ちなみに、 `<Base64 エンコード文字列>` には管理者の `ユーザー名:パスワード` を base64 でエンコードしたものを入れる。

例えば、管理者のユーザー名が `adminuser` で パスワードが `adminpassword` の場合、mac なら下記のような感じで取得した値 `YWRtaW51c2VyOmFkbWlucGFzc3dvcmQ=` を使う。

```zsh
% echo -n 'adminuser:adminpassword' | base64
YWRtaW51c2VyOmFkbWlucGFzc3dvcmQ=
```

## いきなり API コールを行いつつアクセストークンを取得する方法

API コールをするときに認証を行い、その流れでアクセストークンを取得することも可能。

例えばデータベースの一覧を curl を使って取得する場合はこんな感じ。（レスポンスヘッダーに返ってくるので `-i` をつける）

```zsh
% curl -i -k -H 'Authorization: Basic <Base64 エンコード文字列>' https://fms.host.name/fmi/admin/api/v2/databases
```

レスポンスヘッダー `x-fm-access-token` にアクセストークンが返ってくるので、次回以降はそのトークンを使って実行すれば良い。

```
HTTP/2 200 
date: Tue, 05 Apr 2022 07:29:08 GMT
server: Apache
x-frame-options: SAMEORIGIN
x-powered-by: Express
x-fm-access-token: <アクセストークン>

・・・

```




## API コールすると 401 エラーになる場合

こうして見ると、普通にユーザー名とパスワードで API コールできるように見えるので、アクセストークン取得せず都度認証して APIコールしようと思ってしまうが、そんな感じで使ってると下記の様に 401 エラーになる。

```json
{
  "response": {},
  "messages": [
    {
      "code": "956",
      "text": "Maximum number of Admin API sessions exceeded"
    }
  ]
}
```

> Maximum number of Admin API sessions exceeded 

なので、Admin API のセッション数の上限を超えたということだと思うが、この状態になると発行済のアクセストークンを使っての API コールしか受け付けなくなる。

既存の Admin API セッションを無効にするには Invalidate Access Token API コールを使うしかないと思うが、下記の様な URI なので、そもそもアクセストークンを控えてないとどうしようもない。

```
/fmi/admin/api/v2/user/auth/<アクセストークン>
```

そのため、アクセストークンを控えていない状況下でこのエラーに遭遇したら、15分間待って既存のアクセストークンが無効になったら再度トークンの取得を行う。

>FileMaker Admin API では、アクセストークンを使用してホストへの接続を定義します。トークンは Invalidate Access Token (アクセストークンの無効化) 呼び出しを使用して無効にされるか、またはそのトークンを指定した最後の呼び出しから 15 分経過するまで有効です。(トークンが有効な間は、そのトークンを指定して呼び出しを行うたびにセッションタイムアウトカウンタがゼロにリセットされます。)
https://help.claris.com/ja/admin-api-guide/content/authentication-server.html


というわけで、大人しくアクセストークンを取得して Admin API をコールするような運用をした方がよさそう。
Laravelフレームワーク入門をver8で勉強するときのエラー箇所まとめ記事

https://www.amazon.co.jp/dp/B07CLLW4MX/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

上記図書をつかって勉強している。
上記図書はLaravel6を前提としている。
そのため、8をつかうとそのままではエラーが出る箇所がある。
当該箇所をまとめてくれている記事。
https://bokihajimeru.com/phplaravel/2852/

ありがたい
Laravelのログをstderrからdocker logsに出力する

# 概要
Dockerコンテナ上で動作しているLaravelのログを`docker logs`コマンドで表示させる場合の設定

# docker logs
[dockerドキュメント](http://docs.docker.jp/v19.03/engine/reference/commandline/logs.html)によると、
標準出力`STDOUT`と標準エラー出力`STDERR`にログを出すことで
docker logsにログが出てきそう。

# ロギングドライバ
Dockerにはログを外部のログ記録ソフトウェアに転送する機構が用意されている。

`docker logs`コマンドで確認できる内容は`/var/lib/docker/containers/＜コンテナID＞/＜コンテナID＞-json.log`というファイルにJSON形式で記録されている。
このJSONファイル内には`STDOUT` `STDERR`の情報も記録されている。

# 記述
config/logging.phpの`stack`の`channels`に「stderr」を記述することで、
標準エラー出力にLaravelからのエラーが出力されるようになる。
その内容が`docker logs [コンテナ名]`で確認できる。

`stack`チャンネルは、Laravelがログを出すときデフォルトで使用されるチャンネル。
```php
'channels' => [
    'stack' => [
        'driver' => 'stack',
        'channels' => ['stderr'],
        'ignore_exceptions' => false,
    ],
],
```

# 参考
[Laravel 6 を Docker 化する。その 3 。 Docker のログへ Laravel のログを出力](https://oki2a24.com/2019/10/28/docerize-laravel-6-3/)
[Dockerコンテナのロギング機能を使ってみる](https://knowledge.sakura.ad.jp/6752/)
[Docker + Nginx + Laravel(PHP-FPM)な環境のログを整理する](https://zenn.dev/nagi125/articles/8f6d4639342f1fc644eb)
[API Gateway→ Lambda] Lambdaでクライアント情報を取得してみました

場合によっては、Lambda Functionsでクライアント情報を取得する必要があります。
たとえば、クライアントのIPアドレスを確認します。

API Gateway（Lambda Proxy）→ Lambda Functions（Golang）を構築してみました。
Lambdaで、APIGatewayを呼び出したクライアントの情報を取得しました。

Golangのサンプルコード:
```
package main

import (
    "context"
    "fmt"
    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
)

func handleRequest(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    strInfo1 := request.RequestContext.Identity.SourceIP
    strInfo2 := request.RequestContext.Identity.UserAgent
    strInfo3 := request.RequestContext.Identity.User
    strInfo4 := request.RequestContext.Identity.Caller
    
    result := fmt.Sprintf("IP: %s \nUserAgent: %s \nUser: %s \nCaller: %s\n", strInfo1, strInfo2, strInfo3, strInfo4)
    fmt.Sprintf("%s", result)
    return events.APIGatewayProxyResponse{Body: result, StatusCode: 200}, nil
}

func main() {
    lambda.Start(handleRequest)
}
```


結果は...
・ブラウザで
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/622f857a-4aca-7852-4307-378be467a482.png)
・CURLで
```
# curl -k https://ul7****d.execute-api.ap-northeast-1.amazonaws.com/prd
IP: 13.***.***.76
UserAgent: curl/7.79.1
User:
Caller: 

# curl ipconfig.io
13.***.***.76

```

PythonまたはNodeJSでIPを取得しようとしています。

参考ドキュメント：
[type APIGatewayRequestIdentity struct]
https://github.com/aws/aws-lambda-go/blob/bc1ec47cb1670c0d5eaca47c10d89789d8507c3d/events/apigw.go#L134

[Building Lambda functions with Go]
https://docs.aws.amazon.com/lambda/latest/dg/lambda-golang.html

[Using AWS Lambda with Amazon API Gateway]
https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html
Stripe Checkoutを利用した決済で、ゲスト顧客の住所や氏名を取得する方法

Stripe Checkoutでは、会員機能のない通販サイトなど向けにゲスト注文の機能が用意されています。

https://qiita.com/hideokamoto/items/783cd6fef5759aaf1505

ゲスト顧客として注文を処理した場合、Customer APIから顧客のデータを取得することができません。

そのため、注文時に入力された氏名や住所は、Checkoutのセッション情報から取得します。

## Checkoutのセッション情報を取得する

Checkoutのセッション情報は、Session IDを利用して取得します。

```js
const session = await stripe.checkout.sessions.retrieve('cs_test_xxxx');
```

**2022/03/30以降の注文**では、取得したデータの中に`customer_details`が含まれています。

```js
{
      customer_details: {
        address: {
          city: null,
          country: 'JP',
          line1: null,
          line2: null,
          postal_code: null,
          state: null
        },
        email: 'test@example.com',
        name: 'test name',
        phone: null,
        tax_exempt: 'none',
        tax_ids: []
      }
      ...
}
```

このデータを利用して、発送業務や顧客からの問い合わせのサポートなどを行うことができます。

### 2022/03/29以前の注文で、データを取得する方法

2022/03/29以前に完了したセッションでは、`customer_details`が`null`になる場合があります。

そのため、以下のようにレスポンスを拡張してデータを取得する必要があります。

```js
      const session = await stripe.checkout.sessions.retrieve('cs_test_xxxxx', {
        expand: [
          'payment_intent.payment_method'
        ]
      });
      console.log(session.payment_intent.payment_method.billing_details);
```

**console.logの中身**

```js
    {
      address: {
        city: null,
        country: 'JP',
        line1: null,
        line2: null,
        postal_code: null,
        state: null
      },
      email: 'test@example.com',
      name: 'test name',
      phone: null
    }
```

## Webhookでデータを取得する

WebhookでCheckoutのセッション完了時に受信するイベント（`checkout.session.completed`）でも、この`customer_details`は取得できます。

Webhookの場合、`body.data.object.customer_details`とすこしネストが深い場所にありますので、ご注意ください。
【Postgresql & Docker】M1 Mac Apple 製のCPUに対応する開発環境への対応 

# AppleのM1チップに変更後開発環境が動かなくなった
具体的には Postgresql のイメージが対応していなかった。
バージョンは9.3.16を利用していましたが、13でも問題なく開発することができたのでそちらへ変更

ベストな対応方法はいろいろあるが一応動いたので、google検索で引っかかるように記事化。

docker-compose.ymlの記載を以下のように変更した。

```:before
image: postgres:9.3.16
```

```:after
platform: linux/x86_64
image: postgres:13
```

postgresql の docker image 一覧はこちらから

https://hub.docker.com/_/postgres

## linux/x86_64の記載は必要か
platform: linux/x86_64 と記載することで、M1チップ対応することができるという記事も散見されたが
postgres13の場合は特にこの記載がなくとも動作することが確認できた

新機能もいくらか増えているが本番環境では12あたりを利用しているので差分に気をつけたい。
もちろん同じバージョンにしていくこと前提なので、本番を13に上げたいですね:eyes:

postgresql13の公式リリース
https://www.postgresql.org/about/news/postgresql-13-released-2077/

## therubyracer も非対応になっていた
therubyracer、v8、いつもトラブルになる子ですね。
こちらも開発環境では不要で、jsのコンパイルに必要なだけなので開発環境では without する対応に一旦してます

最新の ruby にアップデートすれば miniracer が入っているのですが
現状のアプリをすぐにアップデートできないので一旦このような対応をお茶を濁してます

```shell
bundle install --without apple_slicon
```

```ruby:Gemfile
group :apple_slicon do
  gem 'therubyracer', '0.12.3', platforms: :ruby
end
```
Laravelのシーディング【個人的なお勉強アウトプット】

## 参考図書
https://www.amazon.co.jp/dp/B07CLLW4MX/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

## シーディングとは
テーブルの用意はマイグレーションでできる。
だけど、レコードは空。初期状態でいくつかダミーレコードを用意しておけると便利。
そのための機能がシーディング

## シーディングの手順
- 1.シーダーファイルを作成
- 2.シーダーファイルを編集
- 3.シーディングを実行

### 1.シーダーファイルを作成
コマンドで作成できる。
`php artisan make::seeder シーダーファイル名`
database/seeds/フォルダ内に作成される。

### 2.シーダーファイルを編集
上記コマンドでシーダーファイルを作成されると初期状態で以下のスクリプトが記述されている。
```database/seeds/PeopleTableSeeder.php
use Illuminate\Database\Seeder;

class PeopleTableSeeder extends Seeder{
public function run(){

}
}
```
シーディング処理はSeederクラスを継承したクラスとして定義する。
runメソッド内にレコード作成するための処理を用意する。

```database/seeds/PeopleTableSeeder.php
use Illuminate\Support\Facades\DB;

public function run(){
$param = [
'name' => 'taro',
'mail' => 'taro@yamada.jp',
'age' => 12,
];
DB::table('people')->insert($param);

$param = [
'name' => 'hanako',
'mail' => 'hanako@yamada.jp',
'age' => 34,
];
DB::table('people')->insert($param);
}

```

#### シーダーファイルの登録
作成したファイルが実行されるように、DatabaseSeederに登録をする必要がある。
プロジェクトにはデフォルトでDatabaseSeeder.phpというファイルが用意されている。これがシーディングのコマンドで実行されるスクリプト。
なので、このファイルのなかにPeopleTableSeederを呼び出す処理を用意しておく。

```database/seeds/DatabaseSeeder.php
use Illuminate\Database\``
class DatabaseSeeder extends Seeder{
public function run(){
$this->call(PeopleTableSeeder::class);
}
}
```
実行するシーダークラスのclassプロパティを引数にしてcallというメソッドで呼び出す。
これはSeederクラスにあるメソッドで、これにより指定したクラスのrunメソッドが呼び出されシーディング処理が実行されるようになる。

### 3.シーディングを実行
`php artisan db:seed`
Rails バッチ処理のエラー　「uninitialized constant Batch」

### バッチ処理を試していたときのエラー　「uninitialized constant Batch」 ###

色々調べると、「spring」というものが原因かも...

```terminal
$spring status #springの状態を確かめる
Spring is running: #springが動いている状態

$spring stop #springを止める
Spring stopped. 
```

これで無事に動くようになりました！

↓参考にしました　※springの説明

https://pleiades.io/help/ruby/spring.html
nvm インストール

#brew でインストール

```
brew install nvm
```

```
 source $(brew --prefix nvm)/nvm.sh
```

```
echo 'source $(brew --prefix nvm)/nvm.sh' >> ~/.bash_profile
```

# バージョン確認
```
nvm --version
```

# 何があるか確認
```
nvm ls-remote
```

# インストールしたいバージョンを指定
```
 nvm install 12.16.0
```

# 確認
```
nvm ls
```

# node確認
```
node --version

```

# リンク

[GitHub](https://github.com/nvm-sh/nvm)
https://github.com/nvm-sh/nvm

[参考本](https://qiita.com/ffggss/items/94f1c4c5d311db2ec71a)
https://qiita.com/ffggss/items/94f1c4c5d311db2ec71a

## 感謝
@ffggss
FileMaker Server のまとめ

https://qiita.com/YKInoMT/items/f64893568b90158ad030

FileMaker Server についてのまとめ

## mac

### 再起動

開始

```
sudo launchctl start com.filemaker.fms
```

終了

```
sudo launchctl stop com.filemaker.fms
```

https://help.claris.com/ja/server-help/content/fms-processes-macos.html

### ネットワークボリュームを追加のデータベースフォルダとして使う場合

macOS だと下記の注意点がある模様。

> ネットワークボリュームを使用するには、ネットワークドライブがマウントされていて FileMaker Server ユーザアカウントがデーモングループのメンバーである必要があります。
https://help.claris.com/ja/server-help/content/config-folders-additional.html

下記のコマンドを実行して daemon グループに FileMaker Server の実行ユーザーが入ってるか確認する。

```
% dscl . read /Groups/daemon
```

インストーラーの指示に従って　fmserver から変えていなければ入ってるはず。

パス指定方法は下記のようになっている。

> 例: filemac:/[ボリューム名]/[フォルダ名]/


```
filemac:/Macintosh HD/Volumes/[ボリューム名]/[フォルダ名]/
filemac:[ボリューム名]/[フォルダ名]/
```

上記の指定は通るが

```
filemac:/Volumes/[ボリューム名]/[フォルダ名]/
```

はエラーになる。

また、 fmserver_helperd に フルディスクアクセス が無いとエラーになる。

![Pasted Graphic 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84947/15dcb214-baf9-c1c4-b3c0-3a2f16ef8200.png)


ここに書いてあった・・・

https://support.claris.com/s/article/バックアップまたはデータベースフォルダの有効なパスを指定する-1503693036855?language=ja


## WebDirect

有効にするには Admin Console > コネクタ > Web 公開 で FileMaker WebDirect を有効する必要がある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84947/baefebfa-0529-479a-afa1-72720b1f0e57.png)

が、これだけではダメで Web 公開エンジン も有効にする必要がある。

![スクリーンショット 2022-01-27 16.55.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84947/3cef3d60-5527-e4de-2989-c711d0f05639.png)

### Web 公開エンジンが有効になっていない場合

Web 公開エンジンが有効になっていない場合、それぞれ下記のようなエラーが出るので Web 公開エンジンを有効にする必要がある。

|OS|メッセージ|
|-|-|
|Mac| メンテナンスで停止中か、サーバの処理能力の問題のため、 現在リクエストに応じることができません。 後ほど再度お試し下さい。 |
|Windows|502 - Web server received an invalid response while acting as a gateway or proxy server.<br> There is a problem with the page you are looking for, and it cannot be displayed. When the Web server (while acting as a gateway or proxy) contacted the upstream content server, it received an invalid response from the content server.|
|Ubuntu|Service Unavailable<br>The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.|

## Web 公開エンジンを有効にする

Admin Console で有効にするだけだが、mac と Windows はもう一手間必要。

JRE を入れろという画面が出てくるので画面の指示に従って入れないとダメ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84947/d12b6253-4522-6b88-1322-5239577d2b58.png)

JRE って書いてあるけど、Windows の場合 JDK をアップロードしないとダメだった。
mac は最初から JDK を入れてしまったので JRE で良いのかは不明。


Windows の場合は再起動が必要な感じの警告が出た。（macは忘れた）

![Pasted Graphic 4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84947/303de9e1-6e1b-38be-032a-5c2e921bab8a.png)
￼
FilemMaker Server の再起動、とは？と毎回思いつつ。とりあえず下記のコマンドを実行したら有効になった。

```cmd
net stop "FileMaker Server"
net start "FileMaker Server"
```

## 関連ページ

https://qiita.com/YKInoMT/items/33bad76d57f994f9bebb