OmniAICreator/Qiita-1.07M huggingface dataset:
テキストの前処理

# はじめに

自然言語処理をする際、テキストの正規化、日本語の前処理を行う必要があります。
それを行うPythonのコードが出回っていたのですが、それがあまりにもひどかったので戦慄しました。
おそらく[こちら](https://github.com/neologd/mecab-ipadic-neologd/wiki/Regexp.ja)が発端だと思うのですが、よりよいコードで塗り替えたいと思うに至りました。

# 結論

```python
import re
import unicodedata

OTHERTRANS = str.maketrans(
    '’”‘。、',
    '\'"`.,'
)

CTRLCHAR_PATTERN = re.compile('[\u0000-\u001F]')
SAPCE_PATTERN = re.compile(r"\s+")
HYPHEN_PATTERN = re.compile('[˗֊‐‑‒–⁃⁻₋−]+')
CHOONPU_PATTERN = re.compile('[﹣－ｰ—―─━ー]+')
TILDE_PATTERN = re.compile('[~∼∾〜〰～]+')

JP_PATTERN = '[\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF]'
LA_PATTERN = '[\u0021-\u007E]'
EXTRA_SPACE_PATTERNS = [
    re.compile(f"({JP_PATTERN}) ({JP_PATTERN})"),
    re.compile(f"({LA_PATTERN}) ({JP_PATTERN})"),
    re.compile(f"({JP_PATTERN}) ({LA_PATTERN})"),
]

def normalize_text(text):
    text = unicodedata.normalize('NFKC', text)
    text = text.translate(OTHERTRANS)

    text = CTRLCHAR_PATTERN.sub(' ', text)
    text = SAPCE_PATTERN.sub(' ', text)
    text = HYPHEN_PATTERN.sub('-', text)
    text = CHOONPU_PATTERN.sub('ー', text)
    text = TILDE_PATTERN.sub('~', text)

    for extra_space_pattern in EXTRA_SPACE_PATTERNS:
        text = extra_space_pattern.sub(r"\1\2", text)
    
    text = text.lower()

    return text
```

# おわりに

コメント欄で議論することによって、よりよく改善していければと思います。
GA4のローデータを活用して集計！BigQuery連携の手順+クエリ実行まで

## はじめに

この記事は以下のようなことをやりたい人におすすめです。

- GA4ではかゆいところに手が届かなかったところの集計・分析をしたい
- 画面ポチポチよくわからん。SQL書いてゴリゴリ分析したい
- 集計結果を顧客に共有・提出したい（CSV/Googleスプレッドシート）

ただし、以下の知識はすでにあるものとして説明を進めます。

- GCPのアカウント作成
- GCPでのプロジェクトの作成

## GA4→BigQuery連携の設定手順

### 事前準備
BigQueryにリンクするプロジェクトを作成しておいてください
https://analytics.google.com/analytics/

`管理 > BigQueryのリンク > リンク` と進みます。

![CleanShot 2023-01-18 at 17.23.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883/746dbcbf-8ec3-0ccf-750e-b8f6de77cd0a.png)
![CleanShot 2023-01-18 at 17.24.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883/6d18d8bf-455c-9bbf-a141-db4efda66415.png)
![CleanShot 2023-01-18 at 17.25.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883/963465fd-ddd1-6190-d951-b867eaffc63f.png)


`BigQuery プロジェクトを選択` を押し、準備したプロジェクトを選択してください。
![CleanShot 2023-01-18 at 17.28.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883/a398ef5f-f3c8-6016-d364-aad0369da24f.png)

:::note warn
プロジェクトが一覧に表示されない場合は、プロジェクトへのアクセス権限を確認してください
:::

### 構成設定
筆者は以下のようにしています。適宜設定してください。
（ストリーミングの設定は、サイト規模により課金が発生するのでBigQueryに慣れるまでオフにしておいたほうがよさそう）
- データのロケーション： `（東京）asia-northeast1`
- 構成の設定
    - データストリームとイベント
        - モバイルアプリ ストリーム用の広告識別子の追加 `チェックなし`
    - 頻度
        - 毎日　`✅ チェック`
        - ストリーミング `チェックなし`

以上で連携に必要な作業は完了です。

:::note warn
すぐにはデータができません（最大48時間）

実際にBigQueryのテーブルに出力されるまで時間がかかります。筆者の環境では1日半ほどかかりました。

:::

## データの確認
コンソールに移動してデータを確認してみましょう。
https://console.cloud.google.com/bigquery

![CleanShot 2023-01-18 at 17.43.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883/d260274a-0ca6-79bc-2aa9-0ba702deec49.png)

`events_(1)` のように表示されていればOKです。`()`内の数字はテーブル数（=日数）です。


### クエリを実行してローデータを見てみよう

![CleanShot 2023-01-18 at 17.48.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883/ffc4dbfa-9b8f-5643-4b66-0b76526b523c.png)

`🔍 クエリ > 分割タブ` でクエリ入力エリアを表示します
![CleanShot 2023-01-18 at 17.53.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883/b7e50e24-5012-1c1f-c3fc-f97a306e75b8.png)

:::note info
「分割タブ」にするとスキーマのフィールドを見ながらクエリが書けるのでおすすめ
:::

ここでは、「デバイスカテゴリ」と「イベント日」を「10件」表示してみたいとおもいます。

```sql
SELECT
  device.category, event_date
FROM
  `{your-project-id}.analytics_nnnn.events_YYYYMMDD`
LIMIT
  10
```
実行すると、結果が表示されるはずです。


クエリを編集すると、エラーは赤線で表示されますし、実行可能になった場合には実行時にどれくらいのバイト数を処理するかが表示されます。親切ですね。
![CleanShot 2023-01-18 at 17.58.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883/bd579ae9-8152-1a60-d67a-571590b6b7ec.png)

`クエリ結果 > ジョブ情報` を見ると、実行結果の詳細が確認できます。

![CleanShot 2023-01-18 at 18.06.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883/b2995993-2d37-f496-aa9a-5d0fa25c3b5b.png)

## まとめ

連携自体はとても簡単でしたね。BigQuery上でのデータ集計はSQLライクに書けるので試すまでのハードルが低かったです。
GA4が得意な所と使い分けしながら活用できると強力な武器になりそうです。

### 参考リンク

- 最新情報 [BigQuery release notes  \|  Google Cloud](https://cloud.google.com/bigquery/docs/release-notes?hl=ja&_ga=2.175513514.-987589594.1649921353)
- [クエリ構文  \|  BigQuery  \|  Google Cloud](https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax?hl=ja)
Monacaクイックビューアで開発する際の注意点

[iOS版Monacaデバッガー配信停止](https://ja.docs.monaca.io/release_notes/discontinuation-of-ios-store-monaca-debugger-and-alternatives)に伴って、新しくMonacaでリリースされたのが「[Monacaクイックビューア](https://ja.docs.monaca.io/products_guide/quick-viewer)」です。

一見するとUIはMonacaデバッガーと同じように見えますが、幾つかの違いがあります。本記事ではその相違点について紹介しつつ、開発時の回避策を解説します。

## Cordovaプラグインは使えません

Monacaデバッガーでは、以下のプラグインがデフォルトで組み込まれています。

- バーコードスキャナー
- バッテリー
- カメラ
- キャプチャー
- デバイス
- デバイスモーション
- デバイスオリエンテーション
- ファイル
- ジオロケーション
- アプリ内ブラウザ
- メディア
- ネットワーク情報
- ローカル通知
- バイブレーション

これらの機能の幾つかについてはHTML APIで代替処理ができます（位置情報、カメラなど）。ただ、Cordovaプラグインとは動作が異なる可能性があるので注意してください。

Monacaアプリとしてビルドしている場合と、Monacaクイックビューアで動作している際の違いは、 `window.cordova` 変数の有無をチェックするのが良いでしょう。

```js
if (window.cordova) {
  // Monacaアプリ、カスタムデバッガービルドとして動作している
  // Cordovaプラグインが使える
} else {
  // Monacaクイックビューア、Web IDEのプレビューとして動作している
  // Cordovaプラグインは使えない
} 
```

HTML APIで代替できるものについては、この判定を使って処理分けしたり、Monacaクイックビューアでは動作させないと言った仕組みにする必要があります。

例えばNCMBのプッシュ通知プラグインもMonacaクイックビューアでは利用できませんので、 `window.NCMB.monaca.setDeviceToken` のような関数へのアクセスはエラーになってしまいます。

## 利用開始できるイベントが異なります

Monacaアプリの場合、画面のDOM構築に加えてCordovaプラグインの準備完了を待ちます。そのイベントが `deviceready` です。対してMonacaクイックビューアの場合はDOM構築のみになるので、 `DOMContentLoaded` イベントのみになります。Monacaクイックビューアで `deviceready` を待ってもイベントが呼ばれないので注意してください。

お勧めの方法としては、 `window.cordova` の有無でイベントを変えることです。

```js
const event = window.cordova ? 'deviceready' : 'DOMContentLoaded';
document.addEventListener(event, e => {
  // 処理を記述
});
```

なお、Onsen UIなどを使っている場合には `ons.ready` などあらかじめ指定されているものを利用すれば問題ありません。

## SafariとwkWebViewでは利用できる機能に差異があります

MonacaクイックビューアをSafariで開いて利用する方は多いかと思います。それに対して、MonacaアプリはレンダリングエンジンにwkWebViewを使います。この時の機能差は意識して開発を行う必要があります。

具体的にどこが違うのか判定が難しいのですが、例えばSafariはフルスクリーン表示ができますが、wkWebViewを使ったブラウザ（Chromeなど）ではできません。[Safariは動画のインライン再生ができます](https://uupaa.hatenablog.com/entry/2016/08/29/171809)が、Chromeでは最大表示になってしまいます。

ChromeはwkWebViewを使っているはずなので、MonacaクイックビューアはChromeで利用するのがお勧めです。Safariで利用できている機能がMonacaアプリで使えないと言った動作齟齬を極力なくした方が、開発しやすいでしょう。

## CORS制限/CSPには注意してください

Webアプリケーションが常に気にしなければならないのがCORS制限です。fetch関数では外部サイトへのPOSTであったり、任意のコンテンツをGETで取得するのに制限があります。

Cordovaプラグインであれば [cordova-plugin-advanced-http](https://github.com/silkimen/cordova-plugin-advanced-http) や [cordova-plugin-fetch](https://github.com/aporat/cordova-plugin-fetch) が利用できますが、Monacaクイックビューアでは使えないので問題になります。これの解決策はMonacaカスタムデバッガービルドを使うほかないでしょう。

また、WebアプリではCSP（Content Security Policy）も問題になります。HTTPSでは使える機能が、MonacaアプリのURLスキーマでは使えない場合があります。これも分かりやすい一覧などがある訳ではないので、実際にやってみないと分からないのですが…なるべく早い段階でカスタムデバッガービルドを使った方が動作差異をなくせます。

## まとめ

Monacaクイックビューアは簡易的な動作確認用ツール、くらいに考えておく方が良いでしょう。iOSアプリをちゃんと開発するならば、早めにカスタムデバッガービルドを使うのがお勧めです。

なお、NCMBのプッシュ通知プラグインはカスタムデバッガービルドでは正しく動作しない（プッシュ通知受信時に期待したハンドリングができない）のでご注意ください（参考： [ニフクラ mobile backendを使ってAndroidへプッシュ通知を送る手順を一から紹介 – モナカプレス](https://press.monaca.io/atsushi/12632)）。
Linux ショートカット一覧

**Linux ショートカット一覧**

Ctrl+A	コマンドラインの先頭にジャンプします。
Ctrl+E	コマンドラインの最後にジャンプします。
Ctrl+U	カーソルからコマンドラインの先頭までクリアします。
Ctrl+K	カーソルからコマンドラインの最後までクリアします。
Ctrl+LeftArrow	コマンドラインの前の単語の先頭にジャンプします。
Ctrl+RightArrow	コマンドラインの次の単語の最後にジャンプします。
Ctrl+R	コマンドの履歴リストであるパターンを検索します。

ディレクトリを作成する	mkdir directory
ファイルをコピーする	cp file new-file
ディレクトリとその内容をコピーする	cp -r directory new-directory
単一のディレクトリを移動または名前変更する	mv file new-file
ファイルを削除する	rm file
ファイルが含まれたディレクトリを削除する	rm -r directory
空のディレクトリを削除する	rmdir directory

パターン	一致例
*	0 文字以上の任意の文字列。
?	任意の 1 文字。
[abc...]	かっこで囲まれたクラス内の任意の 1 文字 (角かっこ内)。
[!abc...]	角かっこで囲まれたクラス以外の任意の 1 文字。
[^abc...]	角かっこで囲まれたクラス以外の任意の 1 文字。
[[:alpha:]]	任意の英字。
[[:lower:]]	任意の小文字。
[[:upper:]]	任意の大文字。
[[:alnum:]]	任意の英字または数字。
[[:punct:]]	スペースや英数字以外の任意の印刷可能文字。
[[:digit:]]	0 から 9 までの任意の数字。
[[:space:]]	任意のスペース 1 文字。これには、タブ、改行、キャリッジリターン、改ページ、またはスペースが含まれます。

crontab -l	現在のユーザーのジョブを一覧表示します。
crontab -r	現在のユーザーのすべてのジョブを削除します。
crontab -e	現在のユーザーのジョブを編集します。
crontab filename	すべてのジョブを削除し、それらから読み取ったものに置き換えます。このコマンドはstdin、ファイルが指定されていない場合に入力を使用します。
初めての Red Hat Directory Server 構築

**初めての Red Hat Directory Server 構築**

初めまして。にっくんと申します。
Hyper-V で Red Hat Directory Server 構築 なんてしてる人がいなさそうなので書いてみます。

環境 Windows10 Pro
ゲストOS RHEL7.9 Server

OSのダウンロードはこちらから
https://www.redhat.com/ja/products/trials?products=hybrid-cloud

当然ながらRed Hat Directory Server のライセンスがないとインストールできません。

まず、Red Hat Directory Server を提供するプールIDを下記コマンドで特定します。

```Bash.
# subscription-manager list --all --available --matches 'Red Hat Directory Server'
```

プールIDが見つかったら、下記コマンドでプールIDを紐づけます
```Bash.
# subscription-manager attach --pool=XXXXXXXXXXXXXXXXXXXXXXXXXX
Successfully attached a subscription for: Example Subscription
```

yum コマンドがうまくいかなかったので、iso ファイルをひっぱってきてマウントします。
```Bash.
# mount /dev/cdrom /media
mount: /dev/sr0 is write-protected, mounting read-only
```
/etc/yum.repos.d/ に移動して rhel-dvd.repo ファイルを編集します。
```Bash.
# cd /etc/yum.repos.d/
# vi rhel-dvd.repo
```
コマンド G で最後列に移動し、下記を加えます。
```Vi.
[rhel-DirectoryServer]
name=Red Hat DirectoryServer
baseurl=file:///media/
enabled=0
gpgcheck=1
gpgkey=file:///media/cdrom/RPM-GPG-KEY-redhat-release
```
保存が終わったら動作確認として利用可能なパッケージ一覧を表示させます
```Bash.
# yum --disablerepo=\* --enablerepo=rhel-DirectoryServer list
読み込んだプラグイン:langpacks, product-id, search-disabled-repos, subscription-manager
インストール済みパッケージ
（以下省略）
```
M5 UnitV2にGentoo Linuxをいれてみた その2

[その1](https://qiita.com/ebisuke/items/d3f38a8363a48c2ea919)のつづきです。

# 目的
- できるだけ従来実現していた機能を再現したい
- ある程度はちゃんと動かせるようにしたい  

# 現状把握
## メモリ
スワップが欲しい。
```
root@unitv2 ~ # free
               total        used        free      shared  buff/cache   available
Mem:          118604       18636       29428         532       70540       93972
Swap:              0           0           0
```
## ネットワークとか
WiFiがないです。eth0が見えているのはUSB-ETHの方ですね。  
```
root@unitv2 ~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether be:e7:57:62:c2:e0 brd ff:ff:ff:ff:ff:ff
```
## ブロックデバイスとか
こっそりとmicroSDを変えてます。
mtdblock~のサイズが変ですね。まだ触らないようにします。
```
root@unitv2 ~ # lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
mtdblock0    31:0    0   512M  0 disk
mtdblock1    31:1    0   384K  0 disk
mtdblock2    31:2    0 497.3M  0 disk
mmcblk0     179:0    0 230.5G  0 disk
└─mmcblk0p1 179:1    0 230.5G  0 part /
```


# あれこれ作業
## swap作成
```
dd if=/dev/zero of=/swap bs=1024 count=1048576
chmod 600 /swap
mkswap /swap
swapon /swap
echo "/swap   none   swap   defaults   0   0" >> /etc/fstab
```
## 無線LAN導入
無線LANドライバはその1のスクリプトで入れようにしましたが、うまく入れられないので、
入らなかったら直接insmodで入れてください。
```
cd /usr/src/rtl8188fu_linux
depmod -a
modprobe rtl8188fu
``` 
## dhcpcdのビルド
portage使うためにインターネットに繋がないといけないが、最小限のものもないため入れる。
- dhcpcd
    - https://github.com/NetworkConfiguration/dhcpcd
```
cd /usr/share/extra/
cd ../../dhcpcd
./configure && make && make install
```

## 最初のemerge-webrsync
dhcpcdを稼働させ、PC(mac)に接続したUSB-ETHとインターネット共有設定にすることでひとまず繋がりました
```
systemctl enable dhcpcd
systemctl start dhcpcd
ip link set wlan0 up
ping 8.8.8.8
```
```
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=114 time=12.2 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=114 time=108 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=114 time=57.2 ms
```

emerge-webrsyncを実行し、同期させる。
```
emerge-webrsync
```

### 必要なものをインストール
```
emerge -av openssh wpa_supplicant rsync
```


既存機能確認は次回に続く
【Vue3/Vite】スマホでlocalhostを確認する方法

## はじめに
レスポンシブのWebアプリを作成していると、ローカルで開発中の状態を実機のスマホで確認したいと思うことはありませんか？？

はい！私はあります。

とてつもなく簡単なんですが、意外と詰まったので共有しようと思います。
## 前提
**スマホとPCで同じWifiを利用していること**
## スマホでlocalhostを確認する手順
### 1. --hostを追加する
普段通り```npm run dev```をすると、下記のように表示されませんか？？
```
  VITE v4.0.4  ready in 220 ms

  ➜  Local:   http://127.0.0.1:3000/
  ➜  Network: use --host to expose
  ➜  press h to show help
```

上記に書いている通り```--host```をオプションとして追加することで表示されるURLにスマホでアクセスすることで、PCで表示しているローカルページがひらけます。
```
npm run dev --host
 ➜  Local:   http://localhost:3000/
 ➜  Network: http://IPアドレス:3000/
```
### 2. vite.config.jsに追記する
もしviteを使っているのであれば、ルートディレクトリに```vite.config.js```が存在しているのではないでしょうか？

同ファイルのdefineConfigの中のserver.hostをtrueにすることでも1番の```--host```をつけているように、NetworkのURLが表示されます。
```
import { defineConfig } from "vite";

export default defineConfig({
  server: {
    host: true,
  },
});
```



```
npm run dev
 ➜  Local:   http://localhost:3000/
 ➜  Network: http://IPアドレス:3000/
```
[UE5]c++でコマンドプロンプトを呼び出し、Pythonの実行

# はじめに
[以前の記事](https://qiita.com/k-o233/items/dad8e5a9dd4d0398a1ab)でPythonを実行する方法を書きましたが、
この機能は実験的機能なので、ゲームをパッケージ化したら、うまく使用できません。
本記事でコマンドプロンプトを呼び出し、Pythonを実行する方法を紹介します。
>Unreal Engineドキュメント：Python を使用したエディタのスクリプティング
 https://docs.unrealengine.com/5.0/ja/scripting-the-unreal-editor-using-python/

この方法は、C++で関数（BlueprintFunctionLibrary）を書いて、ブループリントで関数ノードを使用する方法です。

## 準備
Unreal EngineとVisual Studioをインストールします。
セットアップは下記のURLを参考にしてください。


https://docs.unrealengine.com/4.27/ja/ProductionPipelines/DevelopmentSetup/VisualStudioSetup/


## 方法

#### **Step 1**　新規C++クラス `BlueprintFunctionLibrary`

UEでBlueprintFunctionLibraryクラスを新規します。
[以前の記事](https://qiita.com/k-o233/items/0b03649206396fd5c84b)で簡単な説明をしています。良ければ参考にしてください。

#### **Step 2**　コードの編集
**①**.hファイルでRunMyPython関数を追加します。
```c++:MyBlueprintFunctionLibrary.h
UFUNCTION(BlueprintCallable, Category = "RunPython")
static bool RunMyPython(int32& ProcessId, 
FString FullPathOfProgramToRun, TArray<FString> CommandlineArgs, bool Hidden);
```
**引数**と**戻り値**の意味は下の通りです。
<dl>
  <dt>引数</dt>
  <dd>FullPathOfProgramToRun：python.exeへのパス　(FString型)</dd>
  <dd>CommandlineArgs：コマンドライン引数　(FString型の配列)</dd>
  <dd>Hidden：コマンドプロンプトのウィンドウの表示/非表示　(bool型)</dd>
  <dt>戻り値</dt>
  <dd>ProcessId：実行中のプロセスid　(int32型)</dd>
  <dd>return：プロセスが完成すると、trueを戻る　(bool型)</dd>
</dl>

#
**②**.cppファイルでRunMyPython関数の詳細コードを書きます。
```c++:MyBlueprintFunctionLibrary.cpp
bool UForExePython::RunMyPython(int32& ProcessId, FString FullPathOfProgramToRun, 
TArray<FString> CommandlineArgs, bool Hidden) 
{
    /*
    コマンドライン引数の配列を空白で結合する
    */
    FString Args = "";
	if (CommandlineArgs.Num() > 1)
	{
		Args = CommandlineArgs[0];
		for (int32 v = 1; v < CommandlineArgs.Num(); v++)
		{
			Args += " " + CommandlineArgs[v];
		}
	}
	else if (CommandlineArgs.Num() > 0)
	{
		Args = CommandlineArgs[0];
	}


    /*
    新しいプロセスを作成する（CreateProcess関数と似てるもの）
    */
	uint32 NeedBPUINT32 = 0;
	FProcHandle ProcHandle = FPlatformProcess::CreateProc(
		*FullPathOfProgramToRun,
		*Args,
		Hidden, //trueにしたら、コマンドプロンプトのウィンドウを非表示にする
		false,
		false,
		&NeedBPUINT32,
		0,
		nullptr,
		nullptr);

	ProcessId = NeedBPUINT32;

	if (ProcHandle.IsValid()) {
        /*
        上記のプロセスが終了したまで、待ちます。
        */
		while (FPlatformProcess::IsProcRunning(ProcHandle));
		FPlatformProcess::CloseProc(ProcHandle);
	}

	return true; //プロセスが終了して、trueを戻る。
}
```

## 使用方法
C++ファイルを修正し、UEのプロジェクトを更新して、ブループリントでRun My Pythonノードが使用できると思います。
![qu1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727189/e5b5d842-42ac-43a3-e305-78d757b6df0b.png)


* *説明１*
上記の画像通りで、入力も同じ文字列で使用すると、
普通のコマンドプロンプト(Windowsではcmd)で、`"C:/xxx/xxx/python.exe" pyfile.py --input C:/xxx/xxx/myfile.txt`という**コマンド**を実行すると同じ結果が出るはずです。

* *説明２*
`Hidden`にチェックを入れると、コマンドプロンプトのウィンドウを表示しません。

* *説明３*
Pythonプロセスを終了して、`Return Value`ではtrueが出力します。
とは言え、Pythonプロセスを待つことが可能になります。

#

### 感想
Windowsでアプリを開発すると、C/C++言語は汎用性が高いので、よく使われます。今回は、Unreal EngineでPythonを使用したいため、色々調べて実現できました。


最後まで読んでいただき、ありがとうございました。
皆さんの参考になれば幸いです。
プリザンターのサーバースクリプトにおいて、items.Getで200件以上のレコードを取得する方法

 # はじめに
items.GetでOffsetを指定し、200件以上のレコードを取得する

 # ソースコード
```javascript

//サイトIDを設定
const siteId = XXXX;
//Offsetを設定
const offSet = 200;
//JavaScriptオブジェクトとして、Offsetに200を設定
let data = {
    //Offsetは開始位置
    Offset : offSet
};
//サイトIDとJSONオブジェクトに変換したdataでレコード情報を格納
let results = items.Get(siteId, JSON.stringify(data));
//1レコード単位で処理を実行
for (let result of results) {
    //resultに設定されているレコードのレコードIDを表示
    context.Log(result.ResultId);
}

```

 # 工夫
工夫というよりは今回の件で理解したことがありました。それは、Offsetというのは読み取りの開始位置だということ。さらにJSON.parse()は、JSON文字列を取得し、JavaScriptオブジェクトに変換するのに対して、JSON.stringify()は、JavaScriptオブジェクトを取得し、JSON文字列に変換するということ。これからはこの知識をもとにサーバースクリプト内でJSONと文字列の変換には困らなそうです。ちなみに、下記リンクを参照。
https://www.digitalocean.com/community/tutorials/js-json-parse-stringify-ja
プロキシ環境下でAWS SDK for PHPを利用してファイルのアップロード・ダウンロードを行いたい

クライアント作成時に `'http' => ['proxy' => 'http://192.168.16.1:10']` を追加することで、プロキシ環境下でAWS SDK for PHPを利用したS3へのアクセスが可能となります。


```php
require 'vendor/autoload.php';

use Aws\S3\S3Client;
use Aws\Exception\AwsException;

$s3 = new \Aws\S3\S3Client([
    'resion' => 'ap-northeast-1',
    'version' => 'latest',
    'profile' => 'default',
    'http' => ['proxy' => 'http://192.168.16.1:10']
]);

```

# 参考

↓の `proxy` を参照

https://docs.aws.amazon.com/ja_jp/sdk-for-php/v3/developer-guide/getting-started_basic-usage.html
AWS SDK for PHPでS3からgzipファイルをそのまま（展開されることなく）取得したい

# はじめに

PHPでaws-sdkを使用してS3からファイルをダウンロードする際に、gzipファイルが展開された状態で出力される場合があります。
特に、gzipのままファイルが欲しい場合に困ってしまいます。

# 対応
クライアント作成時に `'http' => ['decode_content' => false]` を追加することで、gzipファイルが展開されずに（gzipファイルのまま）取得することができます。


```php
require 'vendor/autoload.php';

use Aws\S3\S3Client;
use Aws\Exception\AwsException;

$s3 = new \Aws\S3\S3Client([
    'resion' => 'ap-northeast-1',
    'version' => 'latest',
    'profile' => 'default',
    'http' => ['decode_content' => false]
]);

```

# 参考

↓の `decode_content` を参照

https://docs.aws.amazon.com/ja_jp/sdk-for-php/v3/developer-guide/guide_configuration.html#config-http
COPY INTOを用いたデータロードにおける一時資格情報の活用

[Use temporary credentials to load data with COPY INTO \| Databricks on AWS](https://docs.databricks.com/ingestion/copy-into/temporary-credentials.html) [2022/9/27時点]の翻訳です。

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

お使いのDatabricksクラスターやSQLウェアハウスがソースファイルを読み込む権限を有していない場合、外部クラウドオブジェクトストレージのデータにアクセスするために一時資格情報を使うことができます。

皆様の組織でクラウドセキュリティをどのように関しているのかに応じて、クラウド管理者やパワーユーザーに資格情報を提供してもらうように依頼する必要があるかもしれません。

# データにアクセスするための一時資格情報、あるいは暗号化オプションの指定

:::note
**注意**
資格情報と暗号化オプションはDatabricksランタイム10.2以降で利用できます。
:::

`COPY INTO`は以下をサポートしています:

- ADLS Gen2やAzure Blob Storageからデータを読み込むための[Azure SASトークン](https://learn.microsoft.com/azure/storage/common/storage-sas-overview)。Azure Blob Storageの一時トークンはコンテナレベルですが、ADLS Gen2のトークンはコンテナレベルに加えてディレクトリレベルとなります。可能な限り、ディレクトリレベルのSASを使うことをお勧めします。SASトークンには`Read`、`List`、`Permissions`権限が必要です。
- AWS S3からデータを読み込むための[AWS STSトークン](https://docs.aws.amazon.com/AmazonS3/latest/userguide/AuthUsingTempSessionToken.html)。トークンには`s3:GetObject*`、`s3:ListBucket`、`s3:GetBucketLocation`権限が必要です。

:::note alert
**警告！**
一時資格情報の誤用や漏洩を避けるために、タスクを完了するのに十分な有効期限を設定することをお勧めします。
:::

`COPY INTO`はAWS S3の暗号化データのロードをサポートしています。暗号化データをロードするには、暗号化のタイプとデータを複合するためのキーを指定する必要があります。

# 一時資格情報を用いたデータのロード

以下のサンプルでは、ソースデータへのアクセスを提供するために一時資格情報を用いてS3とADLS Gen2のデータをロードしています。

```sql:SQL
COPY INTO my_json_data
FROM 's3://my-bucket/jsonData' WITH (
  CREDENTIAL (AWS_ACCESS_KEY = '...', AWS_SECRET_KEY = '...', AWS_SESSION_TOKEN = '...')
)
FILEFORMAT = JSON

COPY INTO my_json_data
FROM 'abfss://container@storageAccount.dfs.core.windows.net/jsonData' WITH (
  CREDENTIAL (AZURE_SAS_TOKEN = '...')
)
FILEFORMAT = JSON
```

# 暗号化データのロード

顧客が指定する暗号化キーを用いて、以下の例ではS3からデータをロードしています。

```sql:SQL
COPY INTO my_json_data
FROM 's3://my-bucket/jsonData' WITH (
  ENCRYPTION (TYPE = 'AWS_SSE_C', MASTER_KEY = '...')
)
FILEFORMAT = JSON
```

# ソースとターゲットで資格情報を用いたJSONデータのロード

以下の例では、AWS S3のファイルから`my_json_data`という外部DeltaテーブルにJSONデータをロードしています。このテーブルは`COPY INTO`を実行する前に作成しておく必要があります。このコマンドでは、外部Deltaテーブルに書き込むための資格情報と、S3ロケーションから読み込むための資格情報をそれぞれで使用しています。

```sql:SQL
COPY INTO my_json_data WITH (CREDENTIAL target_credential)
  FROM 's3://my-bucket/jsonData' WITH (CREDENTIAL source_credential)
  FILEFORMAT = JSON
  FILES = ('f.json')
```

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
neovimのinit.lua設定 おすすめ2023

# 概要
そろそろneovimに乗り換えたいな〜と思っていたものの、最近の(?)neovimは設定ファイルが`init.lua`というluaファイルの形式になっていて、既存のvimrcから書き換えるの面倒だな〜と思っていましたが、いい感じに初期設定してくれるリポジトリを見つけたので紹介します。

# kickstart.nvim
https://github.com/nvim-lua/kickstart.nvim

インストールは上記githubにある`init.lua`をコピってきて、`~/.config/nvim/init.lua`に置いてやるだけ！
あとはnvimを起動すると勝手に初期設定をしてくれる！

# 使い方を紹介しているyoutubeがある
これを見るとだいたいわかる。

https://youtube.com/watch?v=stqUbv-5u2s&feature=share

# 個人的に気になったところ
## `<leader>` がデフォルトでスペースに割り当てられてる
`init.lua` の中で下記の設定をしている箇所があるので、デフォルトの`\`に戻すなり変えたりしたい場合は書き換えてやる。（デフォルトに戻したい場合はコメントアウトしてやれば良い）
```lua
vim.g.mapleader = ' '       
vim.g.maplocalleader = ' '
```

## `Mason` が便利！
[mason.nvim](https://github.com/williamboman/mason.nvim) というプラグインがデフォルトで設定されていて、言語毎のLSPのインストールや設定をGUI的にできる！
まだあまり使いこなせてないが。。。

## `telescope` が便利！
[telescope.nvim](https://github.com/nvim-telescope/telescope.nvim)
ファジーファインダーです。
デフォルトで`<leader>sf`などのキーマップが設定されているので、ファイルの探索が楽。

# まとめ
とりあえずこれをベースに設定やプラグイン追加していくと良いかなと思いました。
iPhoneが急にタッチできなくなった際のソリューション

<h1>ソフトウェア要因</h1>
iPhoneのタッチパネルに不具合が生じる原因は一様ではありません。大きくは、ソフトウェア要因とハードウェア要因に二分されます。<br>ソフトウェア要因の場合、再起動が最も優先して行うべき対応です。<br>画面が反応しない場合、電源ボタンとボリュームダウンボタンを長押し後、画面に表示される「スライドで電源オフ」を行うことができないため、強制再起動が必要です。<br>強制再起動は以下の手順で行います。<br><ol>
<li>ボリュームアップボタンをクリック</li>
<li>ボリュームダウンボタンをクリック</li>
<li>電源ボタンを長押し。画面がブラックアウト後、リンゴマークが表示されたら電源ボタンから手を放す</li>
</ol><br>以上の手順で強制再起動が完了します。<br>これでタッチの不具合が改善した場合、一時的なシステム異常だったと言えます。</p>
<h1>ハードウェア要因</h1>
<ul>
<li>画面が割れている</li>
<li>液晶漏れがある</li>
<li>画面に虹色の縦線が表示される</li>
</ul>
画面が上記のような状態で、タッチに異常が見られる場合は、画面部品の故障が原因で異常が発生している可能性が高いでしょう。
部品の故障は修理でのみ改善できます。
<h1>修理</h1>
正規店での修理では、本体交換となり多くの場合データが初期化されて戻ってくる可能性があることに注意しましょう。
第三者修理店では、正規店のデメリットをカバーできることがあります。データは初期化されず、予約せずとも最短30分ほどで返却してもらえることも多くあるのが、第三者修理店のメリットです。
<h1>参考</h1>
<ol data-sourcepos="25:1-28:46">
<li data-sourcepos="25:1-25:47"><a href="https://flash-agt.com/blog/tips/53989" class="autolink" rel="" target="_blank">iPhoneのタッチパネルが反応しない原因と対処法 【スマホ修理王】</a></li>
</ol>
</div></div>
wslでnerves その10

# 概要
wsl(wsl2じゃない)でnervesやってみる。
qemu(x86_64エミュレータ、ラズパイじゃない)でやってみた。
練習問題やってみた。

# 練習問題
この、errorを潰せ。

```
iex(4)> Logger.info("ok")
** (UndefinedFunctionError) function Logger.info/1 is undefined or private. However there is a macro with the same name and arity. Be sure to require Logger if you intend to invoke this macro
    (logger 1.13.4) Logger.info("ok")

```

# 対処

```
iex(6)> log_attach
{:ok, #PID<0.1111.0>}
iex(7)> :logger.info("ok")

07:13:24.735 [info]  ok
:ok
iex(8)>

```

以上。
EC-CUBE 3.0系をdockerで動かすときのメモ

3.0.18をDockerで動かすときのメモ

```
// git clone
git clone https://github.com/EC-CUBE/ec-cube3.git
cd ec-cube3

// 2.17のdocker関連ファイルを取得
(
CURRENT_DIR=$(pwd)
cd /tmp
git clone --depth 1 https://github.com/EC-CUBE/ec-cube2.git
cd ec-cube2
cp -r dockerbuild ${CURRENT_DIR}/
cp Dockerfile ${CURRENT_DIR}/
cp docker-compose.yml ${CURRENT_DIR}/
cp docker-compose.pgsql.yml ${CURRENT_DIR}/
cp docker-compose.mysql.yml ${CURRENT_DIR}/
cp docker-compose.dev.yml ${CURRENT_DIR}/
cp eccube_install.sh ${CURRENT_DIR}/

rm -rf /tmp/ec-cube2
)

// composer1系を利用
sed -i "" 's/composer:2.2/composer:1.10/g' Dockerfile

// インストールは別途行うので不要
sed -i "" 's/.*wait-for-pgsql\.sh/#&/g' docker-compose.pgsql.yml  
sed -i "" 's/.*wait-for-mysql\.sh/#&/g' docker-compose.mysql.yml  

// pgsqlはバージョン9を利用
sed -i "" 's/image: postgres/&:9/g' docker-compose.pgsql.yml

// ビルド
export TAG=7.0-apache
docker build -t ec-cube2 --no-cache --pull \
--build-arg TAG=${TAG} \
--build-arg GD_OPTIONS="--with-freetype-dir=/usr/include --with-jpeg-dir=/usr/include" \
--build-arg EXT_INSTALL_ARGS="gd zip mysqli pgsql opcache pdo_pgsql pdo_mysql" \
--build-arg APCU=apcu \
--build-arg FORCE_YES= \
./

// タグ付け
docker tag ec-cube2 ghcr.io/ec-cube/ec-cube2-php:${TAG}

// 起動(pgsql)
docker-compose -f docker-compose.yml -f docker-compose.pgsql.yml -f docker-compose.dev.yml up

// 起動(mysql)
docker-compose -f docker-compose.yml -f docker-compose.mysql.yml -f docker-compose.dev.yml up

// composer install
docker exec -it ec-cube3-ec-cube-1 composer install 

// ブラウザで開く
open https://localhost:4430/
```

トラブルシュート

pgsqlで`FATAL:  "/var/lib/postgresql/data" is not a valid data directory`のエラーが出る場合は以下を参照

https://qiita.com/mm_sys/items/996991d19b0d6e5c0715
【JavaScript】非同期関数内のエラーを呼び出し元でキャッチしたい

## 問題

非同期関数を呼び出す時、呼び出し元でtry/catchを書いてもエラーをcatchできず、困っていました。

以下の場合、関数`sub`だけではなくて関数`func1`でも例外をキャッチしたい！

```js
async function sub() {
  console.log("subが呼ばれました");
  try {
    const a = 0;
    a = 1; // エラー発生！
    res = a;
    return res;
  } catch (e) {
    console.error("subでエラーが発生しました", e); // キャッチされる
  }
}

async function func1() {
  try {
    console.log("func1が呼ばれました");
    const result = await sub(); // この関数内でエラー発生
    console.log("resultにsubの結果を格納しました");
  } catch (e) {
    console.error("func1でエラーが発生しました", e); // キャッチしたいけどされない！
  }
}

func1();
```

実行結果
![キャッチされない.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652834/90db6ae3-89bd-00a8-b051-d86989f32025.png)



## 解決方法

呼び出し先の関数でcatchした例外をそのままthrowする（例外の再発生）
具体的には、`throw e`を追記する。

> 再度発生した例外は、利用者がわかるように、囲んでいる関数または最上位にいたるまで伝播します。

[参考サイト](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/throw)より
```js
async function sub() {
  console.log("subが呼ばれました");
  try {
    const a = 0;
    a = 1; // エラー発生！
    res = a;
    return res;
  } catch (e) {
    console.error("subでエラーが発生しました", e); // キャッチされる
    throw e; // これだけ追記
  }
}

async function func1() {
  try {
    console.log("func1が呼ばれました");
    const result = await sub(); // この関数内でエラー発生
    console.log("resultにsubの結果を格納しました");
  } catch (e) {
    console.error("func1でエラーが発生しました", e); // キャッチされる！
  }
}

func1();
```

実行結果
![キャッチされる.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652834/7d6e93b1-8376-220a-7249-c6ff6fe735b1.png)



## 参考

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/throw

https://nipo-plus-doc.sndbox.jp/tech/asyncawaiterror/index.html
mruby-fatfsを作ってみた

EYEFIカードを制御できる、eyefi-configはFreeBSDにも対応しているようなのですが、バグっているので作り直す事にしました。

Cでも書けるのですが、amd64だけではなくmipsなどでも動かしたいので、mrubyで処理する事を考えました。

EYEFIのインターフェースはFAT32のファイルの読み書きなので、FATを処理する軽量のライブラリFatFsを使うことにしました。

https://irtos.sourceforge.net/FAT32_ChaN/doc/00index_j.html

これをラップしてファイルの作成と読み出しだけ実装してみました。

https://github.com/yamori813/mruby-fatfs

bare metal用のFatFsのmrbgemsを作られている方がいましたが、ちょっと違うので、別に作りました。

mruby-ioに継承する方法もあるのかもしれませんが、よく分からなかったので必要な機能だけ作りました。

このmrbgems入れてビルドしたmrubyでEYEFIカードからMACアドレスを拾ってみます。

```ruby
f = FatFs.new "/dev/da0s1"

EYEFI_BUF_SIZE = 16384

MAC_ADDRESS = 1

eyefi_buf = f.read "0:EYEFI/RSPC"
seq = eyefi_buf[0] | (eyefi_buf[1] << 8)
seq |= (eyefi_buf[2] << 16) | (eyefi_buf[3] << 24)

p seq

if seq == 0xffffffff
  seq = 0x1234
end

eyefi_buf = Array.new(EYEFI_BUF_SIZE)
eyefi_buf[0] = 0x6f
eyefi_buf[1] = MAC_ADDRESS
f.create "0:EYEFI/REQM", eyefi_buf

seq += 1

eyefi_buf[0] = seq & 0xff
eyefi_buf[1] = (seq >> 8) & 0xff
eyefi_buf[2] = (seq >> 16) & 0xff
eyefi_buf[3] = (seq >> 24) & 0xff
f.create "0:EYEFI/REQC", eyefi_buf

sleep(2)

eyefi_buf = f.read "0:EYEFI/RSPC"

rspseq = eyefi_buf[0] | (eyefi_buf[1] << 8)
rspseq |= (eyefi_buf[2] << 16) | (eyefi_buf[3] << 24)

if seq == rspseq
  eyefi_buf = f.read "0:EYEFI/RSPM"
  printf "%d %02x:%02x:%02x:%02x:%02x:%02x\n", eyefi_buf[0], eyefi_buf[1],
    eyefi_buf[2], eyefi_buf[3], eyefi_buf[4], eyefi_buf[5], eyefi_buf[6]
end
```
eyefi_buf[0]が6でeyefi_buf[1]以降の6バイトがMACアドレスです。
Salesforceのテーブル（オブジェクト）について

# 概要

- Salesforceのテーブル（オブジェクト）について簡単にまとめる。

# 内容

- DBで言うテーブルのことを、Salesforceではオブジェクトと言う
- DBで言う行のことを、Salesforceではレコードと言う
- DBで言う列のことを、Salesforceではフィールドと言う

| DB（MySQLなど） | Salesforce |
| --- | --- |
| テーブル | オブジェクト |
| 行 | レコード |
| 列 | フィールド |
| カラム | 項目 |

- オブジェクトは主に2種類有るらしい
    - 標準オブジェクト：Salesforceを起動した時に作成され、設定されるオブジェクトのこと。（laravelでいうところのusersテーブルとかmigrationsテーブルとかのデフォルトテーブルみたいな感じ・・？）
    - カスタムオブジェクト：Salesforceのユーザーが自分たちで作るオブジェクトのこと。（laravelでいうところのエンジニアがマイグレーションファイルを記入してマイグレートして作成するテーブルみたいな感じ・・？）

# 参考文献

https://developer.salesforce.com/docs/atlas.ja-jp.object_reference.meta/object_reference/sforce_api_objects_list.htm
https://developer.salesforce.com/docs/atlas.ja-jp.object_reference.meta/object_reference/sforce_api_custom_objects_list.htm
JavaScriptでA-Zの羅列を楽に作る方法

エクセル形式が関わる案件でたまに使うんだけどちょくちょく忘れるので備忘録

`String.fromCharCode`を使う。これは文字コードのnumberをstringに変換してくれる
例えば`String.fromCharCode(0x41);`とすると"A"が出てくる。
これをfor文で回してあげる
```js:index.js
for(let i = 0x41; i <= 0x5A; i++){
  console.log(String.fromCharCode(i))
}
```
出力
```
A
B
C
D
...
```
小文字が欲しければ0x61~0x7Aを見てあげればいい

ただしこの手法はひらがなには使えない。
0x3041: ぁ
0x3042:　あ
0x3043: ぃ
0x3044: い
0x304B: か
0x304C: が
のように小文字や濁点付き文字がごっちゃに出てくる。この場合素直にあ~んまで打った方が早いだろう。
パーシャルのオプションを使うには

# エラーになる
```html
.
.
.
<%= render '*****/******', locals: {variable: @user} %>
.
.
.
```
```undefined local variable or method `variable' for #<ActionView::Base:********>```

どうしてローカル変数を設定したが、定義されていないと書かれてある。

# ドキュメントをじっくり読んでみた
```:layoutなどの追加オプションも渡す場合は、:partialオプションも明示的に指定する```必要があります。

### 出典
https://railsguides.jp/layouts_and_rendering.html#:~:text=%3Alayout%E3%81%AA%E3%81%A9%E3%81%AE%E8%BF%BD%E5%8A%A0%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%82%E6%B8%A1%E3%81%99%E5%A0%B4%E5%90%88%E3%81%AF%E3%80%81%3Apartial%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%82%E6%98%8E%E7%A4%BA%E7%9A%84%E3%81%AB%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B%E5%BF%85%E8%A6%81%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82

# 修正
```html
<%= render partial: '******/********', locals: {variable: @user} %>
```

成功！

# 感想
しっかり使うときは公式のドキュメントを読んでおく必要がある。
同じビューで変数だけを変えたいときはパーシャルは便利だ。
Outlook メール送信待機

:::note info
メールを送信する際に、よーく確認したにも関わらず送信後に誤りに気付くことがある。送信を一定時間待機すれば、ある程度防げるのではないか。
①[ファイル]→[仕分けルールと通知の管理]
②[仕分けルール]→[送信メッセージにルールを適用する]→[次へ]
③[次へ]この仕分けルールは全ての・・・・→[はい]
④[ステップ1]指定した時間分後に配信するにチェック→[ステップ2]指定した時間をクリック
⑤配信時間を指定→[OK]→[次へ]→[次へ]
⑥仕分けルールの名前を指定→[完了]→[OK]
以上
:::
python3、mpmathを用いて、自然対数の底eを求めるテスト


python3、mpmathを用いて、自然対数の底eを、求める

```e.py
#!/usr/bin/python3
import mpmath
mpmath.mp.dps=10000

kaijou = 1
number = 1000
napier = mpmath.mpf('1.0')
 
for i in range(1,number+1):
  kaijou *= i;
  napier += mpmath.mpf('1.0') / kaijou;
 
print("計算結果 e =",end='')
print(napier)
print("mpmath.e =",end='')
print(mpmath.e)
```
Unity CatalogによるデータロードでのCOPY INTOの活用

[Use COPY INTO to load data with Unity Catalog \| Databricks on AWS](https://docs.databricks.com/ingestion/copy-into/unity-catalog.html) [2022/8/17時点]の翻訳です。

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

COPY INTOでサポートされているソースやファイルフォーマットからUnity Catalogのマネージドテーブル、外部テーブルにデータを取り込む際にCOPY INTOを使用することができます。Unity Catalogでは、生データに対するセキュアなアクセスを設定するための新たなオプションを追加しており、クラウドオブジェクトストレージにあるデータにアクセスするためにUnity Catalogの外部ロケーションやストレージ資格情報を使うことができます。

# Unity CatalogテーブルへのCOPY INTO

3レベルの識別子(`<catalog_name>.<database_name>.<table_name>`)を用いてUnity Catalogのテーブルを指定することができます。現在のクエリーやノートブックにおけるデフォルトのカタログやデータベースを設定するために、`USE CATALOG <catalog_name>`や`USE <database_name>`を使うことができます。

既存のテーブルにCOPY INTOを行いたい場合には、テーブルを格納するカタログとデータベースに対する`USAGE`権限と、当該テーブルに対する`MODIFY`権限が必要になります。

[一時資格情報](https://docs.databricks.com/ingestion/copy-into/temporary-credentials.html)が設定されたクラウドオブジェクトストレージロケーションを含む、あなたがアクセスできるソースロケーションからCOPY INTOを実行することができます。

# 外部ロケーションからのデータのロード

Unity Catalogの外部ロケーションからデータをロードするには、当該ロケーションに対する`READ FILES`権限が付与されている必要があります。外部ロケーションの権限は指定されたロケーション配下にあるすべてのネストされたディレクトリに適用されます。

例えば、URL `s3://landing-bucket/raw-data`で定義される外部ロケーションへのアクセスが可能な場合、以下のコマンドは適切です:

```sql:SQL
COPY INTO landing_table
FROM 's3://landing-bucket/raw-data'
FILEFORMAT = PARQUET;

COPY INTO json_table
FROM 's3://landing-bucket/raw-data/json'
FILEFORMAT = JSON;
```

この外部ロケーションに対する権限は、指定されたロケーションの上位レベル、同レベルのディレクトリに対してはいかなる権限も付与しません。例えば、以下のコマンドのいずれも適切ではありません:

```sql:SQL
COPY INTO parent_table
FROM 's3://landing-bucket'
FILEFORMAT = PARQUET;

COPY INTO sibling_table
FROM 's3://landing-bucket/json-data'
FILEFORMAT = JSON;
```

# データにアクセスするためのストレージ資格情報の指定

データ取り込みに使用されるディレクトリに対しては、外部ロケーションを用いて明示的に権限を設定することをお勧めします。また、COPY INTOは、データにアクセスするためにUnity Catalogのストレージ資格情報をサポートしています。`READ FILES`権限は、ストレージ資格情報でアクセスすることができるすべてのクラウドオブジェクトストレージロケーションからのCOPY INTOを用いたデータの取り込みを行うためのアクセス権を付与します。ストレージ資格情報は外部ロケーションよりも広範な権限を持つ場合があるので、ストレージ資格情報へのアクセスを許可する際には注意して使用してください。

以下のサンプルでは、ソースデータへのアクセスを提供するためにUnity Catalogのストレージ資格情報を用いて、S3やADLS Gen2からデータをロードします。

```sql:SQL
COPY INTO my_json_data
FROM 's3://landing-bucket/json-data' WITH (
  CREDENTIAL `bucket-creds`
)
FILEFORMAT = JSON;

COPY INTO my_json_data
FROM 'abfss://container@storageAccount.dfs.core.windows.net/jsonData' WITH (
  CREDENTIAL `adls-creds`
)
FILEFORMAT = JSON;
```

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
Xojo Web アプリで CurrentWorkingDirectory を調べる

Xojo でアプリを作成する場合、アクセストークンなどをハードコーディングするのではなくて設定ファイルを別に置きたいけれども、さて設定ファイルはどこに置けばいいかな？

Xojo は デスクトップ・Webアプリ・モバイルアプリが作成できる。
プラットフォームも  Win/Mac/Linux(PC)/Linux(RaspberryPi)/iOS/Cloud などもある。

すべてを網羅するのは難しいだろうが、Webアプリの場合の環境を調べる。

Webアプリもデバッグ実行・スタンドアロン実行・cgi実行などがあるが今回は検証できたもののみ。

# 環境

- Xojo 2019 Ver3.2
- Windows10 Pro 上でIDEを使用
 
# プログラム

WebPage インターフェースに TextField と ボタンを配置

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/88cf6733-6ce9-b332-51b5-7a49ddd76d60.png)


ボタンに以下のアクションを割り当てる


```
var f as Folderitem
f= SpecialFolder.CurrentWorkingDirectory
TextField1.Text=(f.NativePath())
```

これを書いたアプリ`test`を使って検証


# 実行結果



## Windows10 デバッグ実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/144a02e7-ea5f-3895-3154-b38c457af2b4.png)

結果：` C:\Program Files\Xojo\Xojo 2019r3.2\ `

Xojo をインストールしたフォルダになりました。

## Windows10 スタンドアロン実行

ダブルクリックして実行した場合


結果：`C:\Users\<ユーザ名>\Documents\XojoProjects2019r32\Builds - test\Windows 64 bit\test\`

ビルドした test.exe をダブルクリックしての実行です。

これは test.exe を置いた場所になりました。




## Linux スタンドアロン実行

結果：'/home/nanbuwks/xojoweb/'


'/home/nanbuwks/xojoweb/'
 のディレクトリから、

` /home/nanbuwks/xojoweb/test/test --port=8092  --Logging /var/log/xojo/xojoweb.log  &`

というコマンドで実行している。

これはプログラムファイルを置いた位置ではなく、プログラムを呼び出発行したシェルのカレントディレクトリになるようだ。
古いiOSでのLet's Encrypt証明書の対応方法

iOS 9以前が入ったiPhone、iPadでは[Let's Encrypt](https://letsencrypt.org/)証明書を利用したhttpsのWebサイトはエラーになって見ることができません。
これはLet's Encryptのルート証明書DST Root CA X3の有効期限(2021年9月30日)が切れているためです。

[参考] https://letsencrypt.org/ja/docs/dst-root-ca-x3-expiration-september-2021/

下記はいずれかの方法でLet's Encrypt証明書に対応できます。

## iOS側で対応する場合
iOSのルート証明書を更新することでLet's Encrypt証明書の対応が可能です。

[「Let's Encrypt」](https://letsencrypt.org/certificates/)の証明書関連のページから[ISRG Root X1のルート証明書](https://letsencrypt.org/certs/isrg-root-x1-cross-signed.pem)をダウンロードして開くと、iOSのプロファイルでインストールできます。
このルート証明書も「Let's Encrypt」で署名されているためエラーが発生する可能性があります。
ルート証明書をインストールするとiPhone、iPadのSafariでLet's Encrypt証明書を使ったhttpsのWebサイトを見ることができるようになります。

[参考] https://www.sillyfrog.com/ios-9-lets-encrypt

## Webサーバー側で対応する場合
利用者ではなくサービス提供者の場合の方法です。
Webサーバーの設定で、古いiOSでアクセスが来たときにhttpへリダイレクトします。
httpアクセスでも問題無いサイトの場合に有効です。

以下は「.htaccess」ファイルの例です。

```apache:.htaccess
RewriteEngine On

RewriteCond %{HTTPS} on
RewriteCond %{HTTP_USER_AGENT} ((iPhone|iPad;(|\ U;)\ CPU)\ OS\ (9|8|7|6|5|4|3)_)
RewriteRule .* http://%{HTTP_HOST}%{REQUEST_URI} [R,L]

RewriteCond %{HTTPS} off
RewriteCond %{HTTP_USER_AGENT} !((iPhone|iPad;(|\ U;)\ CPU)\ OS\ (9|8|7|6|5|4|3)_)
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
```

httpsアクセスで、WebブラウザのUser-AgentがiOS 9以前のSafaiの場合はhttpにリダイレクトしています。
それ以外のWebブラウザでhttpアクセスの場合はhttpsにリダイレクトしています。
【Ruby】例外処理の基礎について

例外についてあまり使う機会がなかったので、簡単にまとめておきます。

# 例外とは
異常が発生したことを表すオブジェクト。
使用例としては、実行時に予想外のエラーが発生してプログラムが停止しないように、エラーを検知してプログラムの続きができるようになります。

# 例外を発生させる
`Kernel.#raise`を使用すると、意図的にエラーを発生させることができます。
第一引数には例外クラスを指定する。第二引数には例外メッセージを指定します。

```ruby
raise StandardError
raise StandardError, "error" #StandardError: error!
raise StandardError.new("error")
# それぞれの書き方があります
```

# 例外クラスの種類
上の例では`StandardError`を発生させましたが、Rubyで定義されている例外クラスを用いていろいろなErrorを発生させることができます。

```ruby
raise StandardError, "error!" # => StandardError: error!
raise RuntimeError, "error!"  # => RuntimeError: error!
raise SyntaxError, "error!"   # => SyntaxError: error!
```

例外の種類については[組込みライブラリ-例外](https://docs.ruby-lang.org/ja/latest/library/_builtin.html)を参照してください。

また、エラーメッセージだけを記載して定義することができますが、この時のエラーの補足は`RuntimeError`になります。

初期値は`RuntimeError`だということを覚えておきます。
``` ruby
raise "error!" # => RuntimeError
```

# beginを使ってエラーを取得


`begin~rescue`でエラーが発生する可能性のある処理を定義
`rescue~end`でエラーが発生した時の処理を定義します。

```ruby
begin
  # 実行するコード定義
rescue
  # エラー時の処理を定義
end
```
また、`else`と`ensure`を定義して、エラーが発生しなかった時の定義と、エラーに関わらず実行される処理を定義することができます。

```ruby
begin
  # 実行するコード定義
rescue
  # エラー時の処理を定義
else
  # エラーが発生しなかった時の処理を定義
ensure
  # エラーに関わらず実行される処理を定義
end
```

簡単な例を挙げます。


```ruby
begin
  p 3/3
rescue
  p "error!"
else
  p "no error!"
ensure
  p "プログラムが処理されました"
end

# => 1
# => "no error!" 
# => "プログラムが処理されました"

```


# rescureでエラーの情報を取得

`rescure =>　変数名`でエラーの情報を取得することができます

```sample.rb
begin
  p 3/0
rescue => e
  p e.class     # 例外の種類を出力
  p e.message   # 例外のメッセージを出力
  p e.backtrace # 例外が発生した位置情報を出力
end

# => ZeroDivisionError
# => "divided by 0"
# => ["sample.rb:2:in `/'", "sample.rb:2:in `<main>'"]
```

# rescueでエラー毎に例外クラスを指定
`rescue`の後に、例外のクラスを指定して、それぞれの例外のケースに合わせて処理を変えることもできます。
 ⇨@okuramasafumiさんのコメントより修正
```ruby
begin
  p 3/0
rescue ZeroDivisionError
  puts "ゼロでは割れません"
rescue StandardError
  puts "エラーが発生しました"
end
# => "ゼロでは割れません"が表示される
```
また、上から順番に定義した例外クラスとマッチしたものから止まるようになります。

```ruby
begin
  p 3/0
rescue StandardError
  puts "エラーが発生しました"
rescue ZeroDivisionError
  puts "ゼロでは割れません"
end
# => "エラーが発生しました"が表示される
```


# raiseとbeginを組み合わせてみる
raiseでは例外を発生させることができるとお伝えしました。
begin~rescueに定義して実際に例外が発生して、取得できているか確認します。


```ruby
begin 
  raise ZeroDivisionError.new("Error!")
rescue => e
  p e.class      #=> ZeroDivisionError
  p e.message    #=> "Error!"
  p e.backtrace  #=> "sample.rb:2:in `<main>'"
end
```
# Retryで処理を再実行
`rescue~end`で`retry`を使用することで処理を再度実行することができる。
 ⇨@okuramasafumiさんのコメントより修正

``` ruby
count = 0

begin
  p 3/0
rescue
  p count += 1   
  if count < 2
    retry
  end

  p "error"
end

# => 1
# => 2
# => "error"
```

# 参照
- [【Ruby入門】例外処理の使い方まとめ](https://26gram.com/ruby-exception)
- [【Ruby】例外処理まとめ](https://qiita.com/k-penguin-sato/items/1a6c8096effccb19565a)
Go言語クリーンアーキテクチャ例

**やりたいこと**
ハンドラー⇒ユースケース⇒リポジトリのようなプロセスをクリーンアーキテクチャな作りにしてテストをしやすくします。

**サンプル**
あくまで例となりますので１ファイルに纏めております。

```golang
// main.go
package main

import "fmt"

// handlerパッケージに置くイメージ
type Handler struct {
	uc UsecaseIF
}

type HandlerIF interface {
	HandlerProcess()
}

func NewHandler(
	uc UsecaseIF,
) HandlerIF {
	return &Handler{uc: uc}
}

func (h *Handler) HandlerProcess() {
	fmt.Println("Handler Process")
	h.uc.UsecaseProcess()
}

// Usecaseパッケージに置くイメージ
type Usecase struct {
	db DBIF
}

type UsecaseIF interface {
	UsecaseProcess()
}

func NewUsecase(
	db DBIF,
) UsecaseIF {
	return &Usecase{db: db}
}

func (u *Usecase) UsecaseProcess() {
	fmt.Println("Usecase Process")
	u.db.DBProcess()
}

// DBパッケージに置くイメージ
type DB struct {
	DBIInformation string
}

type DBIF interface {
	DBProcess()
}

func NewDB(
	di string,
) DBIF {
	return &DB{DBIInformation: di}
}

func (d *DB) DBProcess() {
	fmt.Println("DB Process")
	fmt.Println(d.DBIInformation)
}

func main() {
	// New
	d := NewDB("DB情報一式")
	u := NewUsecase(d)
	h := NewHandler(u)
	// 処理開始
	h.HandlerProcess()
}
```

**main実行結果**
Handler Process
Usecase Process
DB Process
DB情報一式

**ポイント**
structのuc,dbをインターフェスにすることでモックに置き換えやすくしている。
String.formatの使い方まとめ



文字列を実装する中で文字列操作をする際にString.formatで実装する機会があったので備忘録。

String, Int, Doubleをそれぞれ使うように作成。
サンプルのユーザーデータは以下

```kotlin
data class User(
    // ニックネーム
    val nickname: String = "", 
    // 年齢
    val age: Int = 0,
    // 身長(cm)
    val height: Int = 0,
    // 足のサイズ(cm)
    val shoeSize: Double = 0.0,
)

```


実際の表示確認は以下

```kotlin

fun main(args: Array<String>) {   
    val jack = User(nickname = "ジャック", age = 27, height = 172, shoeSize= 26.5)

    print(String.format("ニックネーム:%s", jack.nickname))
    // ニックネーム:ジャック
    print(String.format("年齢:%d歳", jack.age))
    // 年齢:27歳
    print(String.format("身長:%dcm", jack.height))
    // 身長:172cm
    print(String.format("足のサイズ:%.1fcm", jack.shoeSize))
    // 足のサイズ:26.5cm
}

```


【メモ】
文字列Stringは「%s」
Int10進数は「%d」

少数が厄介で、**「%.1f」と設定しているが、小数点第一位まで表示**を定義している

12.34みたいな小数点第二位までなら「%.2f」になる。

【参考文献】
https://java-code.jp/173

https://www.sejuku.net/blog/14466
macのusキーボードでイコールを打ちやすくする

左コマンドとシングルクォートでイコールを打てるようにしました

karabinerをインストールして以下のファイルを作成し、karabinerを開いてComplex ModificationsからAdd ruleをしてenableにすれば反映される

```~/.config/karabiner/assets/complex_modifications/original-setting.json 
{
  "title": "自作の設定",
  "rules": [
    {
      "description": "左コマンドとシングルクォートでイコール",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "quote",
            "modifiers": {
              "mandatory": [
                "left_command"
              ]
            }
          },
          "to": [
            {
              "key_code": "equal_sign"
            }
          ]
        }
      ]
    }
  ]
}
```

参考記事
https://knowledge.sakura.ad.jp/23355/
https://qiita.com/s-show/items/a1fd228b04801477729c
Apacheを再起動したのにphp.iniの設定が反映されない

以前にも詰まったと思うけどまたやったので備忘。

```php.ini```の設定を変えたので反映させようと
```
$ sudo systemctl restart httpd
```
をやったのに```phpinfo();```で見たときに設定変更が反映されてない。
[以前](https://qiita.com/Kokusui/items/42ee26d7e8ad1a114b12)確認した際に、PHPがモジュール版でなくFPM/CGIで動いてたというのを思い出し、
```
$ sudo systemctl restart php-fpm
```
これで無事設定変更できた。ところでいつもやらかすのだが、
✕ ```sudo systemctrl restart httpd```
◯ ```sudo systemctl restart httpd```
「コマンドが見つかりません」と言われて気づくというね…。
コマンドでネットワークの状態を知る

ネットワークに障害が発生したときに、CLI(Command Line Interface)上で```ネットワークの状態を確認するコマンド```が```ネットワーク・コマンド```です。
Windowsだとコマンドプロンプト、Unix系だとTerminalで利用できる。

# コマンドの種類
### ```ipconfig```
IPアドレスやサブネットマスク、デフフォルトゲートウェイなど、```ネットワークに関する設定を表示```するコマンドです。
UNIX系では```ifconfig```と入力する。

### ```ping```
特定のIPアドレスに対する疎通を確認するコマンドです。
```ICMP(Internet Control Message Protocol)```という制御パケットを送受信して、```お互いに疎通を確認```できます。

#### 気づき
応答が返って来ればレイヤー３までは問題がないことがわかる。のか。

### ```tracert```
特定のIPアドレスに対する確認コマンドです。
```どのような経路を辿って、そのIPアドレスまで到達しているか````を確認できます。
なおUNIC系では```traceroute```と入力する。

### ```arp```
ARPテーブルの情報を表示するコマンドです。
```同じネットワークにいるコンピュータのMACアドレスを確認```することができます。

### ```nslookup```
DNSによる名前解決を確認するコマンドです。
```DNSサーバーで名前解決ができているかを確認```するために使用します。

### ```netstat```
```コネクション情報(接続されているIPアドレスやポート番号)をルート情報を表示```するコマンドです。
送受信したパケット数やエラーパケット数など、NICの統計情報も表示できます。

#### 気づき
```netstat```を入力してみたが、少しずつIPアドレスが表示された。


# 出典
https://www.sbcr.jp/product/4797386660/

# 感想
これらを実践的に使ってみたい。
忘れた頃にまた書くだろう。
【Mysql】PODの使い方

# PDOの使用

## DB接続
```php
$dbname = 'vocaloid';
$host = 'localhost';
$user = 'root';
$password = 'password';

// データベースとの接続
try {
    $pdo = new PDO('mysql:dbname='.$dbname.';host='.$host.';charset=utf8mb4', $user, $password);
}   catch (PDOException $e) {
    echo "データベース接続エラー　：".$e->getMessage();
}
```

## 使用方法
１. DBファイルを読み込む
```php
// DB接続ファイルを読み込む
require("../detabase/dbconnect.php");
```
<br>

２. prepareで処理内容を記載
```php
$stmt = $pdo->prepare('SELECT * FROM users WHERE userid=?');
```
<br>

３. executeで実行
```php
$stmt->execute(array("12345"));
```
:::note info
```php
$id = $stmt->execute(array("12345"));
```
上記のようにfetchを省略することも可能です。
:::
<br>

４. fetchで値を取り出す
```php
$user = $stmt->fetchAll(PDO::FETCH_ASSOC);
```
:::note info
fetchを使うと余計な値を含まずに返してくれたり、希望する連想配列で返してくれたりもできる。
デフォルトはFETCH_BOTH
:::
>FETCH_BOTH：【配列のキー】カラム名＆連番  
FETCH_ASSOC：【配列のキー】カラム名のみ  
FETCH_KEY_PAIR：指定した2つのカラムを「キー／値」のペアの配列にする  
FETCH_COLUMN：指定した1つのカラムだけを1次元配列で取得  

:::note info
FETCH_ASSOCがおすすめ。
:::
Gitでデフォルトブランチの名前を変更する方法

Githubを使っていると、このように言われる。
```
echo "hoge" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:hoge/fuga.git
git push -u origin main
```
この中の`git branch -M main`という箇所が今回取り上げる部分になる。

以前は、デフォルトブランチの名前は`master`だったのだが、これが良くないからということで変更になった。
そのため、デフォルトブランチの名前を`master`から最初に変えてねというものなのだが、毎回これをやるのが面倒くさい。

# グローバルの設定を変えてしまう
私の場合はデフォルトブランチ名は`development`を使用するのだが、
そんな時には、こうするとよい。

```
git config --global init.defaultBrach development
```

これで次回から`git init`するとデフォルトのブランチが`development`になる。
営業マンから人事に転身して思ったこと

初めまして！

開発会社で働く、ひよっこの人事です。

ひよっこっていうのは
社会人経験の中で、人事職に就くのは未だ半年経っていないためです笑

これから色々勉強のためにQiitaで
多くのエンジニアやプロジェクトに関わる人と繋がれたら良いなあと思い、ブログ初めてみました。

技術的なことは恥ずかしながら、ここに居る方よりも未熟なため
個人的にIT業界きて6ヶ月感じたことや思ったことをここに綴りながら、
客観的な会社の雰囲気を伝えていけたら良いなと考えております:writing_hand::relieved::dizzy:



それでは、ぜひこの記事が多くの方の目に留まってもらえるよう、書いていきたいと思います〜:fist:
宜しくお願いいたします。
iOSアプリの配信手段まとめてみた

## はじめに
Apple Developer Enterprise Programの更新がほぼほぼの企業でできなくなり
一般企業でのin houseなどの配信が難しくなりました。
ただ、テスト端末へのアプリ配信はアプリのデバッグ用に必要のため
アプリ配信などで現状使用している配信手段を整理してみます
※Apple Developer Program については加入前提としています

## Test Flight
Apple公式の配信手段で、[AppStoreConnect](https://appstoreconnect.apple.com/)にアプリを作成しArchiveしたビルドデータをストアに送ることで使用可能
公式だけあり、クラッシュを含む機能が便利
また審査も入るため、ストアリリース前にリジェクト内容があった場合の確認が可能

### メリット
- Apple公式の配信手段
- Storeにデータをアップロードすることで使用が可能
- ストア未公開状態でも使用可能
- ストアリリース前にリジェクト理由を知ることができる
- メールアドレスのみで配信可能
    - メールアドレスの種類をグループとして管理が出来、まとめての送信が可能
    - 配信上限は10,100
        - 内部テストユーザー 100名（審査前のテスト可）
        - 外部テストユーザー 10,000名（審査後のみテスト可）
- テスター端末からフィードバックを送ることで、クラッシュや現象のスクリーンショットをもらうことが可能


### デメリット
- 審査が入る
    - バージョン変更 (1.0 → 1.0.1など) ごとにストア申請並の審査が入る※同バージョンのbuildNumber違いは審査がほぼ無い
    - 非公開APIや落ちるようなアプリは審査で落とされる可能性が高いので、実験的アプリでは使用しづらい
- コマンドで送ることも可能でjenkinsなどを使って自動化も可能だが、配信についてはAppStoreConnectにアクセスする必要有
- テスト期間が有り、配信開始から90日のみ
- ストアに送信する関係上App Identifierを作成する必要有

## FirebaseDistoribution
[FireBase](https://firebase.google.com/)の配信手段
Ad Hocのipaファイルを作成しアップロードすることで配信が可能
Ad Hocのため、テスト用の端末を事前にすべて登録をしてProvisioningProfileを作成してビルドする必要が有る
CLIが用意されておりコマンドで操作し配信まで自動化することが可能

### メリット
- 審査なしでアップロード後すぐに配信が可能
- 証明書の期限は有るが、テスト可能な日数の期限は無い
- Crashlyticsなどの機能を入れてテスターのクラッシュ情報を確認することが可能
- テストアプリなどもipaさえ作れれば配信が可能
- Gmailアドレスのみで配信可
    - メールアドレスのグループ化をして管理が出来、まとめての送信が可能
- CLIがあり、配信まで自動化も可能
- App Identifierをワイルドカードにしても使用可能
    
### デメリット
- 基本はAd Hoc配信になるため、テスト端末をすべて登録しておく必要有
- Crushを知るためにCrashlyticsなどを入れる必要があり、アプリサイズが若干大きくなる
- テスター用にGoogleアカウントの作成が必要
- テスター端末でプロファイルのインストールが必要
- Deviceを登録する関係上最大で各デバイス（AppleTV,iPad,iPod,AppleWatch,iPhone）で100ごと

## 最後に
ここに記載した配信方法に関しては、現状使用しているものに絞っています
この他のアプリ配信方法で言えば[deploygate](https://deploygate.com/)や
Webページを用意してAd Hoc用のPlistとipaをアップロードし配信する方法もあります。

:::note warn
Webページを用意する系（一般的なAd Hoc）の配信方法は、インストール中に途中で止まり一生消せないアプリとして存在するバグなどが昔に多数起こって苦い思いをしたので自分からはオススメし辛いです。
:::

## 公式リンク
- [AppStoreConnect](https://appstoreconnect.apple.com/)
- [FireBase](https://firebase.google.com/)
- [DeployGate](https://deploygate.com/)
【Typescript】型 'string | undefined' の引数を 'string' のパラメーターに割り当てることができません。を解決したい

# はじめに
環境変数を読み込むと型がstring | undefined となり、このまま関数に渡そうとするとタイトルのエラーが出ました。
エラーで検索をかけると型定義ファイルを自作する記事が多かったので試していたのですが、もっと簡単に書けたのでまとめます。


# 解決方法
envを読み込むタイミングで型の絞り込み(narrowing)をします

```
const HOGE = process.env.REACT_APP_HOGE ?? "";
```

# おわりに
思ったより時間をかけてしまいました。しばらくはnarrowingにお世話になりそうです
ElasticBeanstalkのUnknown or duplicate parameter: NodeCommandの対処法

昨日、下に貼ったこちらの動画と公式のドキュメントを基にnode.jsのアプリケーションをAWS Beanstalkでデプロイすることを試みた。

https://www.youtube.com/watch?v=0oIcGPK8mQE

https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/create_deploy_nodejs_express.html

ということで上の資料ではエラーが起きてしまうところの対処法を先に記述する。
その後、全体の流れを記述する。

```
C:\Users\yusuk\nodejs-project>eb deploy
Creating application version archive "app-c698-230118_133959827133".
Uploading nodejs-project/app-c698-230118_133959827133.zip to S3. This may take a while.
Upload Complete.
2023-01-18 04:40:02    INFO    Environment update is starting.      
2023-01-18 04:40:07    ERROR   "option_settings" in one of the configuration files failed validation. More details to follow.
2023-01-18 04:40:07    ERROR   Unknown or duplicate parameter: NodeCommand 
2023-01-18 04:40:07    ERROR   Failed to deploy application.        

ERROR: ServiceError - Failed to deploy application.
```

しかし、このようなエラーを起こし、昨日はデプロイ出来なかった。

そして、今日色々ドキュメントを漁っていると原因がわかった。

https://stackoverflow.com/questions/61782952/unknown-or-duplicate-parameter-nodecommand

こちらで投稿されていた質問は私のエラー内容と同じだったので、この投稿に貼られていたURLを読んでいくと以下のページがあった。
要約すると、NodeCommandを含んだconfigファイルはレガシーオプションなので新しいProcfileに置き換えろということであった。

詳しく述べると、プロジェクトファイル直下に作成した .ebextensions フォルダー内にProcfileというフォルダを作成し、その中に以下の記述をすれば良い。

```
web: npm start
```

https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/nodejs-configuration-procfile.html

こうすることで他は動画ないし、公式のドキュメントに従えばかんすすぎるアプリケーションのデプロイは出来る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2971002/c054c1d9-a193-0a17-584d-354243280f58.png)

少し、長くなったので最初からのデプロイの仕方は別に記事で公開する。