OmniAICreator/Qiita-1.07M huggingface dataset:
RaspberryPiを購入してから自分のPCで遠隔操作できるようになるまで

#やること
###　目次
* 購入する前に(SDカード購入で気を付けること)
* OSのインストール
* ラズパイ初期設定
* 遠隔操作設定(TeamViewer & SSH)


こちらの記事では、RaspberryPiを購入してから、自分のPCで同一LAN内からSSHでいじれるようになるまでを書きます。
本当はRaspberryPiとESPを使って、自宅のエアコンを外出先から操作できるように書きたかったのですがあまりにも長くなりそうなので、ある程度区切ってそれぞれ記事にして書こうと思います。

<dl> 
  <dt> 他記事 </dt>
    <dd> [記事1]() </dd>
    <dd> [記事1]() </dd>
    <dd> [記事1]() </dd>
    <dd> [記事1]() </dd>
</dl>




# 購入する前に (SDカード購入で気を付けること)
RaspberryPiでは本体に埋め込まれているチップにブートローダが搭載されています。そのブートローダがSDカードに書いてあるOSを読み込むのですが、SDカードがFAT32形式でないと読み込めません。SDカードは容量レンジごとに名前とフォーマット形式が決まっています。

| SDカード容量 | SDカードの名前 | デフォルトフォーマット形式 |
|:----------:|:-:|:-:|
| ~2GB        |  SDカード    | FAT(FAT16)|
| 4GB~32GB    |  SDHCカード  | FAT32     |
| 48GB~       |  SDXCカード  | exFAT     |

デフォルトと書いたのは、無理やり他のフォーマット形式でもフォーマットできるからです。しかし私がRaspberryPi(4)で126GBのものをFAT32形式でフォーマットして試してみましたがうまく行きませんでした。ちゃんと調べれば原因がわかるのだろうとは思いますが、購入してから作業するまでできる躓くところ減らしたいのであればSDHCカードを購入することをお薦めします。





# OSのインストール
自分のPCのにて[公式サイト](https://www.raspberrypi.org/downloads/noobs/)からNOOBSをダウンロードします。ダウンロードしたZipファイルを解凍してでてきたものをSDカードの一番上の階層に全てコピーします。
コピーしたら、SDカードをRaspberryPiに差し込み、起動します。そしたら後は画面の指示に従えのみ。

*NOOBSとはRaspbianをインストールするためのインストーラです。コピーさえしてしまえばマウスとキーボード数回叩けばインストールしてくれます。言語を選ぶ時は日本語でもいいですが、Use English Languageにチェックすることをおすすめします(フォルダ名が日本語だと面倒)

# ラズパイ初期設定
* キーボード日本語入力化　[参照](https://qiita.com/sukinasaki/items/426068d6e87169fa3d88)
* ユーザー名変更 [参照](https://jyn.jp/raspberrypi-username-change/)
* ホスト名変更 [参照](https://qiita.com/naoyukisugi/items/66fd21512da75b437465)
* ルータ設定画面(http://192.168.1.1) へ飛び、ラズパイのローカルIPアドレスを確認しておく。IPアドレスは固定しておくといい。




# 遠隔操作設定(TeamViewer & SSH)
[こちら](https://iot-plus.net/make/raspi/remote-control-using-teamviewer-on-raspbian/) に従ってTeamViewerをインストールします。
これでも遠隔操作は十分ですが、やっぱりSSHで操作するほうがサクサクしているし、ファイルのやり取りもしやすいです。ただ、rootでのログインが必要になった場合、無理やりTeamViewerでできるので両方いれておきます。(SSHでのログインはRootログインを許可しないようにするのでセキュリティ状好ましいため。)

### SSHの設定
初期設定ではSSHの設定が、できない、になっているのでターミナルで `sudo raspi-config` と叩くて出てくるウィザードで設定できます。root権限必要なのでsudoを付けて実行。

* 5 Interfacing Options
* P2 SSH

の順に進み設定できます。(写真等分かりやすい説明は他記事に任せます。)
SSH鍵認証設定は[こちら](https://qiita.com/gotohiro55/items/36a22516de2b381b3c6e)を参照してください。


# 参考サイト
http://denshikousaku.net/raspberry-pi-ip-address-and-open-port
https://nyanonon.hatenablog.com/entry/20180711/1531299090
Node.jsとMeCabで漢字・ひらがな・カタカナ辞書順ソート

Node.js, MeCabを使用した日本語の辞書順ソート用compare関数を実装しました。
漢字、ひらがな、カタカナに対応しています。

`String#localeCompare()` は概ね辞書順に動きますが、濁音半濁音を無視します。
これを補完し、漢字の読みにも対応しました。

コード全体はこちらにおいてあります。

https://gist.github.com/sujoyu/b93e83596e6de9142933ce7cc9cd711b

#必須環境

- Node.js
- MeCab

```
$ npm install is-windows encoding-japanese --save
```

# 使い方
```js
const Comparator = require('./japanese-comparator')

const list = ['b', 'a', '2', '1', '+', '-', '-2', 'あがき', '悪', '赤城']
// get関数は引数なしでも動作しますが、リストを渡してキャッシュを作ったほうが早くなります
const compare = new Comparator().get(list)
console.log(list.sort(compare))
/*
[
  '-', '-2', '+',
  '1', '2',  'a',
  'b', '赤城', 'あがき',
  '悪'
]
*/
```

# 内部の実装

```js
function hiraToKana(str) {
  return str.replace(/[\u3041-\u3096]/g, function(match) {
    var chr = match.charCodeAt(0) + 0x60;
    return String.fromCharCode(chr);
  });
}
```
ひらがなをカタカナに変換します。

```js
const dakuMap = hiraToKana('かが きぎ くぐ けげ こご さざ しじ すず せぜ そぞ ただ ちぢ つづ てで とど はばぱ ひびぴ ふぶぷ へべぺ ほぼぽ')
  .split(/\s/g)
  .reduce((prev, current) => {
    [...current].map(c => {
      prev[c] = current
    })
    return prev
  }, {})
```
濁音半濁音の文字の順序を定義しています。

```js
function compareKana(a, b) {
  if (a[0] === undefined && b[0] === undefined) {
    return 0
  } else if (a[0] === undefined) {
    return -1
  } else if (b[0] === undefined) {
    return 1
  } else if (a[0] === b[0]) {
    return compareKana(a.substring(1), b.substring(1))
  } else if (
    dakuMap[a[0]] && dakuMap[b[0]] && dakuMap[a[0]] === dakuMap[b[0]]
  ) {
    return dakuMap[a[0]].indexOf(a[0]) - dakuMap[a[0]].indexOf(b[0])
  } else {
    return a[0].localeCompare(b[0], 'ja')
  }
}
```
カタカナの文字列同士を比較します。

```js
if (isWindows()) {
  this.detected = Encoding.detect(exec(`echo テキストエンコーディングのテスト | mecab -Oyomi`))
}
...
Encoding.convert(exec(command), {
  from: this.detected,
  type: 'string'
})
```
Windowsでは何も考えずに`mecab`コマンドを叩くと出力が`Shift-JIS`になるので変換しています。

```js
  createCache(list) {
    list = this.preprocess(list)
    const yomiAll = this.kanjiToKana(list.join(this.splitter), true).split(this.splitter)
    console.log(yomiAll)
    list.forEach((str, i) => {
      this.cache[str] = yomiAll[i]
    })
  }
```
`compare`関数が呼ばれるたびに`mecab`コマンドを叩いていると日が暮れてしまうので、
ソートする文字列リストを全結合し、一回だけ`mecab`を叩き、再度分割、結果をキャッシュする仕組みを入れました。

以上です。
AWSへデプロイしてみよう（〜EC2インスタンス作成〜SSH接続 その２）

つづきです。

前回の投稿はこちら。。


## 3.固定IP割り振り
インスタンスを作成した直後はIPアドレスは動的に変化します。つまり、住所がコロコロと変わってしまいます。この状態では、ユーザがアクセスする先がコロコロ変わってしまうため、IPアドレスを固定させます。

画面左上の[サービス]から[EC2]をクリックします。

左のスクロールバーからElastic IPを選択します。

[新しいアドレスの割り当て]ボタンをクリックします。

[割り当て]ボタンをクリックして終了です。

#### <font color="Crimson">※注意</font>

固定IPアドレスはEC2インスタンスと関連付けなければ、課金対象になり料金が発生します。すぐにEC2インスタンスと関連付けましょう。

インスタンスを停止させる場合は[アドレスの解放]も実施しないと課金されます。
　
アクションボタンをクリックし[アドレスの関連付け]をクリックします。

「インスタンス」の項目に今作ったインスタンスを選択して[関連付け]をクリックします。

## 4.ダウンロードしたキーペアへの読み取り権限付与
ダウンロードしたキーペアの秘密鍵（xxxx-key.pem）に、自分のみに読み取り権限を与えます。
秘密鍵（achieve-key.pem）があるディレクトリに移動しましょう。
macの場合、デフォルトでDownloadsフォルダに保存されますので、自分のみに読み取り権限を付与します。

```
cd ~
cd Downloads
chmod 400 xxxx-key.pem
```
## 5.EC2へSSH接続する
EC2とSSH接続をするために、以下のコマンドを実行。
キー名は「xxxx-key.pem」、ユーザ名は「ec2-user」 （デフォルトのユーザ名）です。

```
ssh -i キー名 ユーザ名@パブリックIP
```
成功すれば以下のように表示されます。

```
The authenticity of host 'echeast-1.compute.amazonaws.com (5197)' can't be established.
ECDSA key fingerprint is SHA256:46fzHtG4zGNkyQj/vSXgp1ijxoffTK7qNTfYVZmQkJg.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '52.193.249.209' (ECDSA) to the list of known hosts.


       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|


<https://aws.amazon.com/amazon-linux-ami/2016.03-release-notes/>
6 package(s) needed for security, out of 15 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip ~]$
```
## 6.EC2インスタンスの初期設定
EC2に入った状態で、以下のように管理者権限に切り替える。

```
$ sudo su -
```
管理者権限に切り替えると、ユーザが以下のように変更される

```
[ec2-user@ip-1-250 ~]$ sudo su -
[root@ip-172-31-29-250 ~]# 
```
次にパッケージ管理ソフトウェアのyumを最新にします。

```
$ yum update -y
```
## 7.タイムゾーンなど修正
以下のコマンドを実行してタイムゾーンを変更します。


```
$ ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
$ vi /etc/sysconfig/clock
```
VIMが開いたら下記のように編集します。

```
ZONE="Asia/Tokyo"
UTC=false
```
次にデフォルトで言語がen(English)になっているため、ja(Japan)に変更します。

```
vi /etc/sysconfig/i18n
```
VIMが開いたら下記のように編集します。

```
LANG=ja_JP.UTF-8
```
次にLinuxOSを、使用する国の環境に最適化するための設定をします。

```
vi /etc/cloud/cloud.cfg 
```

VIMが開いたら下記のように編集します。

```
repo_upgrade: none

locale: ja_JP.UTF-8 
```
続いてswap領域を作成します。
サーバを動作させている中で、物理メモリ(RAM)の容量が満杯になった時点で必要になるのがswap領域、、らしいです。

```
$ dd if=/dev/zero of=/swapfile bs=1M count=1024
$ mkswap /swapfile
$ swapon /swapfile
$ vi /etc/fstab 
```

VIMが開いたら下記のように編集します。

```
/swapfile swap swap defaults 0 0 
```

## 8.新規ユーザー作成
デフォルトユーザであるec2-userで開発するのはセキュリティ的に危険であるため、新しくユーザを作成し、今後はそのユーザで開発するようにします。

useraddコマンドでユーザを作成します。

```
$ useradd app -G wheel
$ visudo
```

VIMが開いたら下記のように編集します。

```
 %wheel ALL=(ALL)    NOPASSWD: ALL 
#この行のコメント（先頭にくっついている#のこと）を削除
```
コメントを解除することで、wheelグループに属するユーザは、パスワードを入力する必要がなくなりました。

つづく。。
【初心者向け】覚えて損はないJSによるform系要素の操作をcodepenで説明

普段はほとんどJQueryで書いています。
とても基本的なことですが、大切なことだと思うのでまとめています。
どれもトリガーはclickになっています。

#テキストボックス/テキストエリアの値を取得
valueプロパティでテキストエリアの中身を取得できます。

<p class="codepen" style="height: 365px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-height="365" data-theme-id="0" data-default-tab="html,result" data-user="n-kaminaga" data-slug-hash="joWNQp" data-pen-title="joWNQp">See the Pen <a href="https://codepen.io/n-kaminaga/pen/joWNQp/">
joWNQp</a> by n-kaminaga (<a href="https://codepen.io/n-kaminaga">@n-kaminaga</a>)
on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

#セレクトボックスの値を取得
セレクトボックスもvalueで取得できます。
<p class="codepen" style="height: 365px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-height="365" data-theme-id="0" data-default-tab="html,result" data-user="n-kaminaga" data-slug-hash="joWNQp" data-pen-title="joWNQp">See the Pen <a href="https://codepen.io/n-kaminaga/pen/joWNQp/">
joWNQp</a> by n-kaminaga (<a href="https://codepen.io/n-kaminaga">@n-kaminaga</a>)
on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

#ラジオボタンの値を取得
checkedプロパティで取得ができます。
for文で同じneme属性のラジオボタン全てのチェックの有無を確認します。
<p class="codepen" style="height: 365px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-height="365" data-theme-id="0" data-default-tab="html,result" data-user="n-kaminaga" data-slug-hash="mYPPaE" data-pen-title="mYPPaE">See the Pen <a href="https://codepen.io/n-kaminaga/pen/mYPPaE/">
mYPPaE</a> by n-kaminaga (<a href="https://codepen.io/n-kaminaga">@n-kaminaga</a>)
on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

#チェックボックスの値を取得
checkedプロパティで取得ができます。
チェックボックスは複数選択可能なので、for文で同じneme属性のチェックボックス全てのチェックの有無を確認し、配列にpushしていきます。
<p class="codepen" style="height: 365px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-height="365" data-theme-id="0" data-default-tab="html,result" data-user="n-kaminaga" data-slug-hash="xNVORb" data-pen-title="xNVORb">See the Pen <a href="https://codepen.io/n-kaminaga/pen/xNVORb/">
xNVORb</a> by n-kaminaga (<a href="https://codepen.io/n-kaminaga">@n-kaminaga</a>)
on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
ec-cube4の開発準備

随時更新

## コード規約のチェック
php-cs-fixerの導入
```
composer require --dev friendsofphp/php-cs-fixer
```

コード修正対象の確認
--dry-runオプションを付与する事で、修正対象の一覧が表示される。
```
php-cs-fixer fix --dry-run ./src
```

コードチェック
コードの対象を最後に指定。今回はsrcの中
```
php-cs-fixer fix ./src
```

## EC-CUBEが提供しているコマンド
http://doc4.ec-cube.net/quickstart_cli

## ControllerやEntityの生成コマンドをec-cubeの仕様に合わせたい
プラグインとして提供してくれている。
[EccubeMakerBundle](https://a-zumi.net/eccube4-maker-bundle/)

こちらを使用することで、customizeディレクトリにRepositoryやEntityを自動生成してくれる。
更にgetterやsetterも用意されている！
```
bin/console eccube:make:entity
```
php7.1から「$this」の矛盾の修正がされている！？

phpでは`$this`は特別な意味を持ちますが、
php7.1から変数名として使ったり、値の代入ができないようにきちんとチェックをすように修正されているとの記述を公式のDocumentを見ていて知りました。

むしろ、当たり前のように使っていたからphp7.0まではチェックしていなかったことを知りませんでした…

以下、公式の引用

> PHP において $this は特別な変数という扱いですが、 これが他の場所で変数名として使われていたり再代入されていたりしないことを、 きちんとチェックできていませんでした。 これを修正してきちんとチェックするようになったので、 $this をユーザー定義の変数名として使ったり他の値を再代入したり、 グローバル変数にしたりすることはできなくなりました。


https://www.php.net/manual/ja/migration71.other-changes.php
terraform

# command
- update terraform plugin
    - `terraform init -upgrade`

# trouble shooting
## unsupported attribute "proxy_configuration"
- when `terraform plan` shows below error message, upgrade aws provider by `terraform init -upgrade`.

```
Error: unsupported attribute "proxy_configuration"
Error: unsupported attribute "proxy_configuration"
Error: unsupported attribute "proxy_configuration"
Error: unsupported attribute "setting"
```
文系にも扱える同人活動の為のエコシステム(一部)


# はじめに
## 注意事項
このエントリは、タイトルで大袈裟な事言ってますが **「同人誌書くのになんとなくJenkins入れたらちょっとだけだけど楽になったかも!! ちょっとだけだけど!!」** というエントリなので、そんなにしっかりとしたもの組んでないですし、できる筈の事もしてなかったりするし、ベストプラクティスという訳でもありません。ですが、複数人での作業に不満を感じた時の参考に、少しでもなれば幸いです。

## まえがき
どうも、T-Diceのにぎやかし担当、姫こと実解析です。いや、今回は割とそっちの立場の記事なので。えぇ。

みなさん長い人生の中で、一回ぐらい本を書く機会があると思います。恐らくほとんどの人はTeXを使ってるかもしれないですが、もしかするとSphinxとかでさっくり書いてる人もいるかもしれません。まさかMSWordで書いてる人なんていませんね? **diffもmargeもできないワープロソフトなんて今すぐアインストールしなさい。** と、いいますか、もし少しでも他人とデータを共有する気があるなら有料ソフトなんぞ使うべきではありません。InDesignだって例外じゃありません。

で、一人で書いてる分にはいいんですが、これが多人数で書くとなるとちょっと難しくなると思います。恐らく一番最初に障壁となるのはファイルの共有方法、恐らくその次は同時編集の必要性についての問題…とりあえずウチのサークルで私が感じた事を列挙しますと

 * ファイルの共有はDropBox、なぜならコンソールを叩ける人間が少ないから、SVNやGITなんて使ってられない
   * 履歴なんて残らない (直近数回ぐらいは残るみたいですが。)
     * だれがいつファイルを触ったのかがわからない
     * 過去版なんて出てこない
     * 「原稿_yymmdd.tex」が大量発生
   * 同じファイルを同時に編集なんてできない
     * ちゃんとファイル分割しましょうねという話もあるがそれでも限界はある
 * TeXをコンパイルできる人間がいない。そもそもコンソールを叩ける人間が(略
   * そもそも、論文ならともかく読み物にする為のTeXは結構リッチな環境にしなきゃいけないので **結局コンパイルができるのは最初に環境を作った一人** という状況になったりする。
   * と、いうか普通の人はTeXなんて書けない。読まない。あたりまえだ。
     * とりあえずプレーンテキストで投げられて、適当に `\{section}` と `\{subsection}`  を入れて、校正チェック用のPDFを出すところから始まる
     * 目の前にソースがあるのに、「校正_yymmdd.txt」が大量発生し、それをTeX書ける人間がセコセコ反映する作業が始まる
   * よしんば誰かがソースを修正しても、コンパイルができる人の手が空くまでPDFにならない。つまり校正が進まない
 
**なぜ、なぜこんなに作業フローが重いのか。なぜこんなに見苦しいファイルが大量に発生するのか。**
## 改善をするのは、自分だ。
とはいえ、人にTeX覚えろとかgitぐらい使えるようになれとか言うのは簡単ですが **フツーの人間にそんな事要求するのが無茶な話** ってやつで、それでも自分の作業は減らしたいじゃないですか。
っていうか校正する側も、日本語の文章のとこだけチョコっと直してすぐPDF見たいじゃないですか。
バックアップは取っておかなきゃいけないけど、別に必要になった時に出せればいいじゃないですか。

## リッチなシステムなんていらないけど……
少しだけ、少しだけ便利だったらそれでいい。リッチなシステムは作るのも大変だけど、使うのも大変である。それでも、それでもやらねばいけない事はいくつかある。

# もとい、『非情報系にも扱わせる事ができる同人活動の為のエコシステム』
## 前提
  * 文章そのものはTeXで書いてる
  * 最終的な成果物はPDF
  * 何人か執筆者がいるが**そのほとんどはパソコンに疎い**

## 実現したい事
前書きでな事言いながら、ぶっちゃけ上に挙げた事のほとんどは解消できていませんがとりあえず以下の事だけでも。

 * 複数人でのファイル共有
 * ソース及び成果物のバージョン管理
   * 必要な時に過去版のソースが見れるようにしたい。 
 * TeXの自動コンパイル
   * ソース直したら自動でPDFが生成されるようにしたい

## 環境
  * ファイル共有
    * DropBox
  * バージョン管理
    * SVN  (「SVNサーバ」**ではない**)(Gitでもいい)
  * ソースのビルド
    * Jenkins

## アウトライン
![Jenkins.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6817/60e87a0f-48a0-7a17-bb5e-b588ab29bcb5.png)
これは最小構成の図なんですが、図にするとタイトルに反してショボいですね。私がやってたのはTeXファイル監視して即座にコンパイルさせるようにしてたんですが、適当にデイリーで回すのでも十分でしょう。

## 他にもやった方がいいこと
* この環境を外部サーバにたてる
* Jenkinsを他のパソコンから見えるようにしてエラーの内容ぐらい見れる方がいい
    * エラー内容をtxtで吐かせてもいいかもしれない
* SVN触れる人が複数いる場合はSVNはやっぱりサーバがいい。

ほかにも改善点あればご指摘ください。これほんと適当にやったやつなんで。
職場のITリテラシーを高めたい。

ベンチャーで社内SE（一人）をやることになりました。
ベンチャーですから当然、業務効率など色々問題を抱えているのです。
そこで社内SEとして気になるのが…

#くだらないことで呼ばれる問題

- 印刷が変！
- 印刷できない！
- パソコンが起動できない！
- パソコンが勝手に再起動する！

**ふざけるな！本業に集中させろ！**


##その原因、解決策

- 知識がない（これは問題ない）
- 調べる意欲がない
- 調べる能力がない
- 調べる前に人に聞いている

これらの解決法は2つですね。

- **検索能力を高める**
- **調べようという意識を定着させる**

この方法の実行手段はどうしましょうかね。。。
v-tootipで複数が重なった場合任意のtooltipを下にする方法

【v-tootip】
https://github.com/Akryum/v-tooltip

v-tootipが重なり合ってどちらか任意の方を下にもって行きたい時
z-indexを変えるオプションがあるかと思ったがなさそう
offsetがあるならあってもよさそうなのに・・・

そこで`popoverClass`を使用して任意のクラスを追加してstyleを書き換える
複数重なり合うパターンだとコード汚くなるのでいい方法を探していきたい

Githubのclassを使用するとこちらで重なりを作っているので

```css
.tooltip {
 z-index: 10000;
}
```

このようにして対応をする

``` js
<v-tootip popoverClass=“under-class”>

.under-class {
 z-index: 5000;
}
```
チートシートまとめ

~~これがインターネットだ！ *地獄編*~~  
毎回インターネットをさまよってるので自分がよく見る分だけまとめました。 
# マークアップ言語とか  
## AsciiDoc
+ 公式リファレンス(英語)  
https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/

+ 有志による公式リファレンスの日本語訳  
https://takumon.github.io/asciidoc-syntax-quick-reference-japanese-translation/

+ チートシート(日本語)  
http://www.venus.dti.ne.jp/~iisaka/DocSys/cheatsheet-ja/asciidoc-869/asciidoc-869.html

# いかかかかかがでしたか？  
→ 巨頭ォ
JavaScript であるプロパティをキーにして２つの配列をマージしたい。


## 1. 状況

例えば `arr0` には国名 `name` と大統領名 `president` をプロパティに持ったオブジェクトが保存されていて

`arr1` には国名 `name` と首都名 `capital` をプロパティに持ったオブジェクトが保存されています。

ここで `arr0` と `arr1` に保存されているオブジェクトの共通のプロパティである国名 `name` で２つの配列を国名 `name` でマージさせたいとします。

```javascript
// こんな配列です。
const arr0 = [
  {
    name: 'United States of America',
    president: 'Donald John Trump',
  },
  {
    name: 'People\'s Republic of China',
    president: 'Xí Jìnpíng',
  }
]

const arr1 = [
  {
    name: 'United States of America',
    capital: 'Washington, D.C.',
  },
  {
    name: 'People\'s Republic of China',
    captial: 'Beijing',
  }
]

```


## 2. 実行
実行結果は、以下のようなものを期待しています。

```
> // mergeArraysByProperty(配列１, 配列２, プロパティ名)
> mergeArraysByProperty(arr0, arr1, 'name')
[
  {
    name: 'United States of America',
    president: 'Donald John Trump',
    capital: 'Washington, D.C.'
  },
  {
    name: "People's Republic of China",
    president: 'Xí Jìnpíng',
    captial: 'Beijing'
  }
]
> 
```


## 3. 定義

以下のような具合です。

```javascript
function mergeArraysByProperty(arr0, arr1, property) {
  if (arr0.length !== arr1.length) {
    throw Error('arr0 and arr1 do not have same lenght.')
  }
  const mergedArr = []
  for (const elm0 of arr0) {
    for (const elm1 of arr1) {
      if (elm0[property] === elm1[property]) {
        mergedArr.push(Object.assign(elm0, elm1))
        break
      }
    }
  }
  if (arr1.length !== mergedArr.length) {
    throw Error('Some elements mismatched between arr0 and arr1.')
  }
  return mergedArr
}
```

* [JavaScriptでObjectをマージしたい - Qiita](https://qiita.com/h-naito/items/062ef0f5dbdae73fe814)
* [Object.assign() - MDN web docs](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)


## 4. ToDo

たぶん、やらないけど...


### ◯ 1 引数チェックの追加
property の値が配列内でユニークであることを確認する。

### ◯ 2 方針の変更
property の値でソートさせてからマージする。現在 O(n^2) なので、O(nlogn) にできる。
ローカル確認のための簡易サーバ(http-server)

結構便利だったのに忘れてしまって、次に探さないためのメモ。

【用途】
ローカル環境でhtmlファイルなどの簡易的な確認を行いたい時に、いちいち面倒なconfの設定などせずにすぐに実行できて便利。

### 事前準備：ツールのインストール

どっちでインストールしたか忘れた。npmだったか。brewでもインストールできる模様。

#### npmの場合

```
npm install -g http-server
```

#### brewの場合

```
brew install http-server
```

npm https://www.npmjs.com/package/http-server
brew https://formulae.brew.sh/formula/http-server

### 使い方
Terminalで確認したいファイルがある任意のディレクトリまで移動して起動

```
cd ./hoge/hage

http-server

Starting up http-server, serving ./
Available on:
  http://127.0.0.1:8080
  http://10.215.10.165:8080
```

127.0.0.1:8080か、localhost:8080でブラウザ確認できるようになる。

以上。

参考：https://utano.jp/entry/2018/02/npm-http-server/
laravel adminの$show->fieldでリレーション使う場合

同じフィールド内にリレーションで持たせた値を表示したい!
フィールドが分かれた感じの説明はよく見るけど、一緒の項目として並んでいるのが探してもわからず...
laravel-adminで準備されている`as`メソッドを使ってみた。
これが正解かはわかりません。

```php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Company extends Model
{
    public function code()
    {
        return $this->hasMany(Code::class, 'company_id', 'id');
    }
}
```

```php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Code extends Model
{
    protected $fillable = [
        'code',
        'company_id',
        'admin_user_id'
    ];

    public function company()
    {
        return $this->belongsTo(Company::class, 'company_id', 'id');
    }
}
```

```php
    /**
     * Make a show builder.
     *
     * @param mixed $id
     * @return Show
     */
    protected function detail($id)
    {
        $show = new Show(Code::with('company')->findOrFail($id));

        $show->field('id', __('Id'));
        $show->field('code', __('Code'));
        $show->field('company', __('Company id'))->as(function ($company) {
            return $company->name;
        });
        $show->field('admin_user_id', __('User id'));
        $show->field('created_at', __('Created at'));
        $show->field('updated_at', __('Updated at'));

        return $show;
    }

```
Xpathとは？Xpathを簡単に紹介する

XML Path Language （XPath（エックスパス）） は、マークアップ言語 XML に準拠した文書の特定の部分を指定する言語構文である。XPath自体は簡潔な構文 （式言語） であり、（XML関係にありがちな）XMLベースのマークアップ言語ではない。標準化団体 W3C (World Wide Web Consortium) で開発され、もともとXPathは、XSL (XSLT) と XPointer に共通する構文と振る舞いのモデルを目標としている。今、XPathは、XML文書中から必要な要素群（サブセット）を取り出す、などといった用途に使うものとして、急速に受け入れられていった。
本文には、Xpathのロケーションパス、軸と演算子から簡単に紹介します。
##1.少し簡単なロケーションパスを紹介する
XPathで最も一般的な式は、ロケーションパスである。ロケーションパスにより、XML文書のあるノード（現在のコンテクストノード）を基準として、別のノードもしくは複数のノード（ノード集合）が指定される（指定されるノードが0個すなわち1個も存在しない場合もある）。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/8c79a4c4-e00f-76df-47cc-62ed48fdfe29.png)
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/783a1a8a-3609-8397-c3ec-3921a0d9f39e.png)
##2.軸
ロケーションステップの軸の記述は、XML文書の木構造において、方向を指定する。XPath仕様で定義されている13種類の軸を示す。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/39a981d6-a80e-06b4-7379-1134942a8f8d.png)
少し例を挙げて、ご参照ください。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/3d507bb1-eb6d-3f70-d25e-a1f78040df9e.png)
##3.演算子
演算子（えんざんし、英: operator symbol, operator name）は、数式やコンピュータプログラミング言語などで、各種の演算を表わす記号・シンボルである。普通は、演算子は単なる記号ないし記号列であって構文論的なものであり、それに対応する演算は意味論の側にある。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/4edf7403-d26f-f47c-f823-c769b15fdbd4.png)

参照リンク：https://ja.wikipedia.org/wiki/XML_Path_Language
sendmailコマンド(Postfix)でEnvelopeFrom, HeaderFromを設定して送信する方法

# 目的
メールサーバを構築したときに、メール送信のテストを簡単に行いたいので、sendmailコマンドの使い方をまとめます。
今回構築する環境では、試験のためにEnvelopeFromとHeaderFromを設定しわける必要があり、その設定方法もまとめます。

# 動作環境
CentOS 7.3 + Postfix 2.10.1-6.el7.x86_64

# sendmaiコマンド
```
$ sendmail -f Envelope-From-Address@xxxxx.xxx.xx RCPT-To-Address@yyyy.yyy.yy
From: Header-From-Address@xxxxx.xxx.xx
To: Mail-To-Address@yyyy.yyy.yy
Subject: TEST

テストメールです
.
```
sendmailコマンドの-fオプションでEnvelopeFromを設定できます。続けて、RCPT-Toを設定します。
sendmailコマンドの行を入力すると、入力待ちとなるので、ヘッダ部を入力します。
ヘッダ部はLFで改行します。
当初(意図せず)CRLFになっていて、Gmailでは正しくヘッダFromもToも表示されるのですが、Thunderbirdでは本文中に表示されてしまいました。

なお、上記はメール本文をその場で手入力していますが、ワンライナーにすると下記のようになります。sendmailコマンドは引数に件名を指定できないようですので、echoで流し込む形を取ってみました。mailコマンド（mailxパッケージ）では件名を引数に取れたはずです。

```
$ echo -e "From: Header-From-Address@xxxxx.xxx.xx\nTo: Mail-To-Address@yyyy.yyy.yy\nSubject: Test\n\nテストメールです" | sendmail -i -t -f Envelope-From-Address@xxxxx.xxx.xx RCPT-To-Address@yyyy.yyy.yy
```

# EnvelopeFromとHeaderFromの違い
メール配送時に使われるのがEnvelopeFrom。メーラに表示されるのがHeaderFrom。
なお、SPFチェックで使われるのはEnvelopeFromだと思います（EnvelopeFromのドメイン部分のDNSに照会される）。違うようでしたらどなたかツッコミを入れて下さい。

余談ですが、一般的にHeaderFromもチェックしているケースもあるのかは不明ですが、たまたま自社のサーバはチェックしていて、社外から自社のドメインをかたって送信されるメールはブロックしていました。・・・このため、社外のクラウドから自社のメールアドレスをFromにしたメルマガを配信すると、自分達だけブロックされて受け取れないという事態に陥り、そのテストのためこのsendmailコマンドを使ったのでした。。。
【Unity】【基礎】SerializeFieldは何者だ？

# やりたいこと
 [SerializeField]とは何者だ。

# [~~]の意味
 - C#の機能で属性と呼ぶ。
 - Javaでいうアノテーションで各フィールドごとに意味を持たせる。
 - 自作の属性も作ることができる。
 - Unity固有の属性も数十と用意されておりSerializeFieldもその一つ。
 - Unity固有の属性一覧については参考サイト1. を参照

# SerializeFieldの意味
 - エディタのインスペクタビューに項目追加され、値の設定が可能になる。
 - ホットリロードが可能になる。<br>
   (ゲーム実行中にスクリプトを修正しても、フィールドの値が失われない。)
 - シリアライズによりハードディスク等外部からの復元を保証する？<br>
   (保証するのか、シリアライズ化の対象であることをマーク（明示）しているだけか<br>
   どちらであるかは調べていない。)

# 具体的な使用例
## テストコード
```csharp:SerialA.cs
public class SerialA : MonoBehaviour
{
    [SerializeField]  SerialB serialB;
    void Start()
    {
        serialB.Value1 = 400;
    }
}
```
```csharp:SerialB.cs
public class SerialB : MonoBehaviour
{
    [SerializeField] int Value1; ・・・（※１）
}
```

## パターン１ : エディタ上から編集したいが、スクリプト上では隠蔽したい。　
```csharp:SerialB.cs
   [SerializeField] private int Value1;
```
エディタ上から値の初期化を行うときに有効。
カプセル化も維持される。

## パターン２ : エディタ上から編集しない、スクリプト上では隠蔽したい。
```csharp:SerialB.cs
   private int Value1;
```
値の初期化をスクリプトで行う場合などに有効。
エディタで誤って値を設定させない場合に有効。

## パターン３ : エディタ上から編集する、スクリプト上でも公開する。
```csharp:SerialB.cs
   [SerializeField] public int Value1{get; set;}
　 // または, 
   public int Value1{get; set;}
```
おそらくあり得ないパターン。スクリプト上で初期化するならインスペクタビューへの公開は不要であるし、逆もまた然り。
まぁ趣味として速さ優先で書く分にはいいかと。
インスペクタビューへの公開のみを目的とするなら下の書き方のが簡潔。


# 参考サイト
[1. UnityのAttribute（属性）についてまとめてメモる。](http://tsubakit1.hateblo.jp/entry/2015/01/03/203843#SerializeField)
[2. スクリプトのシリアル化](https://docs.unity3d.com/ja/current/Manual/script-Serialization.html)
Unityをプロキシ内でインストール&使用(Windows 10)

# 結論(2019/10/29)

- https://docs.unity3d.com/Manual/upm-network.html に従って起動用バッチファイルを用意する．
- プロキシを使用しないアドレスのリストに 127.0.0.1 を指定する．

# 手順

サーバのアドレス(FQDN)を your_proxy_server，ポートを 8080 として説明する．

## プロキシの設定

手動プロキシセットアップでプロキシが適切に設定されているかチェックする．Unity Package Manager の動作のためには，プロキシを使用しないアドレスのリストに 127.0.0.1 を指定する必要がある．以下は認証を必要としないプロキシの場合の設定例である．

- プロキシサーバーを使う: オン
- アドレス: your_proxy_server
- ポート: 8080
- 次のエントリで始まるアドレス以外に...: localhost;127.0.0.1
- ローカル(イントラネット)のアドレスにはプロキシサーバーを使わない: チェック


## Unity Hubのインストール

https://unity3d.com/jp/get-unity/download から「Unity Hub をダウンロード」をクリックし，UnityHubSetup.exe をダウンロードして実行する．

## 起動用バッチファイルの作成

以下の内容のバッチファイルを作成し，例えばデスクトップに unity-hub-proxy.bat などのファイル名で置く．

```:unity-hub-proxy.bat
@echo off
set HTTP_PROXY=http://your_proxy_server:8080
set HTTPS_PROXY=http://your_proxy_server:8080
start "" "C:\Program Files\Unity Hub\Unity Hub.exe"
```

このバッチファイルで Unity Hub を起動すると，新規インストール，モジュールの追加，サインインなどが行える．また Unity Hub から起動した Unity Editor では，Asset Store からのダウンロードが可能になる．

## Windows Defender ファイアウォールのブロック解除

Unity Hub や Unity Editor の初回起動時にWindows Defender の警告が出る可能性がある．
プライベートネットワーク にチェックを入れてアクセスを許可する．
1行でコールバックをawaitする簡易Promisify

`Util`を`require`するほどでもないときに使うイディオム。

```javascript
const buffer = await new Promise((ok, ng) => fs.readFile(path, (err, res) => err ? ng(err) : ok(res)))
```

[こちら](https://qiita.com/suin/items/99aa8641d06b5f819656)を見て反射的にアウトプット^^;

`~Sync`使えよって話ですが非同期に統一したいもので。
PhpStormでのgit add -p

(2020-03-26) この記事は http://blog.a-way-out.net/blog/2019/10/30/phpstorm-git-add-p/ のコピーです。今後、退会により削除される可能性があります。

# 環境

- PhpStorm 2019.2.3

# 手順

## 「Commit Changes」ウィンドウを表示させる

- 右上の「Git:」の右にあるチェックマーク「✔️」アイコンをクリックします。

または、

- ウィンドウ下の「Version Control」をクリックします。
- 左上のチェックマーク「✔️」アイコンをクリックします。

## コミット対象を選択する

- 「Commit Changes」ウィンドウの下に差分が表示されているので、そのチェックマークを外すとコミット対象から外せます。

# 参考

- [IntelliJ IDEA 2018.1 EAP: Gitの部分コミットなど | JetBrains ブログ](https://blog.jetbrains.com/jp/2018/02/21/857)

---

[![クリエイティブ・コモンズ・ライセンス](https://i.creativecommons.org/l/by-sa/4.0/88x31.png)](http://creativecommons.org/licenses/by-sa/4.0/deed.ja)
この記事は[CC BY-SA 4.0（クリエイティブ・コモンズ 表示 4.0 継承 国際 ライセンス）](http://creativecommons.org/licenses/by-sa/4.0/deed.ja)の元で公開します。
[入門者によるメモ]swift4 xib作成手順

昔少しだけswiftをやっていて、その時なんか苦労した記憶があって敬遠してたけど、めちゃくちゃ簡単でびっくり。
入門者による自分用メモです。

##具体的な手順
① TestView.swift　ファイルと　TestView.xib　ファイルを作る
②　TextView.xib ファイルの Owner'sFileに　TestView.swiftファイルを設定
③Swiftファイルにおいて、xibを読み込む設定をする。
コードは以下の通り

```swift

import UIKit

class XibView: UIView {

    // コードから生成した時の初期化処理
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.nibInit()
    }
    
    // ストーリーボードで配置した時の初期化処理
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.nibInit()
    }
    
    // xibファイルを読み込んでviewに重ねる
    fileprivate func nibInit() {

        // File's OwnerをTestViewにしたので ownerはself になる
        guard let view = UINib(nibName: "TestView", bundle: nil).instantiate(withOwner: self, options: nil).first as? UIView else {
            return
        }
        
        view.frame = self.bounds
        
        view.autoresizingMask = [.flexibleHeight, .flexibleWidth]
        
        self.addSubview(view)
    }

}
```

以上でxibファイルをswiftファイルと紐付けができたので、あとはそれを好きな時にレゴブロック的に呼び出すだけ。

Main.storyboardにおいて、xibファイルを設置したいときは、storyboard上でViewファイルなりを設置して、そのカスタムファイルを先に作成したTestView.swift　にすれば完成。



StoryboardでViewにおいてどっちが優先されるんだろうと思って、View背景色を緑にしといて、xibファイルの方では青を設定したら青になった。　xibの方が優先されるのかほほーってなりました。swiftの理解がほぼ０なので頑張らなきゃ

##参考文献
https://program-life.com/559
すごくわかりやすくて感謝です。ありがとうございますmm
Spring Batchの基本(メモ)

# Spring Batchの作成と呼び出し方についてまとめ
## Spring Batch本体の作成
### Jobの作成
```
/**
 * サンプルJOB.
 *
 */
@Configuration
@EnableBatchProcessing
@EnableAutoConfiguration
public class SampleJob {
  @Autowired
  private StepBuilderFactory stepBuilderFactory;
  //タスク(複数ある場合はその分宣言する)
  @Autowired
  private SampleTask sampleTasklet;
  @Autowired
  private ExecutionContextPromotionListener promotionListener;

   /**
   * ランチャー設定(Bean化).
   * @param jobRepository JobRepository
   * @return JobLauncher
   */
  @Bean(name = "SampleJobLauncher")
  public JobLauncher simpleJobLauncher(final JobRepository jobRepository) {
    final SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
    jobLauncher.setJobRepository(jobRepository);
    jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());// 非同期設定
    return jobLauncher;
  }

  /**
   * タスクレット(ステップ)の設定(Bean化).
   * @return タスクレット(ステップ)
   */
  @Bean(name = "sampleStep")
  public Step sampleStep() {
    return stepBuilderFactory.get("sampleTasklet")
        .tasklet(sampleTasklet).listener(promotionListener).build();
  }

   /**
   * タスクレット間パラメータ引き渡し設定
   * @return
   */
  @Bean
  public ExecutionContextPromotionListener promotionListener() {
    String[] keySet = { "param1", "param2" };
    ExecutionContextPromotionListener promotionListener = new ExecutionContextPromotionListener();
    promotionListener.setKeys(keySet);
    return promotionListener;
  }

 /**
   * サンプルJOB設定(Bean化).
   * @param jobs JobBuilderFactory
   * @param sampleStep サンプルタスクレット(複数ある場合は引数に追加)
   * @param jobErrorLoggingListener 例外エラーリスナー
   * @return Job
   */
  @Bean(name = "sample")
  public Job sampleJob(JobBuilderFactory jobs, @Qualifier("sampleStep") Step sampleStep, JobErrorLoggingListener jobErrorLoggingListener) {
    return jobs.get("sampleJob").incrementer(new RunIdIncrementer()).listener(jobErrorLoggingListener)
        .start(sampleStep).on(ExitStatus.COMPLETED.getExitCode()).end()
        .from(sampleStep).on(ExitStatus.FAILED.getExitCode()).fail().end().build();
  }
}
```

### タスクの作成
```
/**
 * バスネットCSV読み込みタスクレット.
 *
 */
@Component
public class SampleTask implements Tasklet {
@Override
  public RepeatStatus execute(StepContribution contribution,ChunkContext chunkContext) throws Exception {
    //ここにバッチの処理を記述する

    return RepeatStatus.FINISHED;
  }
}
```

## Spring Batchの呼び出し
```
public class BatchStart {
  @Autowired
  @Qualifier("sampleJobLauncher")
  private JobLauncher samplejobLauncher;

  @Autowired
  @Qualifier("sample")
  private Job sampleJob;

  /**
   * バッチ起動
   */
  public void startBatch() {
    Map<String, JobParameter> params = new HashMap<String, JobParameter>();
    UUID uuid = UUID.randomUUID();
    params.put("jobKey", new JobParameter(uuid.toString()));
    JobParameters jobParameters = new JobParameters(params);
    try {
      this.samplejobLauncher.run(sampleJob, jobParameters);
    } catch (JobExecutionAlreadyRunningException e) {
      //・・・
    } catch (JobRestartException e) {
      //・・・
    } catch (JobInstanceAlreadyCompleteException e) {
      //・・・
    } catch (JobParametersInvalidException e) {
    }
  }
}
chromeが文字化けして詰まった話

## 結論
chromeのフォント設定が特殊なものになっていた。

## 環境
chrome のverison: 77.0.3865.120
windows 10
thinkpad x390

## 状態
半角英数字のみ文字化けしてしまった。
テキストエンコーディングの拡張機能を入れて文字コードを変更しても文字化けが解消されない。
ソースコードでは文字化けしている部分が、正しく表示されていて表示する際に何らかの処理が行われておかしくなっていることが分かった。

## 解決方法
以下のURLを参考にシークレットモード、ゲストモードで実行してみたところゲストモードでは文字化けが改善されることが分かった。
https://support.google.com/chrome/forum/AAAAG2Advoc_yeS6Fcol08/?hl=ja

このことから問題は自分のアカウントの設定であることが判明。
chromeの設定 -> デザイン -> フォントのカスタマイズからフォントの種類が勝手に
"Marlett"というものに変更されていたことが判明。

フォントを何か好みの別のものに変更した結果文字化けが解消された。

## まとめ
なぜ勝手にフォントが変更されたのかは不明
Linuxでもログインしているからそこで変更されていまったのかなー...。
telnet コマンドの代替としての StreamRelay.NET.exe

---
### telnet コマンドの代替としての StreamRelay.NET.exe

ver3.5.2.0 より、[TelnetLib.dll](https://archive.codeplex.com/?p=telnetexpect) を同梱して、「-RemoteProxy」オプションに telnet スキームを新設した。


---
### スキームの仕様

仕様はこんな感じ

`telnet://≪ユーザ名≫:≪パスワード≫@/≪コマンド1≫/≪コマンド2≫...?≪オプション≫`

≪コマンドn≫ は、ログイン後に自動発行するコマンドの羅列。

---
### スキームのオプション

≪オプション≫は、以下を用意した(ver3.5.2.1)

<dl>
 <dt><b>NTLM</b>
  <dd>NTLM認証をする
 <dt><b>user=≪プロンプトメッセージ≫</b>
  <dd>既定は「login:」を監視して、その後にユーザ名を送信するが、この文字列を変更できる
 <dt><b>pass=≪プロンプトメッセージ≫</b>
  <dd>既定は「password:」を監視して、その後にパスワードを送信するが、この文字列を変更できる
</dl>

---
### 使用例

単純に、「192.0.2.4:23」のTelnetサーバに「ユーザ名=user、パスワード=password」で接続するには

`StreamRelay.NET.exe -LocalPort 0 -RemotePort 23 -RemoteHost 192.0.2.4 -RemoteProxy telnet://user:password@/`

こんな感じ。

単純に、「192.0.2.4:23」のTelnetサーバに「ユーザ名=user、パスワード=password」で接続して、直後に「dir」「ipconfig」を実行させたい場合は、

`StreamRelay.NET.exe -LocalPort 0 -RemotePort 23 -RemoteHost 192.0.2.4 -RemoteProxy telnet://user:password@/dir/ipconfig`

こんな感じ。

単純に、「192.0.2.4:23」のTelnetサーバに「ユーザ名=user、パスワード=password」で接続して、直後に「dir」「ipconfig」を実行させて切断したい場合は、

`StreamRelay.NET.exe -LocalPort 0 -RemotePort 23 -RemoteHost 192.0.2.4 -RemoteProxy telnet://user:password@/dir/ipconfig/exit`

こんな感じ。

一応、[TelnetLib.dll](https://archive.codeplex.com/?p=telnetexpect) には NTLM認証もあるので、、

`StreamRelay.NET.exe -LocalPort 0 -RemotePort 23 -RemoteHost 192.0.2.4 -RemoteProxy telnet:///dir/ipconfig?NTLM`

でできるかも知れない。(開発環境ではうまく動作しない)

対象のTelnetサーバのログインプロンプトが「user:」でパスワードプロンプトが「passphrase:」の場合は、

`StreamRelay.NET.exe -LocalPort 0 -RemotePort 23 -RemoteHost 192.0.2.4 -RemoteProxy telnet://user:password@/dir/ipconfig/exit?user=user:&pass=passphrase:`

こんな感じ。

---
### 目次へ戻る

[目次というか最初の一歩](http://qiita.com/tomoki0sanaki/items/85f20cbe18378e33cd6f)
【Shopify】チェックアウト画面を任意の言語で表示する

JSONとJavaScriptで言語切り替えを実装しているテーマで、チェックアウト画面の言語も切り替える方法を見つけたのでメモ。

# tl;dr
- Shopify管理画面のチェックアウト言語切り替えはアクセス元の地域によって言語を切り替えるため、日本からのアクセスでは全て日本語で表示されてしまう。
- チェックアウトページのURLに`?locale=en`とパラメータを付けると指定した言語で表示される。
- カート画面にある`<form>`の`action`属性を`/cart?locale=en`とすると遷移先のチェックアウトページへパラメータが引き継がれ、任意の言語でチェックアウト画面を表示できる。

# やりたいこと
各言語の翻訳テキストをJSONに格納して、JavaScriptでレンダリングする方法で多言語対応をしているストアで、JavaScriptで制御の効かないチェックアウト画面も任意の言語で表示したい。

## 問題点
### 管理画面の言語切り替えは使えない
Shopify管理画面から[チェックアウト言語切り替え](https://help.shopify.com/en/manual/checkout-settings/checkout-language)ができるようになっていますが、これはアクセス元に応じて言語を切り替える仕組みのようで、日本からアクセスしている限りは英語に切り替えたとしてもチェックアウト画面は日本語になってしまいます。
### 翻訳アプリはコストに見合わない
[LangShop](https://apps.shopify.com/langshop?locale=ja)のような翻訳アプリを入れれば選択した言語でチェックアウト画面を表示してくれます。
動的コンテンツを翻訳する必要があれば確かに便利ですが、今回は基本的に自前のJSONとJSで言語切り替えを実装しているので、チェックアウト画面の言語を切り替えるためだけに月18ドル払うのは割に合わないです。
あと静的テキストなどは更新するたびに翻訳を実行しなければならず面倒だったり

# 実装
公式リファレンスでは見つけられなかったのですが、チェックアウト画面のURLに`?locale=fr`のようにパラメータをくっつけると、パラメータの値に設定した言語で表示してくれる仕様みたいです。


ただ、基本的にチェックアウト画面はカスタマイズできない（プランによってはできるようです）のでカート画面をちょっといじります。

```html:cart.liquid
<form class="cart-form" action="/cart" method="post" novalidate>
   <!-- formの中身 -->
</form>
```
`cart.liquid`内にこんな感じでチェックアウト用のフォームがあるかと思います。
ここの`action`属性にチェックアウト画面で表示したい言語の言語コードをGETパラメータとして設定すれば、それがそのままチェックアウト画面のURLへ引き継がれるという仕様になっているみたいです。

例えばフランス語で表示したかったらこんな感じです

```html:cart.liquid
<form class="cart-form" action="/cart?locale=fr" method="post" novalidate>
   <!-- formの中身 -->
</form>
```
これでチェックアウトボタンを押せばフランス語のチェックアウト画面が表示されます。

ちなみに管理画面で言語の設定をする必要はなく、Shopify側で用意されている言語であればどれでも表示することができるようです。ありがたい。

# まとめ
翻訳アプリを入れるとチェックアウトも言語切り替えができて不思議に思っていたのですが、GETパラメータで言語を切り替える仕様だったようですね。
公式のドキュメントにはアクセス元によって言語を切り替えるやり方しか書いてないですが、自前で言語切り替えを用意したいときはこの方法で何とかできそうです。

> 参考
> [Pass Locale parameter using Buy Button - Shopify Community](https://community.shopify.com/c/Shopify-APIs-SDKs/Pass-Locale-parameter-using-Buy-Button/m-p/313228)
> [Draft Orders Checkout -- set locale parameter for translation
 - Shopify Community](https://community.shopify.com/c/Shopify-APIs-SDKs/Draft-Orders-Checkout-set-locale-parameter-for-translation/td-p/353652)
ペアプロ　お買い物プログラム２　回答

```ruby:order.rb
#注文
def order(num, menus, total_price)
  puts "いくつ注文しますか？"
  quantity = gets.to_i
  menu = menus[num]
  price = menu * quantity
  total_price += price
  puts "他にご注文はございますか？"
  return total_price
end

#レジ
def register(total_price)
  puts "お会計は#{total_price}になります"
  puts "ありがとうございました！"
  exit
end

#メニュー
burger = 500
potato = 300
drink = 150
menus = [burger, potato, drink]
total_price = 0
puts "いらっしゃいませ、ご注文をどうぞ"

while true do
  puts "[0]:ハンバーガー・500円"
  puts "[1]:ポテト・300円"
  puts "[2]:ドリンク・150円"
  puts "[3]:お会計へ"
  num = gets.to_i
  if num == 3
    register(total_price) #レジへ
  else
    total_price = order(num, menus, total_price) #注文へ
  end

end

```

補足：イートインかテイクアウトかで税率を変える機能をつけても楽しいかも
PythonとMecabで特定の品詞の単語だけ取り出す


# はじめに

「私はプログラミングが苦手です」
のような文書を、単語に分かち書きしたいことがあります。

これは、Pythonでは

- MecabをホストOSにインストール
- mecab-pythonをpipインストール

すればよいです。

しかし、このまま分かち書きをすると
`私 は プログラミング が 苦手 です`と「は」「が」「です」といういらない品詞が入ってしまうため、それらを削除しましょう。

# 特定品詞

```py
import MeCab

# 取り出したい品詞
select_conditions = ['動詞', '形容詞', '名詞']

# 分かち書きオブジェクト
tagger = MeCab.Tagger('')

# Neologdの指定版 最新語に対応する
# tagger = MeCab.Tagger('-d /usr/lib64/mecab/dic/mecab-ipadic-neologd')

# 安定するらしい
tagger.parse('')


def wakati_text(text):
    """
    文書textを分かち書きして、半角スペース区切りの単語文字列に変換する

    Parameters
    ----------
    text: str
        文書

    Returns
    -------
    text_result: str
        分かち書きされた文書

    """

    # 分けてノードごとにする
    node = tagger.parseToNode(text)
    terms = []

    while node:

        # 単語
        term = node.surface

        # 品詞
        pos = node.feature.split(',')[0]

        # もし品詞が条件と一致してたら
        if pos in select_conditions:
            terms.append(term)

        node = node.next

    # 連結おじさん
    text_result = ' '.join(terms)
    return text_result


text = "私はプログラミングが苦手です"

'''
私 プログラミング 苦手
'''
print(wakati_text(text))

```

文書$text$をMecabのオブジェクト$tagger$でノード(単語)ごとに分割します。
そして、各$node$の品詞を見て、それが自分の指定した品詞集合と一致するかで判定すればよいです。

# 参考にさせていただいたサイト

- [MeCab：品詞ごとに取り出す](https://qiita.com/Sue_chan/items/091e2b77e6c0b26d4106)
- 
[MeCabを使って、テキスト中に含まれる品詞をカウントしてみよう！](https://qiita.com/yonedaco/items/27e1ad19132c9f1c9180)
ペアプロ　お買い物プログラム２

#Rubyアルゴリズム問題
#お買い物プログラムを作ろう2

今回作るプログラムはお買い物プログラムです。

#仕様
####仕様は以下のようにしたいと思います。
・商品の個数を選択し、お買い物カゴに入れることができる
・レジに進むと合計金額が表示される

####用意する品物


| 品物    |価格  |
|:-------|-----:|
|バーガー|500円 |
|ポテト   |200円 |
|ドリンク   |150円|
（これもある程度自由で大丈夫です）
#回答
https://qiita.com/shintaro_yataki/items/be3db88cc20764f11adc
LaravelでAmazon MWS APIを使用し注文情報を取得する

## 事前準備
Amazon MWSのアカウント：申請してから1ヶ月くらいかかります。

## ファイルをダウンロードしてきます
Composerは使用できないので、以下より注文用のファイルをダウンロードします。
https://developer.amazonservices.jp/phpclients

## Laravelに追加
今回は `appp/Libraries`というディレクトリを追加し、
そこに上記でダウンロードした `MarketplaceWebServiceOrders` をフォルダごと追加します。

## composer.json に設定を追加
以下のようにします。

```composer.json
"autoload": {
  "classmap": [
    "app/Libraries/Amazon/MarketplaceWebServiceOrders/Client.php"
  ],
  // その他設定
}
```
そして `composer dump-autoload` を実行

PHP5.6以降は以下でひっかかるので条件追加

```php:Client.php

if ( (float)phpversion() < 5.6 ) {
  iconv_set_encoding('output_encoding', 'UTF-8');
  iconv_set_encoding('input_encoding', 'UTF-8');
  iconv_set_encoding('internal_encoding', 'UTF-8');
}
```

これで使えるようになるはず。

```php

use MarketplaceWebServiceProducts_Client;

// Japan
$serviceUrl = "https://mws.amazonservices.jp/Orders/2013-09-01";

$config = array (
    'ServiceURL' => $serviceUrl,
    'ProxyHost' => null,
    'ProxyPort' => -1,
    'ProxyUsername' => null,
    'ProxyPassword' => null,
    'MaxErrorRetry' => 3,
);

// 以下は申請が承認されるともらえます
$service = new MarketplaceWebServiceProducts_Client(
    AWS_ACCESS_KEY_ID,
    AWS_SECRET_ACCESS_KEY,
    APPLICATION_NAME,
    APPLICATION_VERSION,
    $config);

// getServiceStatus
$getServiceStatus = $service->getServiceStatus(null);
var_dump($getServiceStatus->GetServiceStatusResult);
echo $getServiceStatus->GetServiceStatusResult->Status; // GREENなど

// 注文情報の取得
$parameters = [
    'SellerId'      => $sellerId,
    'AmazonOrderId' => $orderId
];
$getOrder = $service->getOrder($parameters);

```
Qiita始めてみた

#1. Qiitaを始めた動機

ナレッジをローカルではなくネットワーク上に公開できるかたちで置いておきたかったから。

なぜそんなことを考えたかというと、ナレッジを貯めておく場所が年々無くなっているから、これに尽きる。常駐型プロジェクトにアサインされるため、自分が作った成果物も調べたメモもプロジェクトが終わるたびに手元に残らない状態で、時と共に記憶も薄れ、同じようなことが起きるたびに再度調べなおすので効率悪いと感じていた。

もちろん守秘義務あるからそのまんま上げるのは無理なやつも多いんだけど、ナレッジを適宜まとめるというルーチンというかフレームワークを作っておきたいというのがある。
ちなみにこれまではslackを使ってたのだけど、会社PCからログインがNGのため、徐々に使いづらくなっていったのでググれば出てくるQiitaはいいかなと感じている。

#2. 自己紹介

肩書付けるなら、SAPのアプリケーションコンサルタント。でも調整ごとやることが多くて技術はイマイチ。文系出身でプログラミングもほとんどやったことない。（ので勉強したいとは思ってます、ハイ）

#3. Qiitaに投稿しようと考えているトピック
・プロジェクト管理
・プロジェクトやっているときに気になったアレコレのTips
・本のレビュー、まとめ
プロジェクトに入っていると細かい部分が気になるのだけど、それを俯瞰して勉強して載せたいと思っている。
[bash] コマンド履歴を一気にコピペする方法

history で見るとコマンドの番号が入ってそのままではコピペに使えなくてめんどくさい。
調べたら簡単なコマンドでできたのでメモ

https://qiita.com/catfist/items/82ed3df7a0b524aeab69
を参考にしました

```bash:history_pbcopy
history | tail -n (何個まえまで見たいか） | cut -d ' ' -f 5- | pbcopy
```

で取れます。便利！！！

ここからここまでって決まっていたら、

```bash:history_pbcopy
history | tail -n (何個まえまで見たいか） | head -n （そこから何個まで見たいか) | cut -d ' ' -f 5- | pbcopy
```

で取ることができます
Spack - The package manager for super computers

## 参考

* [spack package managerを使って最新のgccをインストール – Nabe International | Takeru Boost >> Takeruを回せ！ >>](https://www.nabe-intl.co.jp/takeruboost/spack-package-manager%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E6%9C%80%E6%96%B0%E3%81%AEgcc%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/)
* [Spack — Spack 0.12.1 ドキュメント](https://spack.readthedocs.io/ja/latest/)
* [Advanced Topics in Packaging — Spack Tutorial documentation](https://spack-tutorial.readthedocs.io/en/latest/tutorial_advanced_packaging.html)

## Spackとは

> スパコン向け(もしくはスパコンユーザー向け)に開発されたパッケージ管理ツールです。

なんかすごいの見つけた・・・。

## インストール

* CentOS 8 にて確認。

```sh
yum install -y python36

git clone https://github.com/spack/spack.git
cd spack/bin
```

|コマンド|説明|
|:--|:--|
| spack list | パッケージ一覧 |
| spack find | インストール済みパッケージ一覧 |
| spack install [package] | パッケージのインストール |
| spack info [package] | インストール可能なバージョン一覧 |

```sh
# バージョン一覧表示
./spack info gcc
```

```sh
./spack install gcc@7.2.0 %gcc@5.4.0

./spack install gcc@4.4.9: languages=c,c++
```

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/8b7f52ee-378b-e541-ee2f-95994de9d213.png)

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/7864a62d-7f0a-1c42-5949-1eab2bebba96.png)

ありゃ・・・コンパイル失敗する。
CSS:画像に対するグラデーション

#画像にフェード効果を適用

html

```
<div class="trim">
 <img src="image.jpg" alt="" title="">
</div>
```

css

```
.trim{
  position:relative;
}
.trim:after{
  position: absolute;
  content:"";
  top:0;
  left:0;
  width: 100%;
  height:100%;
  /* 塗りつぶす */
  background: -webkit-linear-gradient(top, rgba(255, 255, 255, 0) 40%, #fff 100%); 
}
```
AWS Batchで投入したジョブが開始されるまでに10分以上もかかる場合

# 環境

AWS Batch
2019年10月30日、us-east-1 (N. Virginia) リージョン

# 症状

Desired vCPUsが0のコンピューティング環境では、キューにジョブを投入してから実際に開始されるまで10分以上かかることがよくある。

例：
[StackOverflow](https://stackoverflow.com/questions/54902213/aws-batch-job-start-too-long-with-min-vcpus-0-in-compute-environment)
[Reddit r/aws](https://www.reddit.com/r/aws/comments/amg7yk/is_there_an_opensource_alternative_to_aws_batch/eflueed/)

Min vCPUsを1以上に設定すると、Desired vCPUsが0になることはないので、「Min vCPUsが0だと10分以上かかる」という相関関係も存在する。しかし本質はDesired vCPUsである。

# 分析

あなたの設定するDesired vCPUsは初期値であり、AWS Batchは直近の利用状況を見てこの値を書き換える。[AWS Batch modifies this value between the minimum and maximum values, based on job queue demand.](https://docs.aws.amazon.com/batch/latest/userguide/compute_environment_parameters.html)
実際に、AWSコンソールでコンピューティング環境を見ると、直近の数時間にジョブが投入されなかった環境のDesired vCPUsは0になっている。逆に、直近に何度もジョブが投入されていると0ではない。

# 対策

ジョブを投入するときに、コンピューティング環境のDesired vCPUsを調べる。もし0になっていたら、そのジョブのジョブ定義で要求しているvCPUsを設定する。

取得：

```Bash
aws batch describe-compute-environments --compute-environment hello-batch-compute-environment
```

desiredvCpusに出てくる。
設定：

```Bash
aws batch submit-job --job-name hello-batch-job --job-queue hello-batch-job-queue --job-definition hello-batch-job-definition:1
```

もちろん実装ではboto3等を使うことになるだろう。
.bashrc,.bashprofileの変更反映

.bashrcなどを変更したときにすぐに反映される方法

一回ターミナルを閉じ直して、もう一度開き直せば反映されますが、コマンドからやるときは

$source ~/.bash_profile　でOK

試しに、コマンド履歴を便利に取り出す関数を導入して見ます（関数に関してはhttps://qiita.com/catfist/items/82ed3df7a0b524aeab69　
の記事をコピペです）

[bash_profileに関数chisを追加]
<img width="718" alt="スクリーンショット 2019-10-30 7.24.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253261/9366a3ec-1c17-57c5-5038-13c499883c95.png">

```bash:.bash_profileの読み込み
 58 07:18:42 ~/Lab_tool  $ vim ~/.bash_profile 
 59 07:20:03 ~/Lab_tool  $ chis
-bash: chis: command not found
 60 07:20:05 ~/Lab_tool  $ source ~/.bash_profile 
 61 07:23:13 ~/Lab_tool  $ chis
source ~/.bash_profile
```

となり、source ~/.bash_profile をする前は使えなかったchisが使えるようになり、直前のコマンドが呼び出せました

source ~/.bash_profile
Pacemaker「ORPHANED FAILED」への対処


Pacemakerでリソース削除時にORPHANED FAILEDが発生した場合の対処例を記載。

## ORPHANED FAILEDの発生

```bash
$ pcs resource delete resource_httpd; 
```

Clusterのステータスを確認したところ、該当のリソースに障害が発生していた。

障害記録があるリソースは削除できない模様。

```bash
$ pcs status

resource_httpd     (ocf::heartbeat:apache):  ORPHANED FAILED test-stb (blocked)

Failed Resource Actions:
* resource_httpd_stop_0 on test-stb 'unknown error' (1): call=86, status=Timed Out, exitreason='',
    last-rc-change='Tue Oct 20 11:57:53 2019', queued=0ms, exec=120004ms
```

## 対処

フェイルカウントをリセットする。

```bash
$ pcs resource failcount reset
```
ペアプロ　お買い物問題

#Rubyアルゴリズム問題
#お買い物プログラムを作ろう

今回作るプログラムはお買い物プログラムです。

#仕様
####仕様は以下のようにしたいと思います。
・商品を繰り返し選択しお買い物カゴに入れることができる
・合計金額が2500円以上で送料無料になる
・合計重量が2000g以上は送料500円になる
・合計重量が2000g未満は送料200円になる

（具体的な数値は自由に変えてもらっても問題ありません）

####用意する品物


| 品物    |価格  |重量 |
|:-------|-----:|:---:|
|さくらんぼ|500円 |200g |
|りんご   |200円 |500g |
|メロン   |1000円|1000g|
（これもある程度自由で大丈夫です）
#回答
https://qiita.com/shintaro_yataki/items/500f7f98388462d46f46
ペアプロ　送料問題　回答編

```ruby:soryo.rb
#商品選択
def purchase(lists, total)
  puts "何を買いますか"
  num = 0
  lists.each do |list|
    puts "#{num}:#{list[:fruit]}"
    num += 1
  end

  select = gets.to_i
  list = lists[select]
  total[0] += list[:price]
  total[1] += list[:weight]
  puts "#{list[:fruit]}を購入しました"
  return total
end

#レジに進む
def register(total)
  total_weight = total[1]
  if total[0] >= 2500
    postage = 0
  elsif total_weight >= 2000
    postage = 500
  else
    postage = 200
  end

  total_price = total[0] + postage
  puts "品物代：#{total[0]}円"
  puts "送料：#{postage}円"
  puts "合計金額：#{total_price}円"
  
  done
end

def done
  puts "またのご利用をお待ちしています"
  exit
end

#商品リスト
lists = [{fruit: "cherry", price: 500, weight: 200}, {fruit: "apple", price: 200, weight: 500}, {fruit: "melon", price: 1000, weight: 1000}]

total = [0, 0]

line = "-------------------------------------------"
puts "いらっしゃいませ！"
puts line
puts "商品"

lists.each do |list|
  puts "#{list[:fruit]}：#{list[:price]}円：重量#{list[:weight]}g"
end

puts line
puts "＊＊＊品物代2500円以上で送料無料です！！＊＊＊"

while true do
  puts "何をしますか？\n番号を選択してください"
  puts "[0]商品を選択する"
  puts "[1]レジに進む"
  puts "[2]買い物をやめる"
  puts line
  num = gets.to_i
  if num == 0
    total = purchase(lists, total) #商品選択へ
  elsif num == 1
    register(total) #レジに進む
  else
    done() #終了
  end

end
```
【忙しい人向け】カップ麺より早く作るDockerでLaravel開発環境構築

コピペするだけ。

```shell-session
git clone https://github.com/ucan-lab/docker-laravel.git
cd docker-laravel

# Makeコマンド用意しています。
make create-project

# or 1コマンドずつ打ちたい人はこちら
mkdir -p src
docker compose build
docker compose up -d
docker compose exec app composer create-project --prefer-dist laravel/laravel .
docker compose exec app php artisan key:generate
docker compose exec app php artisan storage:link
docker compose exec app chmod -R 777 storage bootstrap/cache
docker compose exec app php artisan migrate
```

http://localhost

<img width="917" alt="スクリーンショット 2019-10-31 14.44.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/08adc3bf-3e8a-3286-ed2d-a13a41b38da2.png">

## GitHub

- https://github.com/ucan-lab/docker-laravel
- https://github.com/ucan-lab/docker-laravel/wiki
  - [Nodeのインストール手順](https://github.com/ucan-lab/docker-laravel/wiki/Setup-Node)など載せています。

## 参考

- [最強のLaravel開発環境をDockerを使って構築する【新編集版】](https://qiita.com/ucan-lab/items/5fc1281cd8076c8ac9f4)
- [Laravelの開発環境をDockerを使って構築する](https://qiita.com/ucan-lab/items/17c806973e69792ada99)
- [【初心者向け】20分でLaravel開発環境を爆速構築するDockerハンズオン](https://qiita.com/ucan-lab/items/56c9dc3cf2e6762672f4)
Cloud ComposerとCloudNATで、Airflow WorkerのIPアドレスを固定する


# やりたいこと
Cloud ComposerのAirflow WorkerからのアクセスをIPアドレス固定したい。

# 手順

ComposerのworkerはGKE上で動いているので、[GKEでのCloudNAT](https://cloud.google.com/nat/docs/gke-example)と同じような手順で出来ます。

1. VPC・サブネット作る（[GKEでのCloudNAT](https://cloud.google.com/nat/docs/gke-example)のStep1）
2. CloudNATを設定([GKEでのCloudNATのStep6](https://cloud.google.com/nat/docs/gke-example#step_6_create_a_nat_configuration_using) ）
3. [プライベート IP Cloud Composer 環境](https://cloud.google.com/composer/docs/concepts/private-ip?hl=ja)を作る
    1. Airflowコマンドを使ったりSSHでworkerに入りたい人は、後述の「GKEマスタへのアクセス」の設定が必要


## 細かい注意点
### ComposerのVPCネイティブとプライベートIP環境は**ベータ**
 ので、Composer環境作る時にベータ機能を有効にする必要があります（下図）
![スクリーンショット 2019-10-30 8.24.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311203/58c90b2d-9d6b-e325-7ac9-2ed6da0a1d5f.png)


### Airflowコマンドを使いたい・Airflow workerに入りたい
Composerではgcloud composer environments runで[Airflowのコマンドを実行出来ます](https://cloud.google.com/composer/docs/how-to/accessing/airflow-cli?hl=ja#running_airflow_cli_commands)（※）。
※ 全部のコマンドが実行出来るわけではないです

プライベートIP環境で実行するには、Composer環境を作る時に「外部 IP アドレスを使用して GKE マスターにアクセスする」の設定が[必要](https://cloud.google.com/composer/docs/concepts/private-ip?hl=ja#cluster)です（下図の項目）。
アクセス元のIPアドレスの範囲を設定してあげてください。

kubectlコマンドでAirflow workerに入ったりしたい時にも必要です。

![スクリーンショット 2019-10-30 8.24.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311203/1e9bd6ec-7017-f4a4-39b0-65d8620cd4c7.png)

## 補足
普通のComposer環境ではなく、プライベートIP環境（パブリックIP(external IP)持たない環境）なのは、Cloud NATがパブリックIPを持たないインスタンスからしか[使えない](https://cloud.google.com/nat/docs/overview#nat-not-performed)ためです。
>If your VM has an external IP address, then packets sent from the primary IP address of that interface do not use Cloud NAT.
GASでObjectを生成する

なんだかんだGASでObjectを作成することをやったことがなかったのでメモ

```javascript

function getProductCategories() {
  var namingRuleSheet = book.getSheetByName('命名規則')
  var data = namingRuleSheet.getRange("M9:N").getValues()
  var result = new Object
  data.forEach(function(d) {
    // d=[カテゴリ名, ID] あ、これ普通逆か
    if(d[0]) {
      result[d[0]] = d[1]
    }
  })
  return result
}
```