OmniAICreator/Qiita-1.07M huggingface dataset:
Visual Studio Codeで必要な時だけXDebugをオン

# やりたいこと
- [必要な時にのみxdebugをオン](https://qiita.com/koriym/items/29f81514706a39e3b7c1)というのをVisual Studio Codeでもやりたい

# Install
- [phpインストール](https://qiita.com/yuki777/items/c8e33ca3290b55862c6a)済みであることを前提としています
- [VSCode拡張のPHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug)をインストールする。
- [VSCode拡張のPHPUnit Test Explorer](https://marketplace.visualstudio.com/items?itemName=recca0120.vscode-phpunit)をインストールする


# php.ini
```
; php --ini でphp.iniもしくはxdebug.iniを探してください

; ここではコメントアウトで無効化しておいて、実行時にvscode側から有効化します
;zend_extension = "xdebug.so"

; 下記は常時設定しておきます
xdebug.client_host = 127.0.0.1
xdebug.client_port = "9003"
xdebug.mode = debug
xdebug.idekey = "PHPSTORM"
xdebug.start_with_request = yes
```

# VSCode設定 launch.json
- `runtimeExecutable`でphpのpathを設定します
- `program`でphpunitのpathを設定します

```json
{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Listen for Xdebug(PHPビルトインサーバ)",
      "type": "php",
      "request": "launch",
      "port": 9003
    },
    {
      "name": "Launch currently open script(PHP CLI)",
      "type": "php",
      "request": "launch",
      "cwd": "${fileDirname}",
      "runtimeExecutable": "${userHome}/.phpenv/shims/php",
      "runtimeArgs": [
        "-dzend_extension=xdebug.so"
      ],
      "program": "${workspaceRoot}/vendor/bin/phpunit",
      "args": [
        "${file}"
      ],
      "port": 9003,
      "log": false,
      "env": {
        "XDEBUG_MODE": "debug,develop",
        "XDEBUG_CONFIG": "client_port=${port}"
      }
    }
  ]
}

```

# PHPUnitを実行する
- `PHPUnit Test Explorer`をインストールすると、テスト対象の上に緑の三角形 ▶️ が表示されます。ここでPHPUnitを実行できます。
- `"phpunit.showAfterExecution": "always"` で、PHPUnit実行後に結果が出力されます。

![Screenshot 2022-12-16 at 22.37.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8352/c8d4048c-3a68-a694-5af1-74abb3960b96.png)


# XDebugを使ってデバッグする
- ブレークポイントを設定して、
- launch.jsonで追加した設定を指定してデバッグします

![xdebug.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8352/574edcca-f4a9-4d14-bb47-9ae6e297f681.png)
javascriptの基礎(条件分岐の特殊な書き方)

## はじめに
以下のサイトを使用し、javascriptを学習しています。
[現代の JavaScript チュートリアル](https://ja.javascript.info/)

以下、備忘録として残します。

## 3項演算子 ‘?’
> #### 3項演算子 ‘?’の使い方
```javascript
let result = condition ? value1 : value2 //condition は評価され、もしも真であれば、'value1' が返却され、そうでなければ 'value2'　になる
let accessAllowed = ( age > 18 ) ? true : false;
```

> #### やらない方がいい場面
```javascript
(company == 'Netscape') ?
   alert('Right!') : alert('Wrong.');
// 変数に結果を代入していない。このような方法で疑問符演算子を使うことは推奨されていない。(読みにくいから)
```

> #### 上記の場合はif文を使う記述が分かりやすい
```javascript
if (company == 'Netscape') {
  alert('Right!');
} else {
  alert('Wrong.');
}
```

## NULL合体演算子　'??'
> #### '??'はリストの中から最初の “定義済み” 変数を選択するための短縮構文
- x = a ?? b の結果は
  - a が null あるいは undefined でなければ a,それ以外の場合は bとなる。以下の処理と同様。
  
> ```javascript
x = (a !== null && a !== undefined) ? a : b;
```

## '??'と'||'の比較
> #### 違い
- '||' は最初の 真 の値を返す
- '??' は最初の 定義済み の値を返す

> ```javascript
let height = 0;
alert(height || 100); // 100(代入されている値0は、false判定となるので)
alert(height ?? 100); // 0(heightが定義されているので)
```
VSCode ショートカット



```JSON5
// Place your key bindings in this file to override the defaultsauto[]
[
  // 開いているファイルの相対パスをクリップボードにコピー
  {
    "key": "ctrl+cmd+e",
    "command": "copyRelativeFilePath",
    "when": "!editorFocus"
  },
  {
    "key": "ctrl+cmd+e",
    "command": "copyRelativeFilePath",
    "when": "editorFocus"
  },
  // gitのブランチ選択UIを開く
  {
    "key": "ctrl+cmd+c",
    "command": "git.checkout"
  }
]
```
Macを買ったら必ず行うセットアップ（メモ）

メモです

## ショートカットキー設定
システム環境設定 → キーボード → 入力ソースを選択。

### 入力ソース
前の入力ソースを選択: cmt + スペース
次の入力ソースを選択: cmt + shift + スペース

### Spotlight
Spotlight検索を表示: ctrl + スペース

## Wifi接続
がんばる

## ブラウザ
Chromeを立ち上げ、アカウントにログイン。
アカウントで同期設定がoffになっている場合は、元のPCで
設定→同期とGoogleサービスから、同期をONにする。

## アプリ
* Slack
* iTerm
* f.lux
* Docker for Mac

## homebrew
これがないと人権が得られない
https://brew.sh/index_ja

## Emacs
```
$ brew install emacs
```

## Git
```
$ brew install git
```

Catallinaからデフォルトシェルがzshに代わり、git-promptを入れるのにbashと同じやり方では通じない。
[こちらの記事](https://medium.com/@m_yukio/macos-zsh%E3%81%A7git%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E5%90%8D%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%95%E3%81%9B%E3%82%8B-fe04afabb5b8)を参照。

最後に.gitconfigの内容を旧PCから新PCへ丸ごとコピー。

## GitHub SSHキー設定
`.ssh/config` に下記を追加。

```
Host github github.com
    HostName ssh.github.com
    User git
    Port 443
    IdentityFile ~/.ssh/github_key
```

鍵を生成。

```
$ ssh-keygen -t rsa -C "メールアドレス"
```

GitHubのSSH And GPG Keysに、新しく生成された公開鍵を貼り付け。

## VSCode
ここから
https://code.visualstudio.com/

下記のプラグインをとりあえず入れておく

* GitLens
* Prettier
* Project Manager
* vscode-reveal
* Github Theme

## Golang
下記を参照
https://qiita.com/sunnyG/items/cabc700e6d9a28219cc8

## Pyenv
https://qiita.com/crankcube/items/15f06b32ec56736fc43a

## Nodebrew
https://qiita.com/ucan-lab/items/517ee13a2f8769ab866c

## Goland
https://www.jetbrains.com/go/promo/

## GitリポジトリをClone
ひたすらがんばる

## SSHキー引継ぎ
がんばる

## aws credential引継ぎ
`.aws/credentials` ファイル
SQLAlchemyのJSON型が更新できない場合の対処方法

# はじめに
JSON型に入れれそうなデータがあって、あまりみんな使ったことないということでJSON型を導入しました。
SQLAlchemyからデータを入れるプログラムを書いていてinsert出来たものの、update出来なかったので対処方法について書きます。

# 環境
Mysql 5.7
Python 3.8.1
SQLAlchemy 1.3.12

多分、Postgresqlでも同様の対処でいけると思います。

# テーブル構成
なんでも良いので、テーブルにJSON型作ればOKです。
JSONの中身は任意で問題ありません。

# insert
insertは特に問題になりませんでした。
入れたい`dict`を作って、カラムに設定すればOKでした。
配列でも特に問題ありません。

# update
問題はこちらで、中身を書き換えたいという時に普通に中身を書き換えても反映してくれませんでした。
反映方法としては`flag_modified`で明示的にカラムが変更されたことを通知してから`add`だったりで反映するとなります。

``` python
from sqlalchemy.orm.attributes import flag_modified

flag_modified(entity, "json")
```

# 終わりに
なんで、このような手順になっているかは知りません
nginxでHTTP(S)以外で通信するリバースプロキシを立てる

Qiitaや他のブログにはHTTP(s)で通信するリバースプロキシサーバーの構築手法はよく掲載されています。しかし、http以外のtcp/udpで通信するリバプロの構築方法を見つけることは難しく苦労したので、こちらに記しておきます。

環境はAWSのEC2(Amazon Linux 2)を用いました。

# nginxをインストールする
まずは最新版のnginxをインストールします。この際、yumでインストールするのではなくwgetでビルドする必要があります。

```
$ wget http://nginx.org/download/nginx-1.19.2.tar.gz 
$ tar zxvf nginx-1.19.2.tar.gz
$ cd nginx-1.19.2
$ ./configure --modules-path=/usr/local/nginx/modules --with-stream
```
ここで、なんやかんや怒られるので足りないものをその都度yumでインストールしましょう。

```
$ yum install gcc
$ yum -y install pcre-devel
$ yum -y install zlib-devel
```

これで通ると思います。そのあと、makeしてinstall。

```
$ make
$ make install 
```

# nginx.confの設定
まずはnginxを起動しましょう。

```
$ sudo /usr/local/nginx/sbin/nginx
```
次に設定ファイルをいじります。

```
$ vi /usr/local/nginx/conf/nginx.conf
```
httpのところは#でコメントアウトしてしまいます。

```nginx.conf
# http{---略---
# }

stream {
    upstream mcserver {
        server {送信先IP}:{送信先ポート番号};
    }
      server {
        listen   {受信ポート番号};
        proxy_pass mcserver;
        allow {許可するIPアドレス};
        deny all;
    }
}

```

あとは再読み込みすれば反映されます。

```
#リロード
$ /usr/local/nginx/sbin/nginx -s reload
#終了
$ /usr/local/nginx/sbin/nginx -s stop
#起動
$ /usr/local/nginx/sbin/nginx
```
kabuステーション®API - REST API用のPythonラッパーをつくってみた

# 概要

以下のkabuステーションAPI記事回では辞書形式からjson形式への変換、requestsの作成、レスポンスのjson形式から辞書型への再変換を毎度行っていたが、このあたりを簡略化するモジュールを作成した。

- [kabuステーション®APIをPythonから使う](https://qiita.com/shirasublue/items/914e1d62d8308623b56b)

- [kabuステーション®APIのWebsocketをPythonで受ける](https://qiita.com/shirasublue/items/222c2bc7dbf284d24878)

### '20/10/07追記

token周りをアプデしてザックリな使い方を書きました

- [python-kabusapiの使い方](https://qiita.com/shirasublue/items/bbd8b5860612904deea0)


# 環境

- Windows 10
- Python 3.8.5 ( Microsoft Store からインストール )

# 使い方

requests のインストールが必要である。

```
pip install requests
```

以下よりダウンロードまたはcloneする。

- https://github.com/shirasublue/python-kabusapi

kabusapi があるフォルダで起動した端末のインタプリタですぐに使うことができる。

```python
PS C:\Users\Shirasu> python
Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:57:54) [MSC v.1924 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import kabusapi
>>> api = kabusapi.Context('localhost', '18080', 'password') 
>>> api.wallet.cash()                                       
{'StockAccountWallet': 123456.7}
>>>
```

他の使い方は同 Git の sample フォルダ内 sample.py を参照のこと。

# 関連記事

- 次回：[python-kabusapiの使い方](https://qiita.com/shirasublue/items/bbd8b5860612904deea0)
- 前回：[kabuステーション®APIのWebsocketをPythonで受ける](https://qiita.com/shirasublue/items/222c2bc7dbf284d24878)
Linuxで通信量を監視する

[前の記事](https://qiita.com/zrock/items/41371460832d2013342f)でディスク容量を監視してみました。
ついでに、通信量を測定してみたかったので、`watch`コマンドに`ifconfig`を渡してみた。

```bash
$ watch -n 1 ifconfig enx00e04c00004a
```

こんな感じ。`enx~`はインターフェース名。書かなければ全部出てきます。
通信量は起動してからの受信量・送信量がそれぞれRX、TXとして表示されます。詳細は`ifconfig`のマニュアル見てね。

```bash
Every 0.1s: ifconfig enx00e04c00004a                       graviohub: Thu Sep 10 14:57:45 2020

enx00e04c00004a: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.86.55  netmask 255.255.255.0  broadcast 192.168.86.255
        inet6 fe80::79b8:173:d2bd:f0e9  prefixlen 64  scopeid 0x20<link>
        ether 00:e0:4c:00:00:4a  txqueuelen 1000  (Ethernet)
        RX packets 2500640  bytes 1823881816 (1.8 GB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3509207  bytes 1042507689 (1.0 GB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
```

このやり方もかなりお手軽なのでおすすめです。きちんと測定したいときはそれなりのやり方を考えましょう。:P

![watch-ifconfig.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/a3844d96-4cec-1669-065f-2d11add70584.gif)
fgetsとかSTDINとか標準入力がわからなくてPaizaスキルチェックを始められない方へ

#はじめに
Paizaでは問題や解答のヒントをSNSなどに記載することは禁じられています。本記事は、その問題を解く以前の大前提を整理したもので、一般に公開されている[「値取得・出力サンプルコード」](https://paiza.jp/guide/samplecode)を中心に解説したものですので、禁止事項に当たらないと認識していますが、万が一問題を指摘されたら非公開とします。

さて、プログラミングを学び始めて、もっと実力を磨くために、問題集みたいなのないかなーと探してPaizaに辿り着いたまではいいものの、「標準入力？fgets？STDIN？何それ？」「標準入力の値の取得方法は下記ページのサンプルコードを参照ください。って言うから値取得・出力サンプルコード見たけど、意味不。」と、当初はDランクの問題ですら、60分以内に解けなかった僕が通ります。

私はPHPを学習しているので、PHP前提でこの記事を作成します。

上級者の方、ツッコミや補足情報あれば、ぜひお願いします。

#標準入力
標準入力とは、ここでは、Paizaスキルチェックにおいて、Paiza側から渡されるデータのことです。現時点では、あなたのプログラムの整合性を確認するために、10パターンのデータを用意して、あなたが提出したプログラムをチェックします。そのデータはこの標準入力としてあなたのプログラムに読み込む準備をしておかなくてはなりません。

そこで必要なのが、(1)fgets関数と(2)STDINというオブジェクト（モノ）です。
#fgetsとは
fgetsは関数で[PHP公式](https://www.php.net/manual/ja/function.fgets.php)では、下記のように定義されています。

>fgets — ファイルポインタから 1 行取得する

ファイルポインタとは？
>サーバーはファイルを扱うためにファイルポイントという専用のしおりを使います。 ファイルポインタは現在ファイルをどこまで読んだか、書いたかを示します。
http://www.standpower.com/php_analyz.html

#STDINとは
標準入力のこと。STDINは変数みたいなもので、そこにPaiza側が用意した実際の値が入ってきます。

>標準入力とは、コンピュータ上で実行されているプログラムが、特に何も指定されていない場合に標準的に利用するデータ入力元。
http://e-words.jp/w/%E6%A8%99%E6%BA%96%E5%85%A5%E5%8A%9B.html

#まずは１行めをきちんと取り出す

仮に、下記のようなデータがSTDINとして与えられたとします。最終行には改行があります。

```terminal:STDIN
1
2
3

```
この値を取得していくには、下記コードでできます。Paizaでも一番最初に既に用意されているコードですよね。当然ながら`$input_line`は別に`$i`とかにしても同じです。

```PHP:PHP
$input_line = fgets(STDIN);
```
出力結果↓

```terminal:STDIN
1

```
わかりづらいですが、1の後に改行が入っています。
これはあまりよろしくないので、[trim関数](https://www.php.net/manual/ja/function.trim)を使ってトリミングしてあげます。

>trim — 文字列の先頭および末尾にあるホワイトスペースを取り除く

```PHP:PHP
$input_line = trim(fgets(STDIN));
```
↑こうすると改行やスペースのない`1`が取り出せます。
#複数行にまたがるデータを取り出す
今見たように、１行めを取り出すのは簡単でしたが、では２行め以降はどのように取り出したらいいのでしょうか。
fgets関数は「ファイルポインタから 1 行取得する」ので、処理を繰り返すと２行目以降も取り出すことができます。

```PHP:PHP
$a = trim(fgets(STDIN));
$b = trim(fgets(STDIN));
$c = trim(fgets(STDIN));
$d = trim(fgets(STDIN));

echo = $a; //1
echo = $b; //2
echo = $c; //3
echo = $d; //データなし
```
↑このように２回目のfgetsは２行めを取ってきます。

また、Paizaでは複数行にわたるデータの最初の行は総データ数を渡してきて、２行目からが実際に処理するデータであることが多いです。下記↓のような例です。（しつこいですが、最終行には改行が入ってます。）

```terminal:STDIN
3
1
2
3

```
↑データ自体は先ほどのデータと同じですが、１行めにデータ数の情報（データ３行あるよ〜）が挿入されています。この１行めの数字は、forやwhileの繰り返し構文の条件設定に使えます。

```PHP:PHP
$input_line = trim(fgets(STDIN)); //$input_lineには3が代入される

for($i=0; $i < $input_line; $i++) { //←繰り返しの条件設定に使う
 //処理したい内容をここに
}

```
↑こうすれば0, 1, 2と３回for内の処理が繰り返されることになります。

また、そこで当然ながらデータを使うことになると思いますので、fgets(STDIN)をfor文の中に書いていきます↓。

```PHP:PHP
$input_line = trim(fgets(STDIN)); //$input_lineには3が代入される

for($i=0; $i < $input_line; $i++) {
 $a = trim(fgets(STDIN)); //もう上で一行目の3は使われているので、二行目の値1から一行ずつ代入されていく
}

```
↑こうして、一行目のデータをデータ数として使用し、二行目以降を実際のデータとして取り出して料理していくわけですね。

ちなみにこちら↓がPaizaの[値取得・出力サンプルコード](https://paiza.jp/guide/samplecode)、PHPバージョンです。引用します。こうして見るとプログラムの最初の３行はわかりやすくなったのではないでしょうか？？４行目からは取得したデータを問題に合わせてコーディングしているだけです。

```terminal:STDIN
2
2 5
3 4

```
```PHP:PHP
$input_line = trim(fgets(STDIN));
for ($i = 0; $i < $input_line; $i++) {
    $s = trim(fgets(STDIN));
    $s = str_replace(array("\r\n","\r","\n"), '', $s);
    $s = explode(" ", $s);
    echo "hello = ".$s[0]." , world = ".$s[1]."\n";
}
```

#最後に
超初歩的な内容ですが、自分が過去に躓いたポイントを整理できました。誰かのお役に立てると幸いです。ご指摘もどうぞよろしくお願いします。
Gitに編集権限をもつために公開鍵をGitに登録する

.sshフォルダを作り、その中に公開鍵と秘密鍵を作る

```terminal:ターミナル
$ cd
$ mkdir .ssh
$ cd .ssh
```

下記のコマンドで公開鍵と秘密鍵を作る(公開鍵と秘密鍵はペア)

```terminal:ターミナル
$ ssh-keygen -t rsa
```

全てEnterキーで構いません

```terminal:ターミナル
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/(username)/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
```

id_rsa(秘密鍵)　とid_rsa.pub(公開鍵)を作ることができました。
id_rsa.pub(公開鍵)の中身を実際にGitに登録していただきます。

```terminal:ターミナル
$ cat id_rsa.pub
```

```terminal:ターミナル
katonoMacBook-puro-4:.ssh katoatsushi$ cat id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADEcpf3vsEk/hFNowzSDRdBIlwU9Q55wRF/5cJNn67X
yF4AH8LdbYh2xzqqh+Q4WfWyb5iZjSVTr7Ncvd0G+iiM0YuHCd+d3WVymbM/Nu
ZJzNZKMxbmR//tZUGcmZ/aPrtUBO4+3S3xkegamAp1VEClydKTTvtSh1Uz4Xx3
590ALo3XccXQS1EXdO8Md9GLte4S4NQfcHrlooVaZyjwWOMbRtkmd1BR+Yw//
jYBSJHZOC8koFGySW8KkxWyVHpGdyD6HkxiBmWg7Dakdaql5n7NWimG0XwEahU
z4BNv5eY+vf4JNkXSBID katoatsushi@katonoMacBook-puro.local
```

公開鍵は
```ssh-rsa AAAAB3NzaC1yc2EAAAADEcpf3vsEk/hFNowzSDRdBIlwU9Q55wRF/5cJNn67XF4AH8LdbYh2xzqqh+Q4WfWyb5iZjSVTr7Ncvd0G+iiM0YuHCd+d3WVymbM/NuZJzNZKMxbmR//tZUGcmZ/aPrtUBO4+3S3xkegamAp1VEClydKTTvtSh1Uz4Xx3590ALo3XccXQS1EXdO8Md9GLte4S4NQfcHrlooVaZyjwWOMbRtkmd1BR+Yw//jYBSJHZOC8koFGSW8KkxWyVHpGdyD6HkxiBmWg7Dakdaql5n7NWimG0XwEahUz4BNv5eY+vf4JNkXSB katoatsushi@katonoMacBook-puro.local```になります
Linuxでディスク使用量を監視する

Linuxでディスク使用量を監視したかったのでちょっと調べてみたら `watch` というコマンドを見つけた。

```bash
$ watch -n 1 df -k
```

を実行すると、1秒毎に下記の画面がリフレッシュされる。

```bash
Every 1.0s: df -k                                  graviohub: Thu Sep 10 14:15:28 2020

Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/root       15008307 13057103   1292403  91% /
devtmpfs         1965540        0   1965540   0% /dev
tmpfs            1967840        0   1967840   0% /dev/shm
tmpfs            1967840    67128   1900712   4% /run
tmpfs               5120        4      5116   1% /run/lock
tmpfs            1967840        0   1967840   0% /sys/fs/cgroup
tmpfs             393568        0    393568   0% /run/user/1000
```

がっつり解析せずにちょっとした傾向とか知りたいときに便利。

![watch-df.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/78ab83e3-8f25-e520-4acb-1d6b0ad0bd94.gif)
vue/composition-apiでscrollの状態を扱うComposition Functionを作った

# 概要

上向きにスクロールしたときに表示して、下向きにスクロールしたら隠すフッターを表示する要件が現れたので、`useScroll`を作成して、スクロールの向きを絶えずリアクティブに返すComposition Functionとして扱ってみました。

# ソースコード

```typescript
import { useWindowScroll } from '@vueuse/core'
import {
  reactive,
  toRefs,
  watch,
} from '@vue/composition-api'

export const useScroll = () => {
  const { x, y } = process.browser ? useWindowScroll() : { ...toRefs(reactive({x: 0, y: 0})) }

  const state = reactive<{
    isUp: boolean,
    isDown: boolean
  }>({
    isUp: false,
    isDown: false,
  })

  watch(y, (newY, oldY) => {
    state.isUp = newY < oldY
    state.isDown = newY > oldY
  })

  return {
    x,
    y,
    ...toRefs(state),
  }
}

```

# 解説

こちらのFunctionには、[vueuse](https://github.com/antfu/vueuse)というライブラリを使わせてもらっています。
composition-apiを使った、特にブラウザのネイティブAPIで扱える値に関してリアクティブに活用できるFunctionがたくさんあります。

今回は`useWindowScroll`を利用させていただきました。
これは、windowへのEvent Listenerとして、ステート管理しているスクロールの高さを変更するハンドラを登録していることによって、リアクティブに座標の値を管理できるようにしています。

composition-apiのwatchで、スクロールのy値を監視しており、変化したときの古い値との比較によって上昇中か、下降中かを判定しています。

## 使い方

こんな感じで書くと、スクロールの向きに応じて出たり消えたりするフッターが作れます。高さが70px決め打ちになっているのが少し悔やまれますが、Vue3でStyle周りの改善が入るらしいのでちょっとそれを心待ちにしていようと思っています。

```vue
<template>
  <footer :style="footerStyle" class="sync-scroll" :class="{ appear: isUp }">
    <slot />
  </footer>
</template>

<script lang='ts'>
import {
  computed,
  defineComponent,
} from '@nuxtjs/composition-api'
import { useScroll } from '~/composables/utils/window/useScroll'

export default defineComponent({
  setup() {
    const scrollState = useScroll()

    const footerStyle = computed(() => {
      if (scrollState.isUp) {
        return {
          height: '70px',
        }
      }

      return {
        bottom: '-70px',
        height: '70px',
      }
    })

    return {
      ...scrollState,
      footerStyle,
    }
  },
})
</script>

<style lang='scss' scoped>
@import '@/assets/css/variable.scss';

.sync-scroll {
  width: 100%;
  position: fixed;
  bottom: -70px;
  animation-name: hide;
  animation-duration: .4s;
  animation-timing-function: linear;

  &.appear {
    bottom: 0;
    animation-name: appear;
    animation-duration: .4s;
    animation-timing-function: linear;
  }
}

@keyframes appear {
  0% {
    bottom: -70px;
  }
  100% {
    bottom: 0;
  }
}
@keyframes hide {
  0% {
    bottom: 0;
  }
  100% {
    bottom: -70px;
  }
}
</style>
```

## 注意点

もとの`useWindowScroll`が、スクロールのイベントハンドラにthrottleのような処理を噛ませていないっぽくて、全てのスクロールイベントに対してハンドラを呼び出しているようです。パフォーマンスを重視するならthrottleを噛ませたほうが良いと思います。

# 最後に

composition-apiにハマって日々いろいろ試して発信しているTwitterアカウントはこちらです。
https://twitter.com/Meijin_garden
Android, Kotlin: CSVの読み書き

- Minimum SDK: API 23
- Android Studio 4.0.1
- Kotlin 1.4.0
- opencsv Version: 5.2


Android, KotlinでCSVの読み書きを、opencsvを使って実装します。
CSVの操作を説明するために、StringReader, StringWriterを使って実装していますので、必要に応じてFileReader, FileWriter, InputStreamReader, OutputStreamWriterに置き換えて実装してください。

SDカードへのファイル読み書きはこちらを参照ください。→ [Android: SDカード上のファイルへの読み書き](https://qiita.com/nozaki-sankosc/items/686ac932420dcc82b063)

## 準備

### opencsvライブラリ取り込み

```gradle:build.gradle(app)
dependencies {
    implementation 'com.opencsv:opencsv:5.2'
}
```

## 配列を使った方法

### 書き込み

```kotlin:実装
        val strWriter = StringWriter()
        val csvWriter = CSVWriter(strWriter)
        csvWriter.writeNext(arrayOf("三幸太郎", "45", "男"))
        csvWriter.writeNext(arrayOf("三幸次郎", "44", "男"))
        csvWriter.writeNext(arrayOf("三幸花子", "35", "女"))
        println(strWriter.toString())
```

```bash:出力
"三幸太郎","45","男"
"三幸次郎","44","男"
"三幸花子","35","女"
```

### 読み込み

読み込み元は、先ほど作成したCSVテキスト(strWriter)

```kotlin:実装
        val strReader = StringReader(strWriter.toString())
        val csvIter = CSVIterator(CSVReader(strReader))
        for (row in csvIter) {
            for (col in row) {
                print(col)
            }
        }
```

## オブジェクト(Bean)を使った方法

### データ定義

初期値はいるみたいです。

```kotlin:CSVヘッダー無し
data class User(
    @CsvBindByPosition(position = 0)
    val name: String = "",

    @CsvBindByPosition(position = 1)
    val age: Int = 0,

    @CsvBindByPosition(position = 2)
    val gender: String = ""
)
```

```kotlin:CSVヘッダーあり
data class User(
    @CsvBindByName(column = "名前", required = true)
    val name: String = "",

    @CsvBindByName(column = "年齢", required = true)
    val age: Int = 0,

    @CsvBindByName(column = "性別", required = true)
    val gender: String = ""
)
```

### 書き込み

```kotlin:実装
        val strWriter = StringWriter()
        val beanWriter = StatefulBeanToCsvBuilder<User>(strWriter).build()
        beanWriter.write(User("三幸太郎", 45, "男"))
        beanWriter.write(User("三幸次郎", 44, "男"))
        beanWriter.write(User("三幸花子", 35, "女"))
        println(strWriter.toString())
```

```bash:出力(ヘッダー無し)
"三幸太郎","45","男"
"三幸次郎","44","男"
"三幸花子","35","女"
```

```bash:出力(ヘッダーあり)
"名前","年齢","性別"
"三幸太郎","45","男"
"三幸次郎","44","男"
"三幸花子","35","女"
```

### 読み込み

読み込み元は、先ほど作成したCSVテキスト(strWriter)

```kotlin:実装
        val strReader = StringReader(strWriter.toString())
        val beanList = CsvToBeanBuilder<User>(strReader)
            .withType(User::class.java)
            .withIgnoreLeadingWhiteSpace(true)
            .build()
            .parse()
        for (user in beanList) {
            println(String.format("%s, %d, %s", user.name, user.age, user.gender))
        }
```
【Laravel】シーディングの私的まとめ

[Laravel公式ドキュメント-シーディング](https://readouble.com/laravel/7.x/ja/seeding.html)の私的まとめ

#シーディング

- シーダークラスDBにテストデータを設定できる
- シーダークラスは好きな名前をつけられる
- `DatabaseSeeder`クラスでシーディングの順番をコントロールできる

##シーダクラス定義
```:シーダ作成
php artisan make:seeder UserSeeder
```
作成されたシーダは`database/seeder`に保存される

このシーダクラスのrunメソッドしかない
このメソッドに処理を書くことでデータを設定できる
##シーダの呼び出し
```php5:DatabaseSeeder.php
public function run()
{
    $this->call([
        UserSeeder::class,
        PostSeeder::class,
        CommentSeeder::class,
    ]);
}
```
`call`メソッドで呼び出すことでシーダを実行できる
##シーダの実行
###db:seedを使う
Composerのオートローダを再生成するために以下コマンドを実行
これをやらないと作成したクラスガオーとローダに反映されない

```bash
composer dump-autoload
```
DBへの初期値設定のために以下コマンドを実行

```
php artisan db:seed
```
これはデフォルトでDatabaseSeederクラスを実行する
特定ファイルを実行したい場合は`--class`オプションを使う

```
php artisan db:seed --class=UserSeeder
```
これでUserSeederクラスが実行される
###migrate:freshを使う
また`migrate:fresh`を使っても初期値を設定できる。

```
php artisan migrate:fresh --seed
```
`migrate:fresh`はDBを完全に作り直したいときに使える(最初にロールバックしてマイグレーションを実行するため)

#ここまでを軽くやってみる
シーダはこれ

```php5:TestTableSeeder.php
<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class TestTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $param=[
            'id'=>12,
            'stringCoslumn'=>'てすと',
        ];
         DB::table('testtable')->insert($param);
    }
}

```

シーダ作成からデータ設定までを軽くやってみると以下のようなエラーが出た

```
$ php artisan db;seed --class=TestTableClass
Target class [TestTableSeeder] does not exist.
```
TestTableSeederを作成したのがだそれが見つからないという
##原因
```
composer dump-autoload
```
を実行していなかった

ぐぐったらすぐわかりました
参考：[追加したはずのSeederが Class TableSeeder does not exist とか言われる](https://qiita.com/ragingalpaca/items/f5351fd7c30749cb31ae)

##しかしエラー
```
$ composer dump-autoload
$ php artisan db:seed
Target class [TestTableSeeder] does not exist.
```
またも見つからないと言われDBを作り直すrefreshもやってみたが駄目だった

```
$ php artisan migrate:fresh --seed
Target class [TestTableSeeder] does not exist.
```
##試行錯誤
シーダファイルのインサート分を消すとシーダファイルの認識はされている

```php5:TestTableSeeder.php
<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class TestTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $param=[
            'id'=>12,
            'stringCoslumn'=>'てすと',
        ];
         //DB::table('testtable')->insert($param);
    }
}

```
```bash
$ php artisan db:seed
Seeding: TestTableSeeder
Seeded:  TestTableSeeder (0 seconds)
Database seeding completed successfully.
```
もうダメだお手上げだと思ってしばらく放置

##そしてなぜか時間をおいたら実行できた
もう訳がわからない

#ただし
もう一度ドキュメント通りに進めてみたら今度は普通にデータがセットできた
なぜ上記の状態ではできなかったのかは全くわからないが今は良しとする
renderのcollectionオプションを使った繰り返し処理の省略

動作環境
Ruby 2.6.5
Rails 6.0.3.2

collectionを使うことでrenderで呼び出した部分テンプレートを繰り返し処理する場合は、省略して記述できることを学んだので、投稿してみました。

##collectionを使わない場合
```ruby:index.html.erb
<% @hoges.each do |hoge| %>
  <%= render partial: "huga", locals: {hoge: hoge} %>
<% end %>
```
上記のコードは、部分テンプレートhugaを呼び出し、その中でhogeという変数を渡して繰り返し処理を行うというコードです。
これをcollectionを使うとどうなるのかを見てみましょう。

##collectionを使う場合
```ruby:index.html.erb
<%= render partial: "huga", collection: @hoges %>
```
こちらのコードは先ほどのコードと**全く同じ意味**を持ちます。3行のコードが1行で済むので、非常に楽に記述できることがわかると思います。
注意していただきたいのが、部分テンプレートhugaで@hogeや@hogesと記述してしまうとエラーが発生してしまうことです。collectionの後の@hogesはコントローラーから受け取っているインスタンス変数です。実際に、部分テンプレートに渡している変数は先ほどのコードと同じhogeですので気をつけてください。

急にrenderのオプションでcollectionが出てきて、私は混乱してしまったことがあるので、この記事が少しでも役に立てればと思います。
警告文「Overriding managed version」の対処法


###はじめに
EclipseにてSpringBootによる開発をしており、pom.xmlを記述していたところ下記のように「Overriding managed version〜」と警告文が表示されました。

![スクリーンショット 2020-09-10 13.45.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639462/43e4b85c-ee86-b082-5433-abcb91d37e23.png)

これによって動作に影響を及ぼすことはないらしいのですが（このエラーを残したままでもアプリは動作した）、この黄色の!マークが表示されているとスッキリしないので、今回はこのエラーについて調べ、消そうと思います。


###親のpom.xmlの内容を確認
今回のエラーは子のpom.xmlの「mockito-core」のversionタグの行で発生しています。
このエラーは**親のpom.xmlで既に定義済みであるものを、子のpom.xmlで定義を上書きすると発生する**エラーです。

まずはエラーが表示されている子のpom.xmlを開いた状態で、**「概要」**タブを押します。
お使いのEclipseの設定によっては**「Overview」**と表示されています。
![スクリーンショット 2020-09-10 13.55.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639462/12496be0-c77d-0236-65cb-be14b4791c5c.png)

「親」と書いてある段の右にあるボタン「親POMを開く」ボタンを押します。
お使いのEclipseの設定によっては**「Open Parent POM」**と表示されています。
![スクリーンショット 2020-09-10 13.59.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639462/db2edf33-4c34-e7aa-f738-e0efb3fcc39d.png)

親のpom.xmlを開いたら**再度「概要」→「親POMを開く」**を押します。
この時のアーティファクトIdは「spring-boot-dependencies」です。

では、一段上の親のpom.xmlを開いたところで、問題の「mockito-core」がどのように定義されているかを確認しましょう。
下図のように\<mockito.version>3.3.3\</mockito.version>と記述されています。
ちなみに子のpom.xmlでは、「\<version>2.22.0\</version>」と定義していました。

![スクリーンショット 2020-09-10 14.11.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639462/144b94ef-27ae-475f-b506-1d1b5f473c19.png)

###子のpom.xmlのエラー行を削除
親のpom.xmlでは子のpom.xmlと異なったversion定義がなされていることがわかったところで、
今度はエラーを削除します。


エラーを引き起こしている行「\<version>2.22.0\</version>」を削除します。

![スクリーンショット 2020-09-10 14.20.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639462/5e44cda6-19d4-feee-4b88-13ffb13d4c99.png)
↓↓
![スクリーンショット 2020-09-10 14.20.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639462/15cc2889-2967-2bb6-89c8-149d3c6c7721.png)

行を削除した瞬間は黄色の!マークが表示されたままになるので、pom.xmlを保存しましょう。
そうするとマークは消えます。


以上です。



参考
https://qiita.com/shotah1215/items/f6ce566e7680d25a238e
https://www.yawintutor.com/warning-overriding-managed-version-maven/
【Python】ジェネレータ(generator)関数

# はじめに
　この記事はジェネレータ(generator)関数を理解せずに使用して失敗したため, ジェネレータ(generator)関数の勉強のための記事になります. 内容は, 参考文献を用いた自分用の備忘録です.

# 定義
　まずはジェネレータ関数の定義を確認する.

- 定義：ジェネレータ関数[^1]

> 関数定義の中でyield文が使われている場合、その関数はジェネレータ関数と呼ばれます。ジェネレータ関数はイテレータの一種です。

例：
　yieldを使ったジェネレータ関数をPython3.7.4で実行. yieldにより区切られて値が返されます.

```Python
def sample_generator_fun():
    yield 1
    yield 2
    yield 3

check = sample_generator_fun()
print(check.__next__())
print(check.__next__())
print(check.__next__())
```
　実行結果

```
1
2
3
```
　さらにcheckを実行すると...

```Python
print(check.__next__())
```
```
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-25-7029da5797f2> in <module>
----> 1 print(check.__next__())

StopIteration:
```
　反復停止と表示され, エラーとなります. つまり, sample_generator_funのyield文が順に実行され, 3番目の「yield 3」が実行されると反復が終了され, さらに実行しても値を返しません.

# 失敗例
　ジェネレータ関数をきちんと理解せず, リストなどのイテレータオブジェクトと同じものとして考え, 下記の様な失敗をしました. ※そもそも, 恥ずかしながらジェネレータ関数の存在を知りませんでした

例：
　取得されたジェネレータ関数のイテレータ数が2超であるのかを確認し, そうであれば実行する.

　**失敗例**

```Python
check = sample_generator_fun()

if len(list(check)) > 2:
    print("True")
    for i in check:
        print(i)
else:
    print("False")
```
　実行結果

```
True
```
　ここで, 私はif文でTrueになっているのに, なぜその下のfor文が実行されないのか悩み, 色々と調べてジェネレータ関数にたどり着くことが出来ました. 条件式内のlist(check)を実行したことで, 最後の「yield 3」まで実行されたことになるので, 次のfor文ではcheckは値を返さないため, for文は実行されません.

# 解決策
　簡単に思いつく範囲で下記2つが挙げられます. 工夫してジェネレータ関数を複数回呼び出し可能にする場合は, [この記事]
(https://qiita.com/tomotaka_ito/items/15b5999c76001dbc9a58)[^2]の様にするのが良いかもしれません. 

- ジェネレータ関数で返される総データサイズが大きくなければ, リストに変換して使用する

```Python
check = sample_generator_fun()
check_list = list(check)

if len(check_list) > 2:
    print("True")
    for i in check_list:
        print(i)
else:
    print("False")
```
　実行結果

```
True
1
2
3
```
- 単純に2回, ジェネレータ関数を呼び出す. この場合はジェネレータ関数のメリットであるメモリの節約は保持されます

```Python
check = sample_generator_fun()

n = 0
for i in check:
    n += 1
    if n > 2:
        print("True")
        check = sample_generator_fun()
        for j in check:
            print(j)
        break
else:
    print("False")
```
　実行結果

```
True
1
2
3
```
# 感想
　スクリプト言語では型宣言などをしなくてもコードを書けますが, どんな型やどんな性質のオブジェクトを触っているのかは, きちんと把握していないと事故りますね. 今回は「リスト」と同様だろうなという希望的観測による失敗でした. 使用するライブラリの中身を全て把握するのは難しいですが, 今回のような基本的なことはきちんと正確に抑えるべきだと改めて痛感しました.

[^1]: 中久喜健司：科学技術計算のためのPython入門, 2016年, 技術評論社
[^2]: [Python のジェネレータを何回もイテレートしたい](https://qiita.com/tomotaka_ito/items/15b5999c76001dbc9a58)
Swiftでデザインパターン【Observer】

元ネタ → [https://github.com/ochococo/Design-Patterns-In-Swift#-observer)

# クラス図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37598/d62c1d6e-e738-a3d9-a798-72422fb5ec1f.png)



図の引用元：[Wikipedia: Strategy パターン](https://ja.wikipedia.org/wiki/Observer_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)

# 概要
The observer pattern is used to allow an object to publish changes to its state. Other objects subscribe to be immediately notified of any changes.
Observerパターンは、オブジェクト（`Subject`）がその状態の変更を公開できるようにするのに使用される。他のオブジェクト（`Observer`）は、変更があるとすぐに通知を受けるように購読する（`Subject`が`Observer`のインスタンスを保持する）。

# サンプルコード
```swift
// Observer
protocol PropertyObserver : class {
    // notify()
    func willChange(propertyName: String, newPropertyValue: Any?)
    // notify()
    func didChange(propertyName: String, oldPropertyValue: Any?)
}

// Subject
final class TestChambers {
    // 集約
    weak var observer: PropertyObserver?

    private let testChamberNumberName = "testChamberNumber"

    // notifyOserver()
    var testChamberNumber: Int = 0 {
        willSet(newValue) {
            observer?.willChange(propertyName: testChamberNumberName, newPropertyValue: newValue)
        }
        didSet {
            observer?.didChange(propertyName: testChamberNumberName, oldPropertyValue: oldValue)
        }
    }
}

// ConcreteObserver
final class Observer : PropertyObserver {
    // notify()
    func willChange(propertyName: String, newPropertyValue: Any?) {
        if newPropertyValue as? Int == 1 {
            print("Okay. Look. We both said a lot of things that you're going to regret.")
        }
    }

    // notify()
    func didChange(propertyName: String, oldPropertyValue: Any?) {
        if oldPropertyValue as? Int == 0 {
            print("Sorry about the mess. I've really let the place go since you killed me.")
        }
    }
}


// usage //

var observerInstance = Observer()
var testChambers = TestChambers()
// addObserver()
testChambers.observer = observerInstance
testChambers.testChamberNumber += 1
```

# クラス図との対応
|  サンプルコード  |  クラス図  |
| ---- | ---- |
|  **PropertyObserver**  |  **Observer**  |
|  willChange, didChange  |  notify  |

|  サンプルコード  |  クラス図  |
| ---- | ---- |
|  **TestChambers**  |  **Subject**  |
|  observer  |  集約（aggregate）  |
|  willSet, didSet  |  notifyOserver  |

|  サンプルコード  |  クラス図  |
| ---- | ---- |
|  **Observer**  |  **ConcreteObserver**  |
|  willChange, didChange  |  notify  |

# 考察
Observer = Subscriber（購読）／ Subject = Publisher（発行）
`TestChambers`が`PropertyObserver`型（`Observer`を[アップキャスト](https://qiita.com/moccow/items/13a9232df69929ca4ae2)）のインスタンスを持つ（集約）。
`TestChambers`はストアドプロパティにより値の状態を監視し、変化があると`PropertyObserver`インスタンスの`willChange/Didchange`を呼ぶ（ポリモーフィズム）。こうして`TestChambers`は値の変化があった場合、`PropertyObserver`インスタンスに通知する。
【備忘】S3からのダウンロード、S3へのアップロード

1.S3からのファイルダウンロード
  今回は、バケットの対象パス下のファイルを全てダウンロードする場合を記述しました。

```
  AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withRegion("リージョン名").build();

  // S3上バケット下のファイル一覧を取得
  ObjectListing objListing = s3Client.listObjects("バケット名");
  List<S3ObjectSummary> objList = objListing.getObjectSummaries();

  try {
    // S3上のファイル分処理する
    for (S3ObjectSummary obj : objList) {
      // objListにはバケット下全てのフォルダ、ファイル情報があるため対象パスで絞り込む必要がある
      // 対象パスを含んでいないか、または、サイズが0であればダウンロードしない
      if (!StringUtils.contains(obj.getKey(), "対象パス") || obj.getSize() == 0) {
        continue;
      }

      // 以下ダウンロード処理
      // obj.getKey()は"対象パス/ファイル名"となっている
      GetObjectRequest request = new GetObjectRequest("バケット名", obj.getKey());
      // ファイル名だけにする
      String fileName = obj.getKey().replace("対象パス", "");
      // ダウンロード先のファイルを生成
      File file = new File(fileName);
      if (s3Client.getObject(request, file) == null) {
        // ダウンロード失敗
      }
    }
  } catch (IOException e) {
    throw e;
  }

```

2.S3へのアップロード
  ファイルをバケット下の対象パスへアップロードする場合

```
  try {
    AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withRegion("リージョン名").build();

    File file = new File("アップロード対象ファイル名");
    PutObjectRequest request = new PutObjectRequest("バケット名", "対象パス" + file.getName(), file);
    request.setCannedAcl(CannedAccessControlList.PublicRead);
    s3Client.putObject(request);
  } catch (Exception e) {
    throw e;
  }

```
あるフォルダに格納されたファイルを更新日時が新しい順に処理をする（Automation Anywhere A360）


#課題：
Automation Anywhere A360であるフォルダにあるファイルを読み込み、
順に処理をさせる際、ランダムな順序で読み込んでしまう。
これを更新日時が新しい順や古い順に処理させたい。

#解決方法：
いろいろな方法があると思いますが、シンプルに実装出来るよう、今回はコマンドプロンプトを使用します。
（A360側にこういう機能が早く実装されてくれても良いんですが）

###dir コマンド
コマンドプロンプトでフォルダ以下のファイル一覧を取得するのに使用する、dirコマンドを使います。
このコマンドのオプションで以下のような事が実現できます。

- 更新日時順にソートする　（/O-d）
- Botが読み出しやすいようにファイル/フォルダ名だけを出力する （/B）
- フォルダは出力対象外にする （/A-d）
- テキストファイルに書き出し、存在しない場合は作成して書き出し

例えばファイルの一覧を取得する対象が"c:\Demo2\"で、
結果をc:\Demo2\result.txtに書き出したい場合、以下のように記述します。

dir /O-d /A-d /B c:\Demo2\  >c:\Demo2\result.txt

コマンドプロンプトを起動して、どんな風な出力が出てくるか試してみてください。

###コマンドプロンプトをA2019から呼び出し、引数でdirコマンド以下を渡す
以下のようなBotを作ります。

- cmd.exeを呼び出し、dirコマンド以下を実行。
    - /c dir /O-d /A-d /B c:\Demo2\  >c:\Demo2\result.txt という具合に、cmd.exeに/cオプションを追加すると、それ以降のコマンドをそのまま実行してくれます。
- 上記コマンドで出力されたresult.txtを開く(区切り文字は"改行")
- 上記ファイルの行数分だけ反復処理
    - 読み取ったファイル名をメッセージボックスで表示
- CSV/TXTファイルを閉じる。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/2e88ee56-c5ea-80c1-b039-e146b89615e4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/4773f7b1-b038-81b6-a2a7-85be4f7d23b7.png)

#結果
この通り、ファイルの更新日時が新しい順にリストが生成されてますので、
あとはCSV/Textを開く、ループ アクションで読み取ってあげれば、この通りに読み取ります。
実際の業務ではメッセージボックスを入れた個所に、行いたい処理が入るようなイメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/6271764c-8c9c-55bc-2af5-0c95afe7b3b3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/51444180-1779-10a1-c387-89ab73920a59.png)

#参考ページ
[コマンドプロンプトでファイル一覧をテキスト出力！結果の便利な活用法も | サービス | プロエンジニア](https://proengineer.internous.co.jp/content/columnfeature/5043)
Gmailの未読メール数を記録する

怠け癖を諫めるために。

スプレッドシートのGASとして設定。

```javascript
function getInboxUnreadCount() {
  var unread = GmailApp.getInboxUnreadCount();
  var sheet = SpreadsheetApp.getActiveSheet();
  var d = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy年M月d日');
  sheet.appendRow([d,unread]);
}
```
レスポンシブデザインは容易に追加すべきではない

#はじめに
スマートフォンの普及をきっかけに、Web制作において
必須のスキルとなっているレスポンシブデザイン。
今回css記述の際に気をつける点を記述する。

#参考文献
<a href="https://www.amazon.co.jp/CSS%E3%82%B7%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%83%E3%83%88-%E2%80%9547%E3%81%AE%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF%E3%81%A7CSS%E3%82%92%E8%87%AA%E5%9C%A8%E3%81%AB%E6%93%8D%E3%82%8B-Lea-Verou/dp/4873117666">CSSシークレット ―47のテクニックでCSSを自在に操る</a>

※kindle版は英語表記しか見つけれませんでした。

#考え方
様々な解像度の下でWebサイトを表示させ、問題が生じたらメディアクエリを記述する。
→しかし、後々変更が必要になった場合、手間は倍となる。

メディアクエリを追加するたびにCSSのコードは不安定さを増す。
よって、ビューポートによって完全にデザインを切り替えたいなどの
最終手段としてメディアクエリを使うべきである。

以下に、
メディアクエリを回避するためのヒントを記述

※メディアクエリが悪いわけではなく、正しく使うべきという考え方。

##①Widthは固定値ではなく、％を使う
学習初期では、よく固定値を多用して他のデザインに影響を与えてハマっていた。

・できる限りpaddingやmarginで表す。
・width: 〇〇px;ではなくwidth: 〇〇%;
・相対値（vw, vh, vmin,vmax）を使う。

##②widthではなくmax-widthを使う
max-widthを使用することによって、メディアクエリを使用せずとも小さな画面に対応できる。

##③置換要素ではmax-width: 100%;を忘れずに
置換要素→img,object,video,iframeなど

##④background-size: cover;
背景画像がコンテナ全体を覆う必要がある場合にコンテナのサイズを記述する必要がなくなる。
※モバイル向けのデザインにて、大きな画像を縮小する場合は不具合も。

##⑤column-widthを指定する
段組を使ってテキストを配置する場合に小さな画面では１段組みで表示する。

#結論
大量のメディアクエリの記述が必要となった場合には
一歩戻ってコードの構造を見直すことが重要。
2,3個の簡単なメディアクエリでレイアウトをレスポンシブにできるように意識する。

cssは奥が深くもっともっと学習が必要であると感じた。
もう少し具体的に記述できるよう随時アップデートしていきたい。
Firebaseへログインできなかった

<h1>はじめに</h1>

Firebaseの環境を構築しようとした際、Firebaseのログイン処理を実行しようとしたがうまくいかなかった。

<h1>実行したこと</h1>
コンソールで firebase login を実行

```
$ firebase login
i  Firebase optionally collects CLI usage and error reporting information to help improve our products. Data is collected in accordance with Google's privacy policy (https://policies.google.com/privacy) and is not used to identify you.

? Allow Firebase to collect CLI usage and error reporting information? Yes
i  To change your data collection preference at any time, run `firebase logout` and log in again.

Visit this URL on this device to log in:
https://accounts.google.com/o/oauth2/・・・・・・

Waiting for authentication...
```

リンクからGoogleアカウント認証ページにアクセスして認証を行う

しかしブラウザ上の認証ページで認証を実行できなかった。

<h1>解決策</h1>
・CLI環境でFirebaseへログインする方法
https://qiita.com/RCA3610/items/adb16aa21826377f3c0f

上記の記事が非常に参考になりました。

先ほどのコードに　--no-localhost　オプションを追加する。

```
firebase login --no-localhost
i  Firebase optionally collects CLI usage and error reporting information to help improve our products. Data is collected in accordance with Google's privacy policy (https://policies.google.com/privacy) and is not used to identify you.

? Allow Firebase to collect CLI usage and error reporting information? Yes
i  To change your data collection preference at any time, run `firebase logout` and log in again.

Visit this URL on any device to log in:

https://accounts.google.com/o/oauth2/auth.......

? Paste authorization code here: （ここにパスコードをペースト）
```

実行後URLからGoogleアカウント認証ページで認証を実行するとパスコードが発行されるのでコンソールにペースト

```
 Success! Logged in as ....
```
これでFirebaseのログイン処理が完了！！
（小ネタ）discord.jsでメッセージから絵文字を取得する

# はじめに
備忘録も兼ねて、[discord.js](https://discord.js.org/)にてメッセージからUnicode絵文字を判別し、取得する方法を紹介します。
DiscordにおいてUnicode絵文字とは、各サーバーで登録されるカスタム絵文字以外の、初めから全てのユーザーができる絵文字のことです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264873/097046ac-e624-277f-792c-d48cba98b248.png)
Discordでは絵文字に[Twemoji](https://twemoji.twitter.com/)を使用しており、それゆえにTwemojiと互換性があります。
そのため今回はTwemojiの絵文字判定処理に使用されている[twemoji-parser](https://github.com/twitter/twemoji-parser)を用いたUnicode絵文字判定処理の方法を紹介します。
twemoji-parserはtwemoji同様、Twitter社によって管理されているライブラリなので、安心感があります。

# 事前準備
適当にプロジェクトを用意していただき、twemoji-parserをインストールしておきます。

```
npm install twemoji-parser
```

# 本題
今回はサンプルとして、[`message`](https://discord.js.org/#/docs/main/stable/class/Client?scrollTo=e-message) イベントで受け取ったメッセージ内に含まれるUnicode絵文字を、リアクションとして返すだけのコードを紹介します。
コードとしてはシンプルなため、解説は省かせて頂きます。

```js
const { Client } = require('discord.js');

// twemoji-parserから判定用の正規表現を取得(gオプション付き)
const twemojiRegex = require('twemoji-parser/dist/lib/regex').default;

const client = new Client();

client.on('message', message => {
  // メッセージから正規表現でUnicode絵文字を取得
  const mathEmojis = message.content.match(twemojiRegex);

  for (const emoji of mathEmojis) {
    // 取得したUnicode絵文字をリアクションで返す
    message.react(emoji)
      .catch(console.error);
  }
});

client.login('Your bot token')
  .catch(console.error);
```

こんな感じで動作します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264873/6f8dc194-32b3-5da5-4646-941432cfc96a.png)

# 注意点
twemoji-parserの正規表現にはgオプションが付いています。
ですから、使用目的によってはそのまま利用できないため、自前で正規表現を再生成する必要があります。
例えば、単にgオプションを外したい場合、このようにします。

```js
const twemojiRegex = require('twemoji-parser/dist/lib/regex').default;
const onceRegex = new RegExp(twemojiRegex, '');
```

# あとがき
メッセージ内のUnicode絵文字を判別し取得する処理は、自前で書こうと思うとなかなかの至難の技です。
twemoij-parserを使用すればUnicode絵文字の複雑な組み合わせも、しっかり1文字と判定されるため、複雑なことを考えずに済みます。
また、これを応用すれば[スプレッド構文](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax)でも実現できなかった、実態に即したUnicodeのパースも行えそうです。
Zabbix5でhttpsサイトの証明書の有効期限を監視する方法

![CentOS-8.2.2004](https://img.shields.io/badge/CentOS-8.2.2004-brightgreen)　![Zabbix-5.0.3](https://img.shields.io/badge/Zabbix-5.0.3-brightgreen)

httpsサイトを公開していますと、証明書の有効期限が間近に迫りばたばたと更新作業に追われたり、有効期限切れにてサイトが不正なサイトとして扱われて大騒ぎになることがあります。そんな事態にならないよう、ZabbixにてSSL証明書の有効期限を監視できるようにしたいと思います。

## テンプレートのダウンロード
以下のサイトからテンプレート(とスクリプト)をダウンロードします。
https://share.zabbix.com/cat-app/web-servers/ssl-certificates-check-4-4

適当なところに解凍しておきましょう。

* zext_ssl_cert_checker.xml ... テンプレート
* zext_ssl_cert.sh ... スクリプト


## テンプレートの読み込み
Zabbix Web管理コンソールにログインし、左メニューの`設定`→`テンプレート`を開き、画面右上にある`インポート`をクリックします。
インポート画面にてテンプレートファイルを読み込ませます。

<img width="512" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97774/92c77cb0-9aee-9f44-3008-c5ad13fad7d3.png"/>

問題なければ、`Template SSL Cert Check External`というテンプレートがインポートされます。

## スクリプトの配置
WinSCPなどを使い、スクリプトファイルをZabbixサーバ上にコピーします。その後、以下の手順に沿ってコマンドを使えるようにします。

```shell-session:
# cp -p zext_ssl_cert.sh /usr/lib/zabbix/externalscripts/
# chmod +x /usr/lib/zabbix/externalscripts/zext_ssl_cert.sh

# #スクリプトで必要になるパッケージのインストール
# dnf install bc
```

## 利用例
問題なくスクリプトが導入されていれば、キーとして `zext_ssl_cert.sh[-d,fqdn,port]` と `zext_ssl_cert.sh[-i,fqdn,port]` が使用可能になります。

* `zext_ssl_cert.sh[-d,fqdn,port]` ... 指定したサイトの証明書の残り有効日数を取得
* `zext_ssl_cert.sh[-i,fqdn,port]` ... 指定したサイトの証明書の認証局名を取得

このキーを利用した以下の様なアイテムを作成し、残り～日になったら発報するといったトリガーを組めば有効期限を監視することが出来るようになります。

<img width="512" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97774/b9ec5d9e-d848-e2b1-29ba-d4dee74e4931.png"/>
dockerのphp-apacheイメージでのapache再起動

# やりたこと
dockerのphp-apacheイメージで不意にapacheが停止した場合、apacheを起動したい。

# 環境
* dockerimage php:7.4-apache

# コマンド
```
service apache2 start
```

以下はダメ。

```
service httpd start
httpd: unrecognized service
```

```
/etc/init.d/httpd start
bash: /etc/init.d/httpd: No such file or directory
```

```
apachectl start
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.24.0.2. Set the 'ServerName' directive globally to suppress this message
```

php:7.4-apacheがDebianだからとかなのかhttpdが使えなくて困った。

```
cat /etc/issue
Debian GNU/Linux 10 \n \l
```
javascriptの基礎(演算子)

## はじめに
以下のサイトを使用し、javascriptを学習しています。
[現代の JavaScript チュートリアル](https://ja.javascript.info/)

以下、備忘録として残します。

## 用語
> #### オペランド(演算子が適用されるもの)
```javascript
let a = (2*3); //オペランドが2つ。
let a = (2*3)+5; //オペランドが3つ。
```
    
> #### 単項演算
  - オペランドが単数の場合
    - (例) `-2`

> #### 二項演算
  - オペランドが二つの場合
    - (例) `1-2`
    
## 文字列連結、二項演算子
> #### 二項演算子が文字列の場合は結合される
```javascript
let s = "my" + "string";
alert(s); // mystring
```

> #### 一方のオペランドが文字列の場合は文字列
```javascript
alert( '1' + 2 ); // "12"
alert( 2 + '1' ); // "21"
```

> #### "+" 以外の算術演算子は数値でのみ動作
```javascript
alert( 2 - '1' ); // 1
alert( '6' / '2' ); // 3
```

## 数値変換、単項演算子
> #### 単項演算子が数値の場合何の影響もない
```javascript
let x = 1;
alert( +x ); // 1
let y = -2;
alert( +y ); // -2
```

> #### 単項演算子が文字列の場合数値に変換される
```javascript
// 非数値を数値に変換
alert( +true ); // 1
alert( +"" );   // 0
```

> #### 文字列を数値に変換
```javascript
let apples = "2";
let oranges = "3";
// 二項演算子プラスの処理の前に、両方の値が数値に変換されます
alert( +apples + +oranges ); // 5
```

## その場で変換する
> #### 変数に演算子を適用し、その中に新しい値を格納
```javascript
let n = 2;
n += 5; // 今 n = 7 (n = n + 5 と同じ)
n *= 2; // 今 n = 14 (n = n * 2 と同じ)
alert( n ); // 14
```

> #### 通常の代入と同じ優先順位
```javascript
let n = 2;
n *= 3 + 5;
alert( n ); // 16  (右のパートが最初に評価されるので、 n *= 8 と同じ)
```

## カンマ
> #### 最後の結果のみが返却される(丸括弧で覆った場合)
```javascript
let a = (1 + 2, 3 + 4);
alert( a ); // 7 (3 + 4 の結果)
```

> #### 丸括弧で覆わなかった場合の挙動
```javascript
let a = 1 + 2, 3 + 4 ; //+ を最初に評価し、a = 3, 7 に加算、カンマのあとの 7 は処理されない。
alert(a); //3
```
【練習】ArrayList

◎二次元配列をArrayListに書き換え

```java
package renshuu;
import java.util.ArrayList;
public class Array_pra {

	public static void main(String[] args) {
		//newでArrayリストのインスタンス生成
		ArrayList<String> seasons=new ArrayList<String>();
        //↑左辺は　List<String> seasons　でもok
		seasons.add("春");
		seasons.add("夏");
		seasons.add("秋");
		seasons.add("冬");

		for (int i = 0; i < seasons.size(); i++) {
			System.out.print("\"" + seasons.get(i) + "\" ");


//実行結果
"春" "夏" "秋" "冬" 
		}
	}
}

```

◎上記をfor文からfor拡張文に書き換え

```java
package renshuu;
import java.util.ArrayList;
public class for_ver {

	public static void main(String[] args) {

		ArrayList<String> seasons=new ArrayList<String>();
		seasons.add("春");
		seasons.add("夏");
		seasons.add("秋");
		seasons.add("冬");

		for(String a:seasons) {
			System.out.print("\""a+"\" ");
		}
	}
}

//実行結果
"春" "夏" "秋" "冬" 
```

◎Iteratorを使用してArrayListを出力

```java
package renshuu;

import java.util.ArrayList;
import java.util.Iterator;

public class Array_iterator {
	public static void main(String[] args) {

		ArrayList<String> seasons=new ArrayList<String>();
		seasons.add("春");
		seasons.add("夏");
		seasons.add("秋");
		seasons.add("冬");

		Iterator<String>itSeason=seasons.iterator();
		while(itSeason.hasNext()) {
			String PSeason=itSeason.next();
			System.out.print("\""+PSeason+"\" ");
		}
	}
}

//実行結果
"春" "夏" "秋" "冬" 
```

◎二次元配列をArrayに書き換え

```java

package renshuu;
import java.util.ArrayList;
import java.util.List;
public class Nijigen_Array {

	public static void main(String[] args) {

		ArrayList<ArrayList<String>> Niji=new ArrayList<ArrayList<String>>();
		    ArrayList<String> a = new ArrayList<String>();
		    ArrayList<String> b = new ArrayList<String>();
		    
		a.add("春");
		a.add("夏");
		a.add("秋");
		a.add("冬");

		b.add("さくら");
		b.add("うみ");
		b.add("いちょう");
		b.add("こたつ");

		Niji.add(a);
		//Niji[0] ゼロ番目の要素にa(春・・)が入る
		Niji.add(b);
		//Niji[1] 1番目の要素にb(さくら・・)が入る

		for (List<String> datas : Niji) { //Niji[0] Nijiの0番目の要素をとりだし
			for (String data : datas) { //その0番目の中を1つづつ取り出す
				System.out.print("\"" + data + "\" ");
				} //Niji[0]のなかを全部取り出し終わったのでループをぬけて
			System.out.println(""); //改行して、for文の最初まで戻る。Niji[1]の処理をする

				}
           //↓春～とさくら～の行間の改行
			System.out.println("");
		}
	}
}

//実行結果
"春" "夏" "秋" "冬" 
"さくら" "うみ" "いちょう" "こたつ" 
```
css 画像 横並べ flexbox版

・テキストは左
・画像は右


こんな感じが完成

![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/454bb044-ecfd-7d1d-68a8-331260a3cac7.png)


以下のようなcssにしたほうがいいね。

・画像をタップしたときに、画像だけ黒くならない

```hoge.vue
        <a class="flex-box" href="//yahoo.co.jp">
            <div class="text">
                <h3>お相手と会う際に気をつけること</h3>
            </div>
            <div class="pic">
                <div style="height: 100px;width: 100px;background-image: url('/img/safe1.png');">
                </div>
            </div>
        </a>

        <a class="flex-box" href="//yahoo.co.jp" style="margin-top: 15px;">
            <div class="text">
                <h3>悪質なユーザーを見分ける手がかり</h3>
            </div>
            <div class="pic">
                <div style="height: 100px;width: 100px;background-image: url('/img/safe2.png');">
                </div>
            </div>
        </a>
```

```hoge.css

.flex-box {
    background-color: #f5fbfb;
    display:flex;
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;
    text-decoration: none;
    width: 100%;
    border-radius: 15px !important;
    -moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    -webkit-tap-highlight-color:rgba(0,0,0,0);
}

.flex-box .text {
    font-size: 14px;
    color: #2c4748;
    flex-basis: 100%;
    padding-left: 15px;
    user-select: none !important;
    -moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
}

.flex-box .pic {
    padding: 5px;
    user-select: none !important;
    -moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
}


```






以下、古い



もしくは上記と逆を作るCSSをメモ。
参考
https://niwaka-web.com/flexbox_reverse/

完成形

![kanse4i.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/25c27ac6-7d59-ceb1-ab4d-248dc02d5aa5.png)


以下、コピペで動く

```hoge.css

<style>

    /* アイコン右 、　テキスト左 */
    .flex-box {

        display:flex;
        flex-direction: row;
        justify-content: flex-start;

      /* 縦方向の並び順*/
        /*    
        flex-start：上揃え（デフォルト）
        flex-end：下揃え
        center：中央揃え
        baseline：ベースライン
        stretch：伸縮
        */
        align-items: center;//要変更

        text-decoration: none;
        width: 100%;
    }

    .flex-box .text {
        background-color: red;
        flex-basis        : 100%;
    }

    .flex-box .pic {
        background-color: blue;
        flex-basis        : 64px;
    }


</style>

```


```hoge.html


<a class="flex-box" href="//yahoo.co.jp">
    <div class="text">
        <h3>恋と言うなの翼</h3>
        <p>切なさの中で</p>
    </div>
    <div class="pic">
        <img src="https://placehold.jp/3d4070/ffffff/64x64.jpg">
    </div>
</a>


<!--            ここに flex-direction: row-reverse; を設定で 左右逆になる-->
<a class="flex-box" style="flex-direction: row-reverse;" href="//yahoo.co.jp">
    <div class="text">
        <h3>恋と言うなの翼</h3>
        <p>切なさの中で</p>
    </div>
    <div class="pic">
        <img src="https://placehold.jp/3d4070/ffffff/64x64.jpg">
    </div>
</a>


```