OmniAICreator/Qiita-1.07M huggingface dataset:
【PHP】array_keysとarray_flipの速度を比較してみた

タイトルの通り、速度検証をしたので、どうやってやったかとその結果を記載します。

# 忙しい人向け結論
array_keysとarray_flipだと、`array_keysのほうが速い`

# 本題
## 経緯

あー特定の文字列が配列のキーに含まれているかチェックしたいなー[^1]

in_arrayだと判定対象はvalueだから違うよなー

そうだ！array_flipでkeyとvalueを逆にすればいいんだ！
[array_flipの公式ドキュメント](https://www.php.net/manual/ja/function.array-flip.php)

``` php

$array = [
    'a' => 'あ',
    'i' => 'い',
    'u' => 'う',
    'e' => 'え',
    'o' => 'お',
];

$needle = 'a';

if (in_array($needle, array_flip($array), true)) {
    // 処理
}
```

よしできた！(*‘∀‘)


あれ、そういえばarray_keysでキーの配列を作ることもできたよな、、、？
むしろこっちのほうが一般的では、、、？
[array_keysの公式ドキュメント](https://www.php.net/manual/ja/function.array-keys.php)

``` php
if (in_array($needle, array_keys($array), true)) {
    // 処理
}
```

こっちでもできた！！！

じゃあ、速度的にはどっちを使ったらいいんだろう？


## 検証

以下のソースコードで検証しました。
説明は適宜コメントアウトで。

``` php

// 実行回数
$count = 1000000;
// 配列から見つけたい文字列
$needle = 'a';
// 検索対象の配列
$array = [
    'a' => 'あ',
    'i' => 'い',
    'u' => 'う',
    'e' => 'え',
    'o' => 'お',
];

// array_keysの速度検証
$st = microtime(true);
for ($i = 0; $i <= $count; $i++) {
    in_array($needle, array_keys($array), true);
}
$end = microtime(true);
$result = '処理：array_keysを' . $count . '回実行' . PHP_EOL;
$result .= '時間：' . ($end - $st) . '秒';
echo $result;

// array_flipの速度検証
$st2 = microtime(true);
for ($i = 0; $i <= $count; $i++) {
    in_array($needle, array_flip($array), true);
}
$end2 = microtime(true);
$result2 = '処理：array_flipを' . $count . '回実行' . PHP_EOL;
$result2 .= '時間：' . ($end2 - $st2) . '秒';
echo $result2;
```
参照した記事は[こちら](https://wemo.tech/1486)

## 検証結果

まず、array_keysの検証結果

``` php:$result
処理：array_keysを1000000回実行 
時間：1.633052110672秒
```

なるほど、100万回で1.6秒かかるとのことです。


続いて、array_flipの検証結果

``` php:$result2
処理：array_flipを1000000回実行 
時間：2.6483287811279秒
```

なんと！こちらは同じ100万回でも2.6秒かかるそうです。

というわけで、結論。

`array_flipよりもarray_keysのほうが速い` 

以上です。ありがとうございました。
何かアドバイス等あればコメントいただけると嬉しいです。


[^1]: 配列のキーに特定の文字列があるかどうかのチェック方法については、今回やろうとしている`in_arrayの第二引数にarray_keysやarray_flipを使うやり方`よりも、`isset`や`array_key_exists`を使った方がわかりやく、`$array`の要素数によってはパフォーマンスもこちらの方がいいとご指摘をいただきました。そのため、本記事では速度比較をした例、という見方をしていただけますと幸いです。
systemd管理サービス一覧のjson形式出力コマンド

```shell
systemctl --type=service | grep .service | sed -E 's/ +/ /g' | sed -E 's/([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +(.*)/{"name":"\1","status":"\4","desc":"\5"},/g' | tr -d '\n' | sed -E 's/(.*),/[\1]/g'
```
yum インストールリストの json形式出力コマンド

```bash
yum list installed | tail -n +2 | sed -E 's/ +/ /g' | sed -E 's/([^ ]*) ([^ ]*) ([^ ]*)/{"name":"\1","version":"\2","repo":"\3"},/g' | tr -d '\n' | sed -E 's/(.*),/[\1]/g'
```
python実行時にオプションを指定する


python実行時にオプションを指定するには、ArgumentParserを使う

```py:option_argparser.py
from argparse import ArgumentParser

def get_option(level):
    argparser = ArgumentParser()
    argparser.add_argument('-l', '--level', type=int,
                           default=level,
                           help='Specify level')
    return argparser.parse_args()

level=1
args = get_option(level)

print('level : ' + str(args.level))
```

実行結果

```
$ python3 option_argparser.py 
level : 1
$ python3 option_argparser.py -l 3
level : 3
$ python3 option_argparser.py --level 3
level : 3
$ python3 option_argparser.py --help
usage: option_argparser.py [-h] [-l LEVEL]

optional arguments:
  -h, --help            show this help message and exit
  -l LEVEL, --level LEVEL
                        Specify level
```

# 参考
[argparse --- コマンドラインオプション、引数、サブコマンドのパーサー](https://docs.python.org/ja/3/library/argparse.html)
[ArgumentParserの使い方を簡単にまとめた](https://qiita.com/kzkadc/items/e4fc7bc9c003de1eb6d0)
module に依存性を注入する

python の場合、module ごとでよければ、簡単に依存性を逆転できる。
`person.py` は `AbstractPerson` の実装に依存しない。

```python:person.py
class AbstractPerson:
    def say(self):
        raise NotImplementedError()


def talk_each():
    person_a = AbstractPerson()
    person_b = AbstractPerson()

    print(person_a.say())
    print(person_b.say())
```

`person` module に依存性を注入する場合は、以下のように書ける。

```python:main.py
import person


class JapanesePerson:
    def say(self):
        return "こんにちは"


class EnglishPerson:
    def say(self):
        return "Hi"


person.AbstractPerson = JapanesePerson
person.talk_each()
# こんにちは
# こんにちは
person.AbstractPerson = EnglishPerson
person.talk_each()
# Hi
# Hi
```

いかにも `python` という感じがする。
PyserialでのBinary送受信

### はじめに

pyserialを使ったBinary送受信について覚えとして記載します。

### PyserialでBinaryを送信する方法
参考：[pyserial(pythonシリアルポート)を使用したバイナリデータ](https://www.366service.com/jp/qa/896caade3e598fc46db4609c44bde780)
この中で、pyserialのSerial.write()メソッドは文字列データのみを送信する。と書かれています。

b"\x00"のような出力になるようにBinary変換したものが送信できます。（「\x」というのは次に続く2文字を16進表記の整数値として解釈することを意味する。)

変換例として
[array – データ型固定のシーケンス](http://ja.pymotw.com/2/array/)を使った方法が書かれています。

```python
import serial
import array

# 送信したい　Binary Data
b = [0xc0, 0x04, 0x00]
print(b)
# 10進数に直されて表示される
# >>>[192, 4, 0]

# PythonのBinaryに変換 arrayを用いた方法
b_data=array.array('B', [0xc0, 0x04, 0x00]).tostring()
print(b_data)
# >>>b'\xc0\x04\x00'

# PythonのBinaryに変換 bytesを用いた方法
b2_data = bytes(b)
print(b2_data)
# >>>b'\xc0\x04\x00'

# 比較するとどちらも同じ。
print(b_data==b2_data)
# >>>True
```
bytes()を用いた方が簡単なので、こちらを用います。
前回の記事にあるTWELITEのBinaryモードでやり取りするときに使うことができます。

#### 送信
```python
# 送信　例えば、
senddata=[0xA5,0x5A,0x80,0x07,0x00,0x00,0x00,0x64,0xFF,0xFF,0x02,0x67]

print(senddata)
# print出力すると10進表記になる
# [65, 90, 128, 7, 1, 0, 0, 100, 255, 255, 2, 103]

# Binaryに変換
send_binary =bytes(senddata) 
# bytearray()でもよい
# send_binary =bytearray(senddata) 

print(send_binary)
# 送信データBinary
# b'\xa5Z\x80\x07\x01\x00\x00d\xff\xff\x02g'

# pyserialで送信
with serial.Serial('COM12', 115200) as ser:
    print('---')
    ser.write(send_binary)
    print('---')

```
#### 受信

```python

with serial.Serial('COM12', 115200) as ser:
    # 読み込むByte数をreadの引数に指定する。
    b_reply = ser.read(23)
    # 全部読み込む場合
    b_reply = ser.read_all()

    print(b_reply)
    # >>> b'\xa5Z\x80\x04\xdb\xa1\x98\x01\xe3\x04\xa5Z\x80\x07\x01\x04\x00\x013<")\x04'

    # structモジュールを使って何Byteの束でどのような型で読み込むか指定する必要がある。
    # 今回は、23Byteを1Byteずつの区切りで読み込む
    # 23BはBが23個並んでいることと同じ。Bは、C言語のunsigned char型で、Pythonでは整数で1Byte

    reply =struct.unpack('23B',b_reply)

    print(reply)
    # >>> 165, 90, 128, 4, 219, 161, 152, 1, 227, 4, 165, 90, 128, 7, 1, 4, 0, 1, 51, 60, 34, 41, 4
    # 最後の4は(EOT)　伝送終了文字（ End-of-Transmission character）
    # Byteの何番目がどの情報を持っているかの仕様により解析する。

```
マルチクラウド時代のAlibaba Cloud活用事例と最新技術 勉強会に参加した

## 開催日程
* 2020年10月15日（木）

## 場所
* オンライン

## 主催
* ソフトバンク

## 申し込み
* https://techplay.jp/event/793418

## 費用
* 無料


## Alibaba Cloudとは
* 阿里巴巴集団が提供する従量課金制、サブスクリプション型のクラウドコンピューティングサービスである
* 2009年9月に設立され、日本でのサービスは2016年12月に開始した
* アジア太平洋地域のランキングが2位
    * 参照：https://www.srgresearch.com/articles/aws-and-alibaba-lead-apac-cloud-market-microsoft-tencent-and-google-chasing-pack

## セッション - Alibaba Cloud導入代表事例
* 中国ユーザへのイベント動画配信システム
    * 課題：日中間のインターネット経由のライブ配信の遅延の問題
    * 効果：ライブ配信機能とCDN機能がワンセットで簡単、速く中国ユーザへ動画配信できる
* AIでの取り組み
    * 家具検索アプリ「Pic Archi」は、画像認識機能で写真を取るとImageSearchのAPI連携で関連画像をすぐ見るかる
    * ゲーム開発や運営活用検証できる

## セッション - 激しいビジネス変化に対応し「継続・拡張」を可能にした Alibaba Cloud の Cloud Native基盤
* Container Service for K8sの特徴
    * クラウドネイティブ環境を支えるAlibaba CloudのマネージドK8sサービス
    * alibaba Cloudのプロダクトと連携
    * ワーカーノードをサポート
    * RAMアカウントと連携し、K8sのリソース制限
    * マネージド、サーバレス
* コンテナイメージのCI/CDパイプライン
    * Dev
        * 開発者はコードをリポジトリへPush
    * Commit
        * いろいろなリジストリーヘwebhookできる
    * Build
        * ビルド、スキャン、リージョン同期、クラスタへデプロイ
    * Deploy
        * イメージを各クラスタへデプロイ
* マネージドされた監視システムのメトリクス収集
    * 専用エージェントからメトリクスを収集
    * Grafanaコンソールが利用可能
    * SMS, Email, Webhookへアラート
    * クラウド内のストレージへデータ保存
TortoiseGitのAzureDevOpsのアカウント切り替え方法

# はじめに
AzureDevOpsとTortoiseGitを組み合わせた場合、TortoiseGitに登録しているユーザを切り替える場合の方法手順を説明します。

# 設定
- コントロール=>資格情報マネージャー　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47172/b09dba2b-1621-874e-0fe0-57f5c1676224.png)

- Windows資格情報　をクリック
下にスクロールして、AzureDevOpsのURLを探す
https://*****.visualstudio.com を探す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47172/3900edd7-60c5-da0f-68f8-0bd1eed0d437.png)

- ▽マークを開いて削除を押す。
![Screenshot_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47172/1cab2393-cbdf-265c-36d4-f69f950249ce.png)

- TortoiseGitをもう一度開いてCloneする。
【Flutter】プロジェクトを新規作成する方法

## 概要
Android StudioでFlutterのプロジェクトを新たに作成する方法と作成後、仮想デバイス上で実行する方法を記します。

## 前提
- Flutter SDKがインストールされている
  https://flutter.dev/docs/get-started/install

- Android Studioで作業

## 手順

### プロジェクト作成

1. File > New > New Flutter Project

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230436/22d76ead-15f6-445e-1a66-b7698ef1dada.png)

2. Flutter Application を選択してNext

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230436/e3c80950-511b-93d4-e2af-665edafd37df.png)

3. プロジェクトの名前やSDKのパスを設定してNext

![colec [C__Users_mibu1_colec-mobile_flutter_colec] - ..._lib_component_collection_list_elem.dart [colec] - Android Studio 2020_10_17 17_58_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230436/20c20026-4db7-2553-0e6b-18e3bd646ba2.png)

4. パッケージ名（com.example.appのような形式が一般的）を入力してFinish

![colec [C__Users_mibu1_colec-mobile_flutter_colec] - ..._lib_component_collection_list_elem.dart [colec] - Android Studio 2020_10_17 18_01_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230436/5ebce585-4086-fd49-9776-c5135317f515.png)

### 仮想デバイスで動作確認

1. 画面右上のAVD Managerのアイコンをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230436/b68bdcf1-f0c9-053f-e834-13e411f55cf1.png)

2. 仮想デバイスのリストが表示されるので、Actionsの`＞`をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230436/86f1b0e0-8282-1099-fcee-1ad81bc00fe6.png)

※仮想デバイスが作成されていない場合は、Create vertual Deviceをクリックして仮想デバイスを追加します。


3. 仮想デバイスが起動したら、画面上部の実行するデバイスとエントリーポイント（main.dart）を指定して`＞`をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230436/06dc5ec6-c693-7a0d-6088-1a6192c1e710.png)

4. 仮想デバイス上でアプリが起動します！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230436/6a958e31-37b5-d94b-7c34-41026c29ea9c.png)
Ubuntu 20.04にSambaを使用してファイルサーバを立てる

Ubuntuに、Sambaを使ってゲストアカウントで接続できるファイルサーバをたてます。

## 環境
Ubuntu 20.04を使いました。

```
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 20.04.1 LTS
Release:	20.04
Codename:	focal
```

## 1. sambaのインストール

`apt install`でSambaをインストールします

```
$ sudo apt install samba
```

version 4.11がインストールされました。

```
$ samba -V
Version 4.11.6-Ubuntu
```

## 2. 共有するディレクトリの作成

任意の場所に共有用のディレクトリを作成します。

```
$ cd /home
$ mkdir share
$ chmod 777 share
```

## 3. sambaサーバの設定

`smb.conf`を編集して、sambaサーバの設定をしていきます。

```
$ sudo vi /etc/samba/smb.conf
```

この辺はよく分かっていないので、ネットにある記事を参考に設定しました。

```
[global]
    unix charset = UTF-8
    dos charset = CP932
    display charset = UTF-8

    bind interface only = yes
    map to guest = Bad User

[public]
    comment = public
    path = /home/share
    public = yes
    writable = yes
    printable = no
    create mode = 0777
    directory mode = 0777
```

ゲストアカウントでの接続するため、`map to guest = Bad User`にしてログインに失敗したユーザを全てゲストアカウントにします。

また共有するディレクトリは、`public = yes`（もしくは`guest ok = yes`）に設定しておきます。

## 4. サーバの起動

```
$ sudo service smbd start
```

## 5. 自動起動設定

必要に応じて自動起動の設定をしておきます。

```
$ sudo sytemctl enable smbd
```

## 5. macからの接続

Finderでサーバへ接続を開く、もしくは`Cmd + k`し、サーバアドレスに

```
smb://<ip address or hostnanme>
```

と、入力すれば接続できます。
Golangはじめて物語(第4話: ローカルリポジトリで共通モジュール管理編)

# はじめに
Golangシリーズ4回目。
過去の3回はこちら。

- [Golangはじめて物語(APIGateway＋Lambdaといっしょ編)](https://qiita.com/neruneruo/items/1ef52f908e4497103a59)
- [Golangはじめて物語(第2話: Gin＋ECS＋Fargateといっしょ編)](https://qiita.com/neruneruo/items/fe292262836ac068e2ea)
- [Golangはじめて物語(第3話: CodePipeline+SAM+LambdaでCI/CD編)](https://qiita.com/neruneruo/items/8112490136775e6abc39)

さて、Golangの公開ライブラリは `import` で GitHub から持ってくるのが一般的だが、開発をしていると当然「共通のモジュールを作らないといけないけど、GitHubには社内規約上ソース置いちゃいけないし……」と悩むことが出てくる。色々とツッコみたくなるかもしれないが、出てくると言ったら出てくるのである。

Javaであれば、CodeArtifactとかを使ってローカルリポジトリをAWSに任せることもできるが、Golangには対応していない。というか対応する必要がない。Golangであれば、CodeCommitをそのまま使えば良いのである。

# 共通モジュール側
CodeCommitで以下のようなディレクトリ構成のモジュールを作る。
今回は、簡単な標準出力するだけのオレオレロガーを作ってみよう。

```
.
├── mylogger
│   ├── go.mod
│   └── mylogger.go
└── README.md
```

```golang:mylogger.go
package mylogger

import (
    "log"
)

func OutputLog(str string) {
    log.Printf(str)
}
```

```go.mod
module git-codecommit.[リージョン名].amazonaws.com/v1/repos/[リポジトリ名].git/mylogger

go 1.13

require (
)
```

ポイントは、```module``` のリポジトリ名の後ろに ```.git``` を付けておくことだ。
これを忘れると上手く動かない。

# 呼び出し側
呼び出し側では、以下のように ```import``` をする。

```golang:main.goなど
import (
    "git-codecommit.[リージョン名].amazonaws.com/v1/repos/[リポジトリ名].git/mylogger"
)
```

go.mod を使っていれば、ビルド時に

```golang:go.mod
require (
	git-codecommit.[リージョン名].amazonaws.com/v1/repos/[リポジトリ名].git/mylogger v0.0.0-20201011112107-e103759ebd6b
)
```

な感じで良い感じにバージョンを埋めてくれる。
※もちろん、必要に応じてバージョン指定する。

ビルド時は

```shell
$ export GOPRIVATE=git-codecommit.[リージョン名].amazonaws.com,direct
```

としておこう。こうしないと、プライベートリポジトリをうまく見に行ってくれなくてビルドが失敗する。

# CodePipeline(CodeBuild)に組み込む場合
これも基本はローカルビルドと変わらない。

Buildspecの環境変数で、プライベートリポジトリを設定してあげる。

```YAML:buildspec.yml(抜粋)
env:
  variables:
    GOPRIVATE: git-codecommit.[リージョン名].amazonaws.com,direct
````

また、CodeBuildではCodeCommitに対してIAMロールで認証をするので、```pre-build``` で以下の設定をしておこう。

```YAML:buildspec.yml(抜粋)
  pre_build:
    commands:
      - git config --global credential.helper '!aws codecommit credential-helper $@'
      - git config --global credential.UseHttpPath true
```

CodePipelineを使う場合、ソースコードの取得はCodePipeline側で行ってS3バケットに格納したものをCodeBuildに連携してくるため、通常はCodeCommitにアクセスする権限は不要だが、この方法を使う場合は、CodeBuildが直接CodeCommitを見に行くため、Readアクセス権が必要になる。CodeBuildのサービスロールに ```AWSCodeCommitReadOnly``` 相当の権限を付与しておこう(絞ろうと思えばもっと絞れると思うが、力尽きた……)

余談ではあるが、CodeBuildのローカルキャッシュを扱う場合、Go言語の場合はデフォルトでは以下のパスになるので設定しておくと良い。

```YAML:buildspec.yml(抜粋)
cache:
  paths:
    - '/go/pkg/mod/**/*'
```

これで、共通ライブラリも制約なく自由に作れるようになったぞ！
firebaseでpull request ごとにpreviewをdeployするgithub action

# 概要
firebaseで、spaをnetlify やvercel のようにプルリクごとにURLを変えてdeployしたい。


# how to


## firebaseの初期化
[公式](https://firebase.google.com/docs/hosting/quickstart)
firebase toolをグローバルにinstall
今回はdeployする directoryはdistをしていします。(firebaseのdefaultはpublic)

```shell

npm i -g firebase-tools
firebase login
firebase hosting #deloyするdirectoryをdist にする
```

## channel deployコマンドをpackage.jsonに追加

previewようのdeployは[channel deploy](https://firebase.google.com/docs/hosting/manage-hosting-resources)というコマンド使います。
そのため、以下のように scriptに追加します。

```json

{
  "name": "firebase deploy app",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "dev": "nuxt-ts",
    "build": "nuxt-ts build",
    "start": "nuxt-ts start",
    "generate": "nuxt-ts generate",
    "lint:js": "eslint --ext .js,.vue --ignore-path .gitignore .",
    "lint:style": "stylelint **/*.{vue,css} --ignore-path .gitignore",
    "lint": "yarn lint:js && yarn lint:style",
    "test": "jest",
    "channel-deploy": "firebase hosting:channel:deploy" ←# 追加
  },
```

## github workflowを設定する
以下のように設定します。

```yml:firebase-deploy.yml
name: CI

on: [push]

jobs:
  FrontDeploy:
    name: FrontDeploy
    runs-on: ubuntu-latest
    steps:
    - name: Checkout Repo
      uses: actions/checkout@main
    - name: setup Node
      uses: actions/setup-node@v1
      with:
        node-version: '12'
        registry-url: 'https://registry.npmjs.org'
    - name: Install Dependencies
      run: yarn
    - name: Build
      run: yarn build
    - name: deploy to Firebase Hosting
      shell: bash
      run:  yarn channel-deploy $(echo ${GITHUB_REF#refs/heads/}) --token=${{ secrets.FIREBASE_TOKEN }}

```

こちらでは、branch名を取得しています。

```
$(echo ${GITHUB_REF#refs/heads/})
```

## tokenを取得
以下コマンドで、tokenを取得できます

```
firebase login:ci
```

取得したtokenを`FIREBASE_TOKEN` にいれましょう。

![Secrets.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112515/8e4ea22d-2fdb-4b25-8de0-3401f31c24ea.png)

以上でdeployできるはずです！


### twitterもフォローよろしくおねがいします。 ！
https://twitter.com/yoshixj
Excel VBAでWordの目次を取得する

#経緯
最近Excel業務が多くなり、Wordの目次をExcelへ取り込んで編集する業務があったので、ExcelにWordの目次をばぁーっと取り込んで、Excelを自動で編集できるといいなと思いVBAを作成しました。  
すごいピンポイントな内容ですが、Wordの目次取得方法を履歴として残しておこうと思います。  
 
##Excel VBAコード
```
'#######################################################################
' Excel VBAでWordの目次(Table of Contents)を取得
' ※参照設定で『Microsoft Word 16.0 Object Library』にチェックが必要です
' ※今回は、取得したい目次のword名が『wd_sample.docx』であり、
' 　本Excelと同ディレクトリに保管してあるという前提です
'#######################################################################
Sub GetWordToc()

'--- 変数準備 ---
    Dim wdApp As Word.Application
    Dim path As String
    Dim wdDoc As Word.Document

'--- Wordアプリを起動する ---
    Set wdApp = New Word.Application
    wdApp.Visible = True
    
'--- Word文書を開く ---
    'ファイルを開く
    path = ThisWorkbook.path
    
    '文書ファイルを開く
    Set wdDoc = wdApp.Documents.Open(path & "\wd_sample.docx")
    
    MsgBox "Open a Word Document"
       
    'Word目次をExcelへ書き出す
    With wdDoc.Paragraphs
        Dim i, j As Integer
        j = 1
        'Wordの1段落目から最後の段落まで繰り返す
        For i = 1 To .Count
            'もしi番目の段落のスタイルが目次のスタイルであれば、Excelへ書き込みをする
            If .Item(i).Style Like "目次 #" Then
                Cells(j, 1).Value = .Item(i).Range.Text
                j = j + 1
            End If
        Next i
    End With    
    
'--- Word文書を閉じる ---
    '文書ファイルを閉じる
    wdDoc.Close
    'オブジェクト変数が何も参照していない状態へ
    Set wdDoc = Nothing
    
'--- Wordアプリを終了する ---
    wdApp.Quit
    Set wdApp = Nothing

End Sub

```
##ポイント
Wordの[Paragraphsオブジェクトのstyleプロパティ](https://docs.microsoft.com/ja-jp/office/vba/api/word.paragraphs.style)を使う  
これを使うと目次の段落部分は目次のスタイルを返してくれます。目次のスタイルであるならば、目次を記載するとコードを書けば、Wordの目次をExcelに書き込めるというシンプルな内容です。  
ここら辺がわかってくると、Excel VBAでWordの情報が結構抽出できるなぁなんて思いました。  

##思ったこと
VBAを勉強していたら、VBAはここ何年もずーっとバージョンアップしてないので、VBAよりもpythonを学習してExcel自動化した方がいいですよって耳にしました。なので、pythonも勉強していこうと思いました。  
だけど、VBAって予想以上に多くのことができるので大変驚きました。  
私は昨年まで事務職やっていたのですが、当時VBAでこんなのできればよかったなぁなんてのが結構あります。  
VBAもまだまだ知らないこといっぱいあるので引き続きVBAも勉強していこうと思ってます。
Laravel　アウトプット

# npm run watch-poll
npm run watch-pollは、Laravelをインストールした際に初めから存在するpackage.json内に定義されているコマンドのひとつです。

このコマンドは、各JavaScriptファイルを常に監視し、編集されたJavaScriptが保存されると自動的にLaravel Mixによるトランスパイルを行います。
JavaScriptの編集・保存の都度、手動でトランスパイルする必要が無くなり、開発を効率化します。
なお、npm run watch-pollを起動中のターミナルでは他のことはできませんので、何か他のコマンドを実行したい場合は別のターミナル画面を使うようにしてください。
また、npm run watch-pollを終了させる場合はcontrol + cを押してください。

# clickLikeメソッド
![スクリーンショット 2020-10-17 16.35.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663122/9e86bbcb-ce9a-82da-f6c9-ee9264c67197.png)
ユーザーが未ログインであれば警告のポップアップを出して、早期リターンでメソッドを終了させるようにしています。

# passedValidationメソッド
フォームリクエストのバリデーションが成功した後に自動的に呼ばれるメソッドです。
バリデーション成功後に何か処理をしたければ、ここに処理を書きます。
![スクリーンショット 2020-10-17 18.16.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663122/ef0a193f-c50e-8470-568e-819961bd3751.png)
Rails if文とunlessの混合条件式の作成

最終課題に向けて調整を行いました。
その際に、条件式をifとunlessの両方を使用するという特殊なパターンに
チャレンジしてみました。備忘録として投稿させて頂きます。

今回はhamlにて記述しています。

```ruby:sample.rb
#viewファイルにて

.item-show-page__link-btn
        -if @item.buyers.present?
          %p SOLD OUT
        -else
          - unless user_signed_in? && @item.user_id == current_user.id
            = link_to purchase_item_path(@item.id), class: "item-show-page__link" do
              購入画面へ
          - else
            %p 出品者は購入できません
```
メソッドの中身
@item 出品情報が入っています。
buyers 購入した履歴のメソッドになります。

#解説
if〜else
もし購入した履歴のIDが存在したらSOLD OUTを表示

unless~else
```if文のelseの中に入れ子として格納```しています。そこからunlessの条件式を入れています。
もし出品した商品とユーザーIDが一致しない場合は購入画面に遷移するリンクを出現。
そうでない場合は「出品者は購入できません」と出現させる。


以上となります。
Firebase Admin SDKでGoogle Cloud Storageに直接画像をアップロードする

## 概要
フロント側からFirebase SDKを利用して画像をアップロードするのではなく、サーバー側でFirebase Admin SDKを利用して画像を直接アップロードする方法に関して試行錯誤したので、備忘録として残す

## 前提
### Firebase SDKで画像をアップロードするには
以下の公式ドキュメントに書かれているように、Firebas SDKを利用して、Blob, File,バイト配列など様々な形式からファイルをアップロードすることができる
ただし、サーバー側ではFirebase SDKは使えず、Firebase Admin SDKを利用する必要がある

```typescript
// Fileからアップロードする例
async uploadFile(file: File) {
      const path = 'cloud_storage_path';

      try {
        const ref = this.$firebase.storage().ref();
        const imgRef = ref.child(path);
        await imgRef.put(file);
      } catch (err) {
        console.error(err);
        alert('画像のアップロードに失敗しました');
      }
    }
  }
```

https://firebase.google.com/docs/storage/web/upload-files?hl=ja

### Firebase Admin SDKで画像をアップロードするには
Firebase Admin SDKでは

- [サーバー内にローカルファイルが存在する状態でGoogle Cloud Storageにアップロードする](https://googleapis.dev/nodejs/storage/latest/Bucket.html#upload)
- [直接Google Cloud Storageにアップロードする](https://googleapis.dev/nodejs/storage/latest/File.html#save)

という２つの方法がある
今回はローカルに一時ファイルを作成せずに、直接アップロードする方法を採用する


## Firebase Admin SDKでGoogle Cloud Storageに直接ファイルをアップロードする方法
結果としては以下のコードで直接ファイルをアップロードを実現できた

### サーバー側
```typescript
async uploadFile(content: StorageUploadContent) {
    try {
      const bucket = admin.storage().bucket('bucket_name');
      const file = bucket.file('cloud_storage_path');
      const buffer = Buffer.from(content.file, 'base64');

      await file.save(buffer, {
        metadata: {
          contentType: content.type,
        },
      });
    } catch (err) {
      console.error(err);
      throw err;
    }
  }
```

### フロント側
```typescript
async uploadFile(file: File) {
      const path = 'cloud_storage_path';
      const reader = new FileReader();

      reader.onload = async () => {
        const arrayBuffer = new Uint8Array(reader.result as ArrayBuffer);
        // ArrayBufferからbase64文字列に変換
        const base64 = btoa(
          arrayBuffer.reduce((p, c) => {
            return p + String.fromCharCode(c);
          }, '')
        );
        const content: StorageUploadContent = { file: base64, type: file.type, path };

        try {
　　　　　　// 自前で作成したAPIを叩く
          await this.$storage.uploadContent(content);
        } catch (err) {
          console.error(err);
          alert('画像のアップロードに失敗しました');
        }
      };

      await reader.readAsArrayBuffer(file);
    }
```

## 詰まったところ
### File型ではFile.save()ができない
Firebase SDK同様にFile型をそのまま渡してアップロードしようとしていたが、
`TypeError: The "chunk" argument must be one of type string or Buffer. Received type object...`
というエラーが出るので、File型ではアップロードができない

### File型をバイナリ文字列でアップロードすると画像がうまく保存されない
File型をFileReader.readAsBinaryString()でバイナリ文字列に変換してアップロードしたところ、アップロードには成功するが画像が表示されない

### File型をbase64文字列でアップロードすると画像がうまく保存されない
バイナリ文字列に変換した場合と同様の結果となった
`must be one of type string`とはどんな文字列なんだろか？
結果としてはbase64文字列をフロント側から渡して、サーバー側でデコードしてFile.save()に渡すようにした
UnityのStandardAssetsで、ThirdPersonControllerが機能しなかった原因はBuildSettingsのPlatform選択にあった

##起きていたこと
Unityでキャラクターを動かしたくてStandardAssetsをインポートしました。
ThirdPersonControllerをヒエラルキーにドラッグアンドドロップした後、早速キャラクターを動かそうとしてみたのですが、

- 矢印コントローラーを押下しても移動ができない
- スペースキーを押下してもジャンプしない
- しゃがむ(cキー)事だけできる

という状態でした。
![isan.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198412/3479f92b-66e5-d7bc-ee99-512750401121.gif)
しゃがむことしかできないイーサン


##原因
Build SettingsのPlatformがAndroidになっていた。
![build-settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198412/429c4cf2-ea1c-bfa2-fc0c-d8f3362e640f.png)

PCに変更したところ、矢印キー押下でキャラクターが動くようになりました。

##StandardAssetsを、スマホ時のキャラクター操作に使う場合はジョイステックを表示することになる
元々は、スマホ時にフリック,スワイプでキャラクターを操作したくてStandardAssetsを利用しました。
ですが調べて見たところ、StandardAssetsでスマホの操作を行う場合はジョイスティックによる操作になるみたいでした。
なのでそもそもStandardAssetsを利用しない方向となりました。
参考記事: [Unity5版Standard Assetsを使って仮想ジョイスティックを実装
](https://qiita.com/cabbage/items/7836efaa04bbb037b086)
Golangの環境構築【goenv】

##goenvとは
goenvはGoのバージョン管理バージョン管理ツールです。

##goenvのインストール
Home brewの場合

```
$ brew install goenv
```

gitの場合
[goenvのinstallation](https://github.com/syndbg/goenv/blob/master/INSTALL.md)

```
$ git clone https://github.com/syndbg/goenv.git ~/.goenv
```

##goenvのPATHを通す
設定ファイルにpathを記述します。（自身の使用しているシェルに記述）

```
$ echo 'export GOENV_ROOT="$HOME/.goenv"' >> ~/.zshrc
$ echo 'export PATH="$GOENV_ROOT/bin:$PATH"' >> ~/.zshrc
$ echo 'eval "$(goenv init -)"' >> ~/.zshrc

$ source ~/.zshrc   //変更を更新
```

```
$ goenv -v
goenv 2.0.0beta11
```

バージョンが確認できたら完了です。

##Goをインストール
下記のコマンドでインストールできるバージョンのリストを表示

```
$ goenv install -l
1.2.2
  1.3.0
  1.3.1
  〜
  1.15rc2
  1.15.1
  1.15.2
```

任意のバージョンをインストールします。

```
$ goenv install 1.**.*
```

##GoのPATHを通す

```~/.zshrc
$ echo 'export PATH="$GOROOT/bin:$PATH"' >> ~/.zshrc
$ echo 'export PATH="$PATH:$GOPATH/bin"' >> ~/.zshrc

$ source ~/.zshrc
```

##使用するバージョンを選択
インストールしたバージョンをglobalに設定します。また、バージョンへの切り替えとか。

```
$goenv global 1.**.*
```

```
$ go version
go version go1.**.* darwin/amd64
```

バージョンが確認できたら完了です。

##VSCodeの環境構築
まずGoのプラグインをインストールします。
![スクリーンショット 2020-10-17 17.06.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702435/b8f19460-fd1e-e415-68e9-e845ce41838b.png)

##Toolのインストール
　次に、便利なtoolたちをインストールしていきます。まず、設定を開き```go.use language server```と検索してチェックがついているか確認します。
　確認したら```shift + ⌘ + P```ですべてのコマンドの表示を開き、```Go: Install/Update Tools```と打ちこんだら```gocode```と```gocode-gomod```以外（コードの補完機能はgoplsで行うため）を選択してインストールします。もし、ここにgoplsがなければ検索タブにgoplsと打ってみてください。
![スクリーンショット 2020-10-17 17.21.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702435/665e6fac-2c3f-c9af-d67e-49e2a69d2701.png)

##任意でsettings.jsonの設定
インストールが終わったら、下記をsettings.jsonに追記します。

```settings.json
"go.useLanguageServer": true,
    "[go]": {
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
            "source.organizeImports": true,
        },
        "editor.snippetSuggestions": "none"
    },
    "gopls": {
        "hoverKind": "SynopsisDocumentation",
        "usePlaceholders": true,
        "linkTarget": "pkg.go.dev",
        "staticcheck": false,        
        "completionDocumentation": true,        
        "completeUnimported": true,        
        "deepCompletion": true
    },
    "files.autoSave": "afterDelay"
```
以上で完了です！
Neo4j 4.1.3をcentOSにインストール

neo4j 4.1.3をcentosにインストールするメモ

##java11をインストール

```
# yum install -y java-11-openjdk
```

##cypher-shell をインストール

```
# curl -O https://dist.neo4j.org/cypher-shell/cypher-shell-4.1.2-1.noarch.rpm
# rpm -U cypher-shell-4.1.2-1.noarch.rpm
```

##neo4jをインストール
```
#curl -O https://dist.neo4j.org/rpm/neo4j-4.1.3-1.noarch.rpm
# rpm -U neo4j-4.1.3-1.noarch.rpm
```

###バージョン確認
javaが複数バージョン入ってたりするとエラーになったりしまっせ！

```
# neo4j version
neo4j 4.1.3
```

###もろもろ設定

```
sudo vi /etc/systemd/user.conf
```

```/etc/systemd/user.conf
[Manager]
...
DefaultLimitNOFILE=60000
```

```
sudo vi /etc/security/limits.conf
```

```/etc/security/limits.conf
neo4j	soft	nofile	60000
neo4j	hard	nofile	60000
```

```
sudo systemctl daemon-reload
```

※外部から接続する場合は下記設定

```
sudo vi /etc/neo4j/neo4j.conf
```

```/etc/neo4j/neo4j.conf
dbms.connector.bolt.address=0.0.0.0:7687
dbms.connector.https.address=<サーバーのIPアドレス>:7474
```
※7687と7474ポートを開放してください！

###neo4j開始
```
sudo neo4j start
```

おわり。
[PHP]データ記述言語と配列の対応

#基本的なこと

PHPにはデータの格納手段に配列(Array)というものがあります。配列については山ほど資料があるので`Array やりたいこと`で調べたらすぐに出てきます。それぐらいに汎用性に優れ、多くの場面で使用されています。
そんな配列データを、ファイルなどに保存する機会は少なくありません。
そんなとき、読み込んだ時に元の配列のデータと同じにするために、**データ記述言語**が存在します。
データ記述言語とは主に`JSON`や`YAML`などのことです。データを指定の形式通りに記述し保存することで、その形式に従って読めば保存したデータを完全に得ることができます。

#配列の構造について理解する

配列は同じ用途の複数の「値」を1つのグループとして扱うためにあります。しかし、その値をさらに分類しておきたい場合は、分類名を「キー」としてその中にデータを格納することがあります。
キーがある配列は特別に「連想配列」といいます。PHPでは連想配列と普通の配列を区別せずに、「Array」として扱います。

##キー

キーは**要素を並列する場合には省略**します。その場合、処理上ではキーには`0, 1, 2...`と連番が付されます。
PHPでは、キーに使用できるのは**整数(int)か文字列(string)のみ**です。**それ以外をキーにすると、整数または文字列に変換(`toString()`)して格納されます。この変換の処理によっては、キーを正しく区別できないことがあります。**

##値

値には、どんなオブジェクトも格納できます。ですが、**JSONなどのテキストファイルに保存する際はこれもまた整数または文字列に変換されます。**データ記述言語に保存する配列は、必ず整数と文字列で構成する必要があります。

値に配列を入れることができます。これを「多次元配列」といい、入れ子のようにデータを記述できます。


##配列のサンプル

+ 一般的な配列(下記の2例は混ぜることもできる)

```php
$array = ["key1" => "value1", "key2" => "value2", "key3" => "value3"];
// "key1" => "value1", "key2" => "value2", "key3" => "value3"

$array = ["value1", "value2", "value3"];
// 0 => "value1", 1 => "value2", 2 => "value3"
```

+ 多次元配列(書き方は一般的な配列と同じ。値にまた配列を入れているだけ)

```php
$array = [
  "keyA" => [
    "key1" => "value1",
    "key2" => "value2"
  ],
  "keyB" => [
    "key1" => "value3",
    "key2" => "value4"
  ]
];
```

##値の参照

作った配列から値にアクセスするには、`配列[キー]`と入力します。

```php
$array = [
  "keyA" => [
    "key1" => "value1",
    "key2" => "value2"
  ],
  "keyB" => [
    "key1" => "value3",
    "key2" => "value4"
  ]
];

// $array["keyA"] は ["key1" => "value1", "key2" => "value2"]
// $array["keyB"]["key2"] は "value4"
```

#データ記述言語の形式にする

前述のとおり、PHPは連想配列であるかを**区別しない**ですが、主なデータ記述言語はそれらを**区別する**ので、その点に気を使わなければいけません。
次のような例を使います。これは図書館の十進分類法を参考にしました。本を細かく分類するコードです。

|分野名|コード|分類名||分野名|コード|分類名|
|:---:|:---:|---|---|:---:|:---:|---|
|産業|0|産業||言語|0|言語|
|産業|1|農業||言語|1|日本語|
|産業|2|園芸||言語|2|中国語・その他の東洋の諸言語|
|産業|3|蚕糸業||言語|3|英語|
|産業|4|畜産業・獣医学||言語|4|ドイツ語|

上の表を配列にする1つの例です。

```php
$bunrui = [
  "産業" => [
    "産業", "農業", "園芸", "蚕糸業", "畜産業・獣医学"
  ],
  "言語" => [
    "言語", "日本語", "中国語・その他の東洋の諸言語", "英語", "ドイツ語"
  ]
];

// $bunrui["産業"] は ["産業", "農業", "園芸", "蚕糸業", "畜産業・獣医学"]
// $bunrui["言語"][1] は "日本語"
```

`$bunrui`は連想配列です。しかし、`$bunrui["産業"]`や`$bunrui["言語"]`は連想配列ではありません。

これをJSONとYAMLにそれぞれ変換してみましょう。結果は以下の通りです。

##JSON

```json:JSON
{
  "産業": [
    "産業",
    "農業",
    "園芸",
    "蚕糸業",
    "畜産業・獣医学"
  ],
  "言語": [
    "言語",
    "日本語",
    "中国語・その他の東洋の諸言語",
    "英語",
    "ドイツ語"
  ]
}
```

JSONでは、連想配列は`{キー: 値}`の形、その他配列は`[値, 値, 値...]`の形になります。

##YAML

```yaml:YAML
---
産業:
- 産業
- 農業
- 園芸
- 蚕糸業
- 畜産業・獣医学
言語:
- 言語
- 日本語
- 中国語・その他の東洋の諸言語
- 英語
- ドイツ語
...
```

YAMLでは、連想配列は`キー: 値`の形、その他配列は

> ```yaml
- 値
- 値
- 値
```

の形になります。YAMLは括弧がないので少しわかりにくいです。
ただし、ほとんどの文字列は`"`(クオーテーション)で囲まなくていいので、楽ではあります。

#ということで

PHPの配列データをデータ記述言語に変換するフォーマットを、構造を説明しつつ解説してみました。
どういう場面に連想配列にするか、どういうデータの形式にするかをよく考えて作ってみてください。

#さいごに

phpのリファレンス最強伝説を残しておきます。
**[php.netを見ろ！！！！！！！！！！！！！読むんだ今すぐ！！！！！！！！！！！！！！！！！！！！！！！](https://www.php.net/manual/ja/)**
監視とは

## 勉強前イメージ

生きてるってことの確認？
ちゃんと動いてるってことを確認する

## 調査

### 監視とは

`かんし【監視】`
`悪いことが起きないように見張ること`

様々な監視があるかと思いますが、今回はネットワーク監視・サーバ監視の観点で調査をしてみようと思います。

### ネットワーク監視・サーバ監視

#### ネットワーク監視とは

ネットワークにトラブルが発生していないことを確認します。
基本的にはネットワー経路・接続の問題をチェックします

#### サーバ監視

サーバ機器や、サーバで稼働しているミドルウェアが正常に動作していることを確認します。
HDDの容量・メモリやCPUの使用率などだったり、ミドルウェアのサービス起動のチェックをします。


- 死活監視
	- ネットワークが通信できることをチェックします
	- pingコマンドなどで監視を行います
- 経路監視
	- ネットワークに問題がなくてもトラフィック量が多くてもレスポンスが遅くなってしまいます
- 遅延監視
	- ネットワークに問題がなくても、レスポンスが遅くなる場合があります
	- 定期的に対象サイトにアクセスをし、アクセスの時間をチェックします
- 状態監視
	- 現在は特に問題がなくても、今後起こりうる異常を検知します
	- 機器のリソースを監視し、「このままほっておいたら大変なことになる」と言うことに対して対処します
	- 例えば、DBサーバのデータ容量や、サーバのメモリ量などです。


### 監視方法

#### リモートサービスを使う

リモート監視サービスにも色々あると思いますが、
外部からのみ監視　と、 内部にエージェントを立てて監視する方法
前者に関しては、ネットワークに入れないので基本的には外部に公開される箇所のみの監視となり、
種類が少ないですが、導入にあまり手間がかかりません
後者に関しては、内部にエージェントを立ててそのエージェントがデータを送信するので外部からのみの監視より種類が多く取れますが、外部との接続経路を作成したりして導入に手間がかかります。

#### 自分で監視サーバを立てて運用を行う

自分でネットワーク内に監視サーバを立てる方法。
リモートサービスを使用するより、より導入の手間がかかりますが、リモートサービスでは取得できないような特定のデータまで取得することができます。
ただし、手間がかかる・運用しないといけないサーバが増えます。


## 勉強後確認

監視の種類がありすぎなのと、ネットワーク監視・サーバ監視が結構曖昧なイメージ。
前に監視サービスを使ってみたことあるけど、結構いいなぁって思ったけど自分の好きにはできなかった(多分できるサービスもあると思うけど....)


## 参考

- [監視項目一覧](https://www.fl-ops.com/monitor)
- [ネットワーク監視とサーバ監視の違いとは？両者を詳しく解説！](https://it-trend.jp/network_monitoring/article/44-0007)
- [ネットワーク監視とは？必要性・監視対象・項目・方法の種類 - システム比較も](https://boxil.jp/mag/a2673/#2673-12)
【2021年版】Macを指定した時間に強制シャットダウンさせる方法

ついついPCを触りすぎてしまった…。そんな経験はないでしょうか。
その時に、「指定した時間に自動的にPCがシャットダウンしてくれたら触りすぎないのに…」と思ったことはないでしょうか。
これを解決する、指定した時間にPCを強制シャットダウンさせる方法についてまとめました。

# 動作環境
- macOS Catalina 10.15.7

# 設定方法
cronというものを使用します。
> cronとは、多くのUNIX系OSで標準的に利用される常駐プログラム（デーモン）の一種で、利用者の設定したスケジュールに従って指定されたプログラムを定期的に起動してくれるもの。

http://e-words.jp/w/cron.html

まずはターミナルを開き、以下のコマンドを実行します。

```
sudo crontab -e 
```


テキストエディタが開くので、指定時間になったらシャットダウンするようにファイルに記載します。
例として、毎日23時にシャットダウンする場合は以下です。

```
0 23 * * * /sbin/shutdown -h now
```

追記：**以下は23:00〜23:59まで1分毎にシャットダウンを実行する設定でした。うまく使えばやりすぎ防止に便利ですが、緊急時にPCを使いたいときなど不便になることもあるので、気をつけて使用してください。**

```
* 23 * * * /sbin/shutdown -h now
```

cronの詳しい書き方については以下を見てください。
[クーロン(cron)をさわってみるお](https://qiita.com/katsukii/items/d5f90a6e4592d1414f99)

最後に保存して終了します。
これで指定した時間に強制シャットダウンされます。

# 止める方法
設定するときと同じく、以下のコマンドを実行して、

```
sudo crontab -e 
```
以下のようにしてコメントアウトします。

```
# * 23 * * * /sbin/shutdown -h now
```


# 「省エネルギー」ではダメなの？
Macには標準アプリとしてシステム環境設定から起動できる「省エネルギー」というものがあります。
このアプリに指定した時間にシャットダウンする機能があるので、これを使えばいいのではないかと思うかもしれません。
ですが、「省エネルギー」には欠点があり、**指定した時間になるとダイアログを出す**のです。
**しかもダイアログはキャンセルすることができ、キャンセルすると無効化されてしまいます。**
これではあまり意味がありません。
cronを使う方法であれば、ダイアログは出ずに強制シャットダウンされます。

# 参考
https://apple.stackexchange.com/questions/25001/how-can-i-forcibly-shut-down-my-mac-at-an-appointed-time
【Docker】引数を指定してコマンドラインツールとして使う(wrapper script)

# はじめに

今回、自分の作成したプログラムを提供して使ってもらうのに、

- 毎回 docker run して使う
- 引数を docker run のコマンドラインで指定する

という形でプログラムの整備をしました。そのメモを書きます。これは昨今の流れに従うもので、このようにして提供されているオープンソースで使われる一般の使い方のようです。

自作のプログラムで

```
$ prog <arg1> <args2>
```

と整備したものを、そのままdocker image に整備して

```
$ docker run -t prog_image <arg1> <arg2>
```

として利用できるようになります。

次を参考にしてできました。

- [コンテナ内で複数のサービスを実行](https://docs.docker.jp/config/container/multi-service_container.html)<br> docker-docs-jp より：Docs » プロダクションでアプリを実行 » コンテナ設定 » コンテナ内で複数のサービスを実行)
- [Docker コンテナの動作に必要な設定を起動時に渡す](https://blog.amedama.jp/entry/2018/01/30/230221)<br>
  例がとても分かり易い。説明も丁寧な投稿。

上記の情報で十分だと思いますが、あえてハマりポイントを挙げると、、、

- CMDでなくENTRYPOINTで：これまでDockerfile で CMD で実行内容を指定していましたが、これだど引数を受け付けないようです。ETNRYPOINT にしたら動きました。
- 実行権限: image 内部での権限が問題のように見えた時、RUN chmod +x <file> を Dockerfile に書いたら動いた。（それでの良いのか^^;)

# 動作確認

### 構成

実現方法は、docker build で

-  実行プログラム```prog```をインストールする
-  prog を実行するためのためのスクリプトを用意する(wrapper script を呼ぶらしい）
-  wrapper script を dockerfile の ENTRYPOINT に設定する

です。（直接実行プログラムを指定しても良さそうな気がしますが、シェルを通したほうがいろいろ良いことがあるのでしょうか。そこのところは分かりませんが。）



### 動作例

テスト用に作ってみました。

- 実行プログラム。hello.c　コマンドラインの引数を表示するプログラム。

```c:hello.c

#include <stdio.h>
#include <stdlib.h>

int main(const int argc, const char**argv)
{
    for(int i=0; i< argc; i++){
        printf("argv[%d]=%s\n", i, argv[i]);
    }
    return EXIT_SUCCESS;
}
```

- wrapper script: ただ引数を渡す

```sh:docker_entrypoint.sh
#!/bin/bash
echo "I am a wrapper script."
hello $@
```

- Dockerfile: ビルドしてインストールし、wrapper script をentrypoint に指定する

```Dockerfile
FROM ubuntu:18.04

RUN apt-get update -y && \
  apt-get install -y -qq --no-install-recommends \
  build-essential \
  gcc

COPY hello.c /tmp/
RUN  cd /tmp && gcc /tmp/hello.c -o hello && mv hello /usr/local/bin/
COPY docker_entrypoint.sh /usr/local/bin

ENTRYPOINT ["docker_entrypoint.sh"]
```

- いざ動かしてみる

```shell
> docker build -t test .
...
Successfully tagged test:latest

> docker run --rm -t test Dear my friends.
I am wrapper script.
argv[0]=hello
argv[1]=Dear
argv[2]=my
argv[3]=friends.
```

### スクリプトなくても動作

今の場合、Dockerfile の ENTRYPOINT に直接実行プログラムを指定しても動きました。

```Dockerfile
ENTRYPOINT [ "hello" ]
```

# まとめ

- とりあえず、Linux で動く環境をそのままdocker run で動かすプログラムにする方法は分かった

今後の課題。

- docker run の管理は、通常のcontainer の管理と同じだと思うが、要確認。CPUなどのリソースの指定や使用状況の取得、HEATHCHECK など気になる。
- Wrapper を使う理由の理解を深める。複数のプログラムを組み合わせて逐次実行する指定をできたりするところかな。

今日（正確には昨日）も生き延びることができた。
(2020/10/17)
testareaの初期値(Value)が反映されない時の解決法

##エラー状況
例えば下記のような入力フォームにinputエリアとtextareaエリアを実装したとする。

<img width="30%" alt="Todo" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671576/d1f118cf-aff4-d41a-8dce-c02de313cc9a.png">

更新して再度開いた時に前回、更新した内容が表示できるようにしたい。
しかしinputエリアは通常に表示されているが、textareaは表示がされていない状況。

<img width="30%" alt="Todo" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671576/dd380407-fbd3-783a-5f8d-ba015542bf5c.png">

##修正作業
コードを確認してみると

```
<div class="title-area">
  <label for="test1">タイトル</label>
  <input id="test1" type="text" name="title" value="{{$sample->title}}">
</div>
<div class="text-area">
  <label for="test2">メモ</label>
  <textarea id="test2" type="text" name="memo" value="{{$sample->memo}}" row="5"></textarea>
</div>
```
一見、問題ないように見えますが、
**textareaにvalueを設定するのではなく、開始タグと閉じタグの間に表示されたい変数などを入れる**ようにコードを修正すれば、表示されると思います。

```
<div class="title-area">
  <label for="test1">タイトル</label>
  <input id="test1" type="text" name="title" value="{{$sample->title}}">
</div>
<div class="text-area">
  <label for="test2">メモ</label>
  <textarea id="test2" type="text" name="memo" row="5">{{$sample->memo}}</textarea>
</div>
```

##最後に
textareaはinputと同じように書きがちなので初学者の方がハマるエラーだと思い、執筆しました。
参考になれば幸いです。
GitHub Educationのメリットと申請方法

# GitHub Educationとは
## GitHub PROがもらえる
![Screenshot from 2020-10-17 17-41-31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397212/03637f38-edc5-0b6d-666e-0ebd5eb3f580.png)
Actionsが月に3000分使えてパッケージストレージが2GB使えるらしい。
どちらもあまり使わないのでそんなにうまみがない。

## GitHub Student Developer Packが使える
![Screenshot from 2020-10-17 17-38-45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397212/bcbdf231-0420-ffa9-f401-90a5c5571d5b.png)
個人的にGitHub Educationの本命
Heroku、Arduino、Twillioなど様々なサービスが並んでいる。
ただしGitHub Educationに登録していなくても受けられる特典がちょこちょこ見受けられる。
その他ラインナップは[こちら](https://education.github.com/pack/offers)を参照

## ハッカソンの旅費を支援してくれる
![Screenshot from 2020-10-17 17-38-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397212/eab95b29-3b79-4454-8d44-4ba3db378f0b.png)
1000ドルくれるらしい。すごい。

# 申請方法

GitHub Educationのページへアクセスします。
https://education.github.com

右上の`Get benefits`を選択
![Screenshot from 2020-09-23 14-47-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397212/0ab5620a-7822-d80d-3421-dcd7bae2c717.png)

IndividualsのGet student benefitsを選択
![Screenshot from 2020-09-23 14-51-53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397212/f0920f92-e084-8203-b992-77ebf8407242.png)



申し込むための資格が書いてあります。

- 学生であること。
- 学校からもらったメアドがあること。
- GitHubアカウントを持っていること。
- 13歳以上であること。
![Screenshot from 2020-09-23 15-02-45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397212/c3595894-014c-dafe-0af8-2ca264391846.png)

`Add an email address`から学校のアドレスを追加します。
![493cdf6e-b824-841d-5e15-ffcd1a814a82.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397212/73e265f5-41db-f2ad-7e8a-d8eb897ab094.png)


`How do you plan to use GitHub?`に回答します。私は次のように回答しました。
I will use to manage private projects and to join internships as a  programmer.
そんなにいっぱい書かなくていいと思う。
![22229e2f-211a-f535-c62b-3eea7b4fc0bf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397212/6efbac8e-e49e-4a2b-4e64-8aeb4c42ee64.png)

`Submit your information`を押して完了です。

![Screenshot from 2020-09-23 15-23-57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397212/f8b97c97-6868-04c1-4c0e-466b3ebb4ee5.png)

# 申請が承認される
2020/09/23申請後、いつのまにか`PRO`マークが付いていました。
(2020/09/25確認)

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">GitHubいつの間にかPROマークついてたんやけどこれ通知とか来んの？ <a href="https://t.co/MfJMpZgzvc">pic.twitter.com/MfJMpZgzvc</a></p>&mdash; 小林@毎日寝坊 (@asuha_prog) <a href="https://twitter.com/asuha_prog/status/1309147783883034632?ref_src=twsrc%5Etfw">September 24, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

~~承認にあたってメールとかはないらしい。
いつ承認されたかはわからないけどわりとスムーズに通るっぽい。~~無能さらしました。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397212/f43323d4-cc0c-5410-7272-a911d1d1828e.png)
スタバのWiFiに自動ログインするだけのスクリプト

スタバのWiFi（at_STARBUCKS_Wi2）は１時間で切れてしまい繋ぎ直すのが面倒なのでスクリプトにしました。
chrome拡張の[ScriptAutoRunner](https://chrome.google.com/webstore/detail/scriptautorunner/gpgjofmpmjjopcogjgdldidobhmjmdbm)に登録して自動で流れるようにしてます。



```javaScript
const login = url => {
    if (url.indexOf("service.wi2.ne.jp/freewifi/starbucks/index.html") > 0) {
        document.getElementById('button_next_page').click()
    }
    if (url.indexOf("service.wi2.ne.jp/freewifi/starbucks/agreement.html") > 0){
        document.getElementById('button_accept').click()
    }
}
login(location.href)
```





イメージ
![staba.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594998/809eb525-3023-29b8-174e-b502e84e6da6.gif)
Javascriptで日付を扱う(moment.js)

# はじめに
Qiita初投稿です。
間違っていることがありましたら、ご指摘いただけると幸いです。

# 開発環境
ruby 2.6.5
Rails 6.0.3.3

# 概要
moment.jsとはjavascriptで日付を扱うときに便利なライブラリです。
パッケージ管理面での欠点があるとも言われていますが、まだ主流な技術なので使用してみました。　

# 使用方法
作業中のディレクトリでmoment.jsをインストールします

```
npm install moment
```

使用したいjsファイルでmomentを読み込みます

```javascript:〇〇.js
var moment = require(“moment”);
```

↓このような書き方で生成できます

```javascript:〇〇.js
const dt = new moment();
```

しかし、これだけだとrails sで引っかかります。
↓おそらく、yarnの再インストールが必要になります。

```
error Lockfile does not contain pattern: "moment@^2.29.1"                                                                                                              
error Found 1 errors.                                                                                                                                                  


========================================
  Your Yarn packages are out of date!
  Please run `yarn install --check-files` to update.
========================================


To disable this check, please change `check_yarn_integrity`
to `false` in your webpacker config file (config/webpacker.yml).
```

check_yarn_integrityはデフォルトでFalseとなっているので
yarn install --check-filesだけを実行してみます

```
yarn install --check-files
```

問題なく使うことができました
# 最後に

moment.jsはレガシーな技術で今後はあまり使われなくなるかも知れません。
day.jsの方が軽量で管理面でも上位互換だとも言われていますが,
現役で活躍していることもあるので試験的に使用してみました。

移行する際は、この方の記事が参考になります。（勝手に掲載してすいません）
https://qiita.com/oika/items/2d15aea7809ab358ba25
【Unity】ステージ(Tilemap)に当たり判定をつける

### Rigidbody2Dをつける
Body TypeをStaticにする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308839/6ffc8160-af89-11b2-06bb-f5063a83b3de.png)

### Tilemap Collider 2DとComposite Cllider 2Dをつける
Used By Compositeにチェックをつける。
こうすることでパネル一つ一つにcolliderが付いていたが、パネルの塊で一つのcolliderがつくようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308839/e9a2cedd-5115-f613-177b-bb59624ae799.png)
Raspberry Pi でストリーミング

Raspberry Pi で　WebCamera を使ってストリーミングを行う方法です。
LAN 内の端末からブラウザーで次のように見えるようになります。
![streaming.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/c97731cb-6b5b-c695-4967-dae819acd2d3.png)

1) Raspberry Pi に USB カメラ`を挿して認識されていることを確認

```text
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 0411:0260 BUFFALO INC. (formerly MelCo., Inc.) 
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```

BUFFALO INC. (formerly MelCo., Inc.) が USB カメラです。

2) motion のインストール

```bash
sudo apt install motion
```

設定ファイルの変更

```text:/etc/motion/motion.conf
（省略）
stream_localhost off
webcontrol_localhost off
（省略）
```

```text:/etc/default/motion
start_motion_daemon=yes
```

3) motion の起動

```bash
sudo systemctl start motion
```

起動していることを確認

```text
$ sudo systemctl status motion
● motion.service - LSB: Start Motion detection
   Loaded: loaded (/etc/init.d/motion; generated)
   Active: active (running) since Sat 2020-10-17 17:32:55 JST; 39s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 5345 ExecStart=/etc/init.d/motion start (code=exited, status=0/SUCCES
    Tasks: 3 (limit: 4915)
   CGroup: /system.slice/motion.service
           └─5351 /usr/bin/motion

Oct 17 17:32:55 violet systemd[1]: Starting LSB: Start Motion detection...
Oct 17 17:32:55 violet motion[5345]: Starting motion detection daemon: motion.
Oct 17 17:32:55 violet systemd[1]: Started LSB: Start Motion detection.
```

4) ブラウザーで　8081 ポートにアクセス

Raspberry Pi が violet.local だとすると、

```text
http://violet.local:8081
```

次のバージョンで確認しました。

```text
$ uname -a
Linux violet 5.15.32-v8+ #1538 SMP PREEMPT Thu Mar 31 19:40:39 BST 2022 aarch64 GNU/Linux
```

関連記事
[Raspberry Pi で、Web カメラを使う](https://qiita.com/ekzemplaro/items/e643591515e92747e084)
Dockerコンテナ内でのgdbエラー対応

#概要
Dockerコンテナ内でgdbコマンドを使ってCプログラムのデバッグをしようとしたところ，以下のような
`warning: Error disabling address space randomization: Operation not permitted`
と怒られました．

```bash
(gdb) b 5
Breakpoint 1 at 0x117c: file test.c, line 5.
(gdb) r
Starting program: /home/user/dev/test 
warning: Error disabling address space randomization: Operation not permitted
```

予想がつくとは思いますが雑にいうと，gdbはシステムコールを利用しているが，コンテナの中からは権限が無いためホストマシンのデバイスにアクセスできないらしい．


#解決策
[システムコールを許可してあげるオプション](https://docs.docker.com/compose/compose-file/#cap_add-cap_drop)を付与してあげる．

* docker run実行時

```bash
$ docker run -it --cap-add=SYS_PTRACE --security-opt="seccomp=unconfined" [CONTAINER_NAME] /bin/bash
```

* docker-composeでの場合

`service`下に以下を書いてあげる．

```yaml:docker-compose.yaml
    cap_add: 
      - "SYS_PTRACE"
    security_opt: 
      - "seccomp=unconfined"
```

#参考記事
https://sott0n.github.io/posts/docker_gdb/
【Unity】ステージの作り方

### ①Tilesフォルダーを作成
こちらはステージ関係のものを保存するために使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308839/bae3c4e7-61b8-53b2-aee7-78f49d99a397.png)


### ②Tile Paletteを選択
左上のメニューからWindow > 2D > Tile Palette
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308839/16997772-192f-ee0e-7178-c7652f225bf9.png)


### ③paletteを作成
Create New Paletteをクリックし、nameを「StagePalette」にする。
Createをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308839/a4e91cd5-d2a6-89c2-d94a-3b89bd02f417.png)


### ④Paletteに画像をドラッグアンドドロップ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308839/3522c673-ab41-db5e-88db-3e4d39579311.png)


あとはメニューの筆や消しゴムを使ってステージを書きましょう！
【Ubuntu】Caps LockをCtrlに変更

Tweaksでcaps lockキーをctrlキーに変更する。

# Tweaksをインストール

ターミナルで

```bash
$ sudo apt install gnome-tweaks
```

を実行し、Tweaksをインストールする。

# Tweaksでキーの設定

Tweaksを起動し、キーボードとマウスを選ぶ。追加のレイアウトオプションをクリックし、

![Screenshot from 2020-10-17 17-12-38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135111/3817d7de-5f74-86a7-81e1-780042572e33.png)


`Caps LockをCtrlとして扱う`にチェックを入れる。

![Screenshot from 2020-10-17 17-15-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135111/6ebad091-4b03-7eaf-83dc-92f2bb273762.png)


Tweaksを閉じて、いったんログアウトしてからログインすると、caps lockがctrlになっている。
PHPマニュアル「参照カウント法の原理」ページのサンプルコード出力が，マニュアル記載のものと異なる

## 発生した問題

### マニュアルと，手元のコードの実行結果が食い違う

以下のコードです．
https://www.php.net/manual/ja/features.gc.refcounting-basics.php

```
<?php
$a = "new string";
xdebug_debug_zval('a');
?>
```

マニュアル記載の出力は以下のようになります．

```
a: (refcount=2, is_ref=0)='new string'
```

実際の出力は以下のようになります．

```
a: (interned, is_ref=0)='new string'
```

refcountの数値の変動を確認したいのに，これでは困ります．

## 原因

Xdebugのバージョンアップに伴う仕様変更とのことです．
手元のXdebugのバージョンを確認すると，"2.9.7-dev" でした．

```
$ php -r "var_dump(phpversion('xdebug'));"
Command line code:1:
string(9) "2.9.7-dev"
```

下記の変更において，文字列の場合，refcountの出力が抑制されるようになったようです．
https://github.com/xdebug/xdebug/commit/dd3c9b4127778dccbf61b98746797c7b88a4caf7

リンク発見元：https://stackoverflow.com/questions/56833897/why-increasing-refcount-of-zval-not-working

これはまだよく理解できていない状態での推測なのですが，おそらく，7系でzendコンテナの実装が変更になったことによるものではないかなと思っています．

https://hnw.hatenablog.com/entry/20141207


# 参考
Xdebugのバージョンを確認する方法
https://stackoverflow.com/questions/2479394/how-to-know-the-xdebug-version-i-have-installed
ec2にRLoginでssh接続してwinsock have error #10061が出た場合の原因

## 動作環境
Windows10
AWS EC2のインスタンスを起動中
RLogin(teraTerm)
仕事で顧客の会社のLANからEC２にssh接続しようとした

## トラブルの内容
Windows10でAWSのEC2にssh接続しようとした。RLoginでssh接続したら、「winsock have error #10061」というエラーが出た。この後、TeraTermでssh接続したら、TeraTermが接続できずに落ちて終了した。このエラーの原因は何か？

## 解決の糸口
別のネットワークから同じEC2のインスタンスにssh接続したら今度は成功した。つまり、顧客の会社のLANのポートの設定でsshの22番ポートが空いていなかったか、もしくは別の50022のような番号をsshポートとして利用しているとかが原因だと推測出来た。

## 結果
ネットワークの設定で外部にssh接続ができるPCが決まっていた。そのため、ネットワークの設定を変更してもらった。

## 所感
AWSの設定の問題かと思っていたが、ローカル側のネットワークの設定の問題できた。盲点でした。「winsock have error #10061」と検索しても、よくわからなかった。インターネット調べても全然出てこなかったのでQiitaに投稿しました。