OmniAICreator/Qiita-1.07M huggingface dataset:
ステージング環境考

## ステージング環境とは

e-Words の[ステージング環境](http://e-words.jp/w/%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%83%B3%E3%82%B0%E7%92%B0%E5%A2%83.html) には以下の説明があります。

> ステージング環境とは、情報システムやソフトウェアの開発の最終段階で検証用に用意される、実際の運用環境と変わらない環境のこと。

要するに本番環境とは別に、リリース直前の検証を行う環境ということですね。単体テスト・結合テスト・総合テストで言うところの、総合テストを行う環境とも言えるでしょう。

このステージング環境について考えてみたいと思います。

(2021.7.2追記)

明記してませんでしたが、主にウェブ系のシステム開発を前提としています。

(2021.7.2追記終わり)

## なぜ必要か

開発環境でもある程度の検証はできますが、開発者以外は開発環境を持ってないことも多いです。社内の人間なら開発環境を用意しろということもできますが、クライアントならそうも言えない。そういう開発者以外の人にリリース前の動作を見せるのには、なんらかの専用環境が必要です。

開発環境はシステム全体の要素を持ってないことも多いので、単体テスト・結合テストまでは行えても、総合テストまでは無理ということもあります。

(2021.7.2追記)

開発環境が手元のPC上に構築されてる場合を想定していましたが、データセンターやクラウド上にある場合もありますね。その場合 URL を伝えれば開発環境を持っていない人でも検証できます。

もっとも、検証中は開発環境で別の作業ができなくなってしまいますので、やっぱりステージング環境が欲しくなりますけれども。

(2021.7.2追記終わり)

## 閲覧範囲

通常はステージング環境は特定少数の関係者だけが閲覧できるように設置します。クローズドな環境に構築したり、インターネットからアクセス可能でもアクセス制限を設けたりします。

逆に、パブリックベータで一般に公開する場合もあります。

## 構成

本番環境と同等の構成であることが理想ですが、現実的には難しい。本番環境が100台のサーバで構成されていたとして、ステージング環境も100台とするとコストがかかりすぎてしまう。なので、台数を減らしたり機器の性能を落としたりして節約した構成にすることも多い。構成が違うことにより負荷試験などが行えなかったり試験結果が正確にならないことがあり得ます。

## OS、言語、ミドルウェアのバージョン

OS、言語、ミドルウェアなどは当然ながら本番環境と同じバージョンである必要があります。が、現実には様々な事情でバージョン違いの環境で検証せざるを得ないこともあります。バージョン違いによって試験結果が不正確になることを考慮しなければなりません。

## データセット

試験するためにはデータセットが必要です。

データセットでまず検討しなければならないのはデータ量でしょう。100件のテストデータで軽々動作していて、本番環境の100万件のデータを扱わせたら重くて動かないでは話になりません。

本番と同量のテストデータセットを用意しても、データのばらつきの問題もあります。テストデータセットでは本番データとはデータのばらつきが変わってきますので、ばらつきに起因する動作や負荷の違いは検証できなくなってしまいます。

データセットのタイムスタンプも重要です。先月のデータを集計するシステムに対して、用意されたデータセットが1年前に構築したものだと、集計動作の検証が行えません。テスト用データセットを seed で用意するなら、現在日時を考慮して生成するようにするべきでしょう。

などなどのことを考えると、理想的なテストデータセットとは本番データセットということになります。本番で現在動作しているデータセットをステージング環境にコピーして使えるといいのですが、今度は機密漏洩の問題がでてきます。たとえステージング環境が社内に閉じていたとしても、厳密に言えば本番環境からステージング環境に機密情報をコピーしたら情報漏洩です。利用規約などでクリアできたとしても、別の問題もあります。実際のユーザのメールアドレスが登録されたデータセットを使ってメルマガ配信のテストを行ってしまったら大問題です。本番のデータセットを使って検証をする場合、機密情報はマスクして持ってくる必要があります。

## 本番環境との差異

ステージング環境は本番環境と構成が同一である必要があります。しかし、ステージング環境では本番リリース前のコードを検証しますので、厳密に言うとその時点で本番環境との差異が発生します。コードだけの差異ならコードを入れ替えれば元通りですが、新機能のために必要なライブラリをインストールしたら、そのライブラリ分が差異になります。マイグレーションを行えば、DB構成にも差異が発生します。ステージングで検証後、すみやかに本番リリースが行われるのであればこうした差異は事実上無視できますが、様々な事情で本番リリースが遅延したり、リリースが断念されてしまうこともあります。そうした際に、インストールされたライブラリや、マイグレーションによるDB構成の差異が残り続けると、今後の検証が正しく行われなくなる危険性があるでしょう。

理想的にはステージング環境は定期的に作りなおされるといいのですが、環境構築が手順書に従った手動だと大きな手間になりますので、構成管理ツールを使って自動化されているといいでしょう。

## 稼働時間

本番環境が24時間365日稼働していたとしても、ステージング環境が同様である必要はありません。検証を行うときだけ立ち上がっていればいいのです。オンプレなら別ですが、クラウドならば起動時間を短くすることでコストを節約できます。平日の就業時間帯だけステージング環境が起動するように設定しておくのはいいアイデアですが、リリース間近になって残業休出しているときにステージング環境が立ち上がってなくて不便ということも起こりえます。

前出の本番環境との差異を含めて考えると、構成管理ツールを使ってコマンド一発でステージング環境が新規に構築できるようになっているのが理想でしょうか。検証が終わればステージング環境を削除してしまうという運用です。

## 外部連携

システムは自分たちで作ったシステムだけで閉じていなくて、他のシステムと連携して動作することも多いです。他のシステムとは、自分たちで作った別のプロダクトのこともありますし、他社の提供しているサービスということもあります。

連携する他のシステムに、ステージング用のインターフェイスがあれば、それを利用すればよいでしょう。複数アカウントを取得できて、ステージング用にアカウントが分けられるのならそれでも構いません。Slack通知を行う場合、ステージング用のチャンネルを用意出来ればそちらに通知すればよいのです。

ここでも一番困るのは電子メールでしょうか。電子メールシステムは全世界に唯一しか存在しません。現実的にはテスト用のメールアドレスを用意して、そちらに配信できればテストOKとするわけですが、これでは特定のドメインへの配信に失敗するような不具合があったとしても検出できません。100万通のメールを配信する負荷テストをする場合に、同一メールアドレスに100万通配信しても負荷テストにはなりません。
D&Dするとランダム文字列パスワードで圧縮するPowershellスクリプト

#準備
https://sevenzip.osdn.jp/download.html
から7-Zip コマンドラインバージョンをダウンロードします。

Powershellスクリプトを作成します。

```powershell:compress.ps1

Function CreatePass{
 $upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()
 $lower = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
 $number = "0123456789".ToCharArray()
 $symbol = "_+-*/=@\%!?".ToCharArray()
 $pwdchar  = "".ToCharArray()
 $up = 3 #upperの文字数
 $low = 3 #lowerの文字数
 $num = 2 #numberの文字数
 $symb = 2 #symbolの文字数

 $pwdchar = Get-Random -InputObject $upper -Count $up
 $pwdchar = $pwdchar + (Get-Random -InputObject $lower -Count $low)
 $pwdchar = $pwdchar + (Get-Random -InputObject $number -Count $num)
 $pwdchar = $pwdchar + (Get-Random -InputObject $symbol -Count $symb)

 $pwdchar = $pwdchar | sort -prop @{Exp={[Guid]::NewGuid()}}

 $password = $pwdchar -join ""

 Set-Clipboard $password
 return $password
}

$PSPATH = (Convert-Path .)
$DESTPATH = ""
$FILE = "" 
$ZIPNAME = ""

foreach($arg in $Args) {
 if ($FILE -eq "") {
  $FILE = $arg
  $DESTPATH = Split-Path -Parent $FILE
  $ZIPNAME = [System.IO.Path]::GetFileNameWithoutExtension($FILE) + ".zip"
  $FILE = """$FILE"""
 } else {
  $FILE = $FILE + " " + """$arg"""
 }
}

$PASS = CreatePass
$CMD = $PSPATH + "\7za.exe a -ssw -p" + $PASS + " " + """$ZIPNAME""" + " " + $FILE 

cd $DESTPATH
Invoke-Expression $CMD

```

#使い方
※compress.ps1、7za.exeは同フォルダに格納してください。

① compress.ps1のショートカットを作成し、プロパティのリンク先を「powershell -NoProfile -File ＜compress.ps1のパス>」に変更します。
② ショートカットに圧縮対象のファイルをD&Dします。もしくはショートカットをshell:sendtoに置いて右クリックの送るから実行します。
④ 圧縮時に使用したパスワードがクリップボードにコピーされます。

#参考文献
[コマンドでZIPや7zにパスワードを付ける](https://sevenzip.osdn.jp/howto/dos-command-password.html)
Raspberry Pi Zero WH カメラモジュールで遊ぶ その1

前→[Raspberry Pi Zero WH カメラモジュールで遊ぶ その0](https://qiita.com/yuzzy22/items/fad80fd6f5084ba6ea67)
次→[Raspberry Pi Zero WH カメラモジュールで遊ぶ その2](https://qiita.com/yuzzy22/items/6c66bde9cc110b2efef2)

本記事では、pythonの設定とカメラモジュールの動作確認を行います。

<!-- TOC -->

- [1. python初期設定](#1-python初期設定)
    - [1.1. リンク設定](#11-リンク設定)
- [2. カメラモジュールの接続](#2-カメラモジュールの接続)
    - [2.1. 接続設定](#21-接続設定)
    - [2.2. 静止画撮影テスト](#22-静止画撮影テスト)
- [3. 各種pythonライブラリの追加](#3-各種pythonライブラリの追加)
    - [3.1. OpenCV](#31-opencv)
- [4. OpenCVを使って動かしてみる](#4-opencvを使って動かしてみる)
    - [4.1. 表示テスト](#41-表示テスト)

<!-- /TOC -->

## 1. python初期設定

### 1.1. リンク設定

今回導入したRaspberry Pi OSのバージョンでは、pythonのシンボリックリンクがpython2(2.7.16)に張られていたので、python3(3.7.3)にリンクを張り替えます。
補足として、Raspberry Pi OSのPythonライブラリは、pipよりもapt-getで入れたものの方が高速のようです。

```bash
# シンボリックリンクの張り替え
$ cd /usr/bin
$ sudo unlink python
$ sudo ln -s python3 python
```

## 2. カメラモジュールの接続

### 2.1. 接続設定

Raspberry Pi本体にカメラモジュールのケーブルを接続した後、「設定」→「Raspberry Piの設定」→「インターフェース」から、カメラを有効化します。
その後、カメラモジュールが正常に接続されているか、確認します。

```bash
# カメラ接続の確認
$ vcgencmd get_camera
```

"supported=1 detected=1"と表示されれば、正常に接続されています。

### 2.2. 静止画撮影テスト

テストとして、静止画を撮影してみます。

```bash
# デフォルトでは/home/piに保存
$ sudo raspistill -o image.jpg
```

## 3. 各種pythonライブラリの追加

### 3.1. OpenCV

はじめにOpenCVが依存しているライブラリをインストールします。

```bash
# libhdf5-xxxのバージョン確認(今回のバージョンは103)
$ sudo apt-cache search libhdf5

# 各種ライブラリのインストール
$ sudo apt-get install libhdf5-dev libhdf5-serial-dev libhdf5-103
$ sudo apt-get install libqtgui4 libqtwebkit4 libqt4-test python3-pyqt5
$ sudo apt-get install libatlas-base-dev
$ sudo apt-get install libjasper-dev
```

次にOpenCVをインストールします。

```bash
# OpenCVのインストール
$ sudo pip3 --default-timeout=1000 install opencv-python
```

このままだと`import cv2`でエラーを吐くことがあるため、環境変数を設定します。
"~/.bashrc"に以下を追記し、`source ~/.bashrc`を実行します。

```bash
# ~/.bashrcに追記
export LD_PRELOAD=/usr/lib/arm-linux-gnueabihf/libatomic.so.1
```

## 4. OpenCVを使って動かしてみる

### 4.1. 表示テスト

カメラからキャプチャした画面をグレースケール化して表示、qキーが押されたら終了するコードです。

```python:capture_test.py

import cv2

def capture():
    # 0 is a camera number.
    cap = cv2.VideoCapture(0)

    print('### Break is \'q\' key.')

    while(cap.isOpened()):
        # 'ret' is a boolean.
        ret, frame = cap.read()

        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        cv2.imshow('frame', gray)

        # Break is 'q' key.
        if cv2.waitKey(1) & 0xff == ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows()

if __name__=='__main__':
    capture()
```
Dockerfile内で動的なENVの設定は出来なかった。


```Dockerfile
RUN yum -y install java-11-openjdk java-11-openjdk-devel
ENV JAVA_HOME /usr/lib/jvm/java-11-openjdk-11.0.8.10-0.el7_8.x86_64
ENV PATH $PATH:$JAVA_HOME/bin
```

こんな感じのDockerfile作ってたんだけど、yumでopenjdkインストールすると`java-11-openjdk-11.0.8.10-0.el7_8.x86_64`の部分がVerUpごとに変わっちゃって、その度に修正しなきゃならないんだよね…。滅多にDockerImage更新することないからいいっちゃいいんだけど。
なので動的にENVの設定が出来ないかなあ？と思ってたんだけど、出来ないみたいだね。

```
RUN  export JAVA_HOME="$(dirname $(dirname $(readlink -f $(which java))))"
```

本当はこんな感じのことができればよかったんだけど。


https://github.com/moby/moby/issues/29110#issuecomment-453718228

セキュリティリスクだから駄目なのか。確かになー。
下みたいにすればいいよって書いてあるけど、Docker内でyumやってるから無理なんだよなこれ。

> However, you can pass the information through a --build-arg (ARG) when building an image;

```Dockerfile
FROM busybox
ARG BUILD_HOST_NAME
ENV DOCKERBUILDHOST=${BUILD_HOST_NAME:-unkown}
RUN echo $DOCKERBUILDHOST
```

> And build the image with;
>> docker build --build-arg BUILD_HOST_NAME=$(hostname) .

> Or, if you want to copy information from an existing env-var on the host;
>> export BUILD_HOST_NAME=foobar
>> docker build --build-arg BUILD_HOST_NAME .

# 他も調べてみた。
AWSのCodeBuildイメージはCoretto11なので、ディレクトリ固定。
https://github.com/aws/aws-codebuild-docker-images

まあこの場合だけの話であれば、普通は`FROM adoptopenjdk/openjdk11:latest`としとけば良いだけだけどねえ。
【学習メモ】Docker（コンテナの詳細）

#コンテナについて
docker runの「run」って？
run = create + start
create:コンテナを作る
start:コンテナを起動してデフォルトコマンドを実行しExitedされる


```
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"bash\": executable file not found in $PATH": unknown.
```
こうなったとき、Ubuntuは指定しなくても、bashが自動的に実行される

ただ、デフォルトコマンドは下記のように上書きできる

```
user$ docker run ubuntu ls #デフォルトにするコマンド
```

#-itの正体
-i:インプット可能な状態にする（キーボードで
打ったものをちゃんとコンテナに反映させる）
-t:出力結果をきれいにする

#コンテナの削除
exitしたコンテナは業務で使うことないので削除が必要

またSTATUSが「UP」にある場合、**削除ができない**ので、下記コマンドで削除

```
docker stop コンテナのNAME
```

#コンテナの名前を指定して使いたいとき
・起動させ続けるコンテナを立てるとき
・共有サーバーを使うとき
・他のプログラムで使用するとき

```
docker run --name <コンテナ名:sample_container> <image:ubuntu>
```

#コンテナの削除ーdetachedとforeground
```
$ docker run -d <image>    #コンテナ起動後にdetachする（バックグラウンドで動かす）
$ docker run --rm <image>  #コンテナをExitしたら削除する（1回きりのコンテナ）
```
CKA/CKAD試験予約で、軽くハマったこと

#簡単な自己紹介
- インフラ関連のHardware/Softwareの提案をしているPresalesエンジニアです。
- インフラ関連の製品(VMware/サーバ/ストレージ/ネットワーク)/OSS/クラウドなど勉強をしてますので、自分の備忘録のために書こうと思います。
- 不定期で、細く長く続けていこうかと。

#CKA/CKADを受けました！
コンテナ/Kubernetesに関して全くの素人だったので、CKA/CKADを4-5ヶ月勉強して、7月/8月になんとか合格しました。
CKA/CKADテスト対策どうやったとか、テストを受けるときのTipsとか追々書いていければと思います。
今日は初めての投稿なので、簡単な内容を共有します。

CKA/CKADの試験の予約方法です。
登録方法/予約方法のやり方を正式にかいてあるWebページがあったりするかもしれませんが、
全く読まず予約しようとした結果、軽くハマったので、その点を共有です。

#CKA/CKAD試験予約で軽くハマったこと
前提:LinuxFoundation上で、アカウントを作成して、CKA/CKADの試験を購入していること。
試験の予約をLinuxFoundationのWebサイト上で進めていくと、「Exam Preparation Checklist」で試験日時を予約する必要があるのですが、若干Tricky。。。

###軽ハマりした内容
下記の画像のように、「Schedule an Exam」と「Take Exam」以外チェックを完了したあと、
「Schedule an Exam」の欄に"ボタンがActiveになるまでまって。最大30分まで。"(Please wait xxx)とあったので、15分ぐらい待ったですが、"Schedule"ボタンがActiveにならず。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284059/4279530e-f025-ccc3-a39a-cb1a2d8f5e38.png)

###解決方法
解決方法は、待つのではなく、「Check System Requirement」からCompatibility Checkをした後(前でもできる？)に、psiから「Sing In With」でLinuxFoundationにログインして、そこから試験日時をスケジュールする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284059/86fee435-5a91-b3d7-3416-bf852ed80de5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284059/7b4dc892-082f-fe95-9502-7f4078beb6f1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284059/bc97754e-ec9d-709c-804b-7af33a4bf1aa.png)

ということで、無事に試験および試験日時を選択するページに進むことができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284059/46f54329-3c56-1e1f-5008-1de3773142c3.png)

#おわりに
- 大した内容ではないですが、私も時間がない中、急いで試験予約をしようと思って、なかなか予約できず困ったので、みなさんは予約する時には気を付けましょう！
- 初めての投稿で分かりづらいところあるかもしれませんが、今後とも宜しくお願いします。
*As of 2020/08/14
量が多いAmazon S3のファイルをローカルのDBに読み込む

[前回](https://qiita.com/eiryu/items/aff67014421dd1f1b8f7)、Treasure DataからAmazon S3にデータをバルクエクスポートした。

ファイルが分割、圧縮されてエクスポートされているため、

1. ダウンロードして
2. 解凍して
3. MySQLにインポートして
4. ダウンロードしたファイルを削除する

スクリプトを書いてみた。

※ 事前にデータベース、テーブルは作成しておくこと
※ `load data infile` が実行出来るMySQL設定となっていること


```groovy
// Groovy Version: 2.5.0 JVM: 1.8.0_181 Vendor: Azul Systems, Inc. OS: Mac OS X
@GrabConfig(systemClassLoader = true)
@Grab('mysql:mysql-connector-java:5.1.31')
@Grab('com.amazonaws:aws-java-sdk-s3:1.11.839')
import com.amazonaws.regions.Regions
import com.amazonaws.services.s3.AmazonS3
import com.amazonaws.services.s3.AmazonS3ClientBuilder
import groovy.sql.Sql
import groovyx.gpars.GParsPool

import java.nio.file.Files
import java.nio.file.StandardCopyOption


AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
        .withRegion(Regions.US_EAST_1)
        .build()

// 適宜パラメータ化
def db = Sql.newInstance("jdbc:mysql://localhost/database_name?useLegacyDatetimeCode=false", "username", "password", "com.mysql.jdbc.Driver")


GParsPool.withPool {
    // 出力されたファイル数分に調整すること
    (0..100).eachParallel {
        def fileNumber = String.format('%03d', it)
        log(fileNumber, "Start")

        s3Client.getObject('bucketName', "table_name/export.$fileNumber.0000.tsv.gz").getObjectContent().withCloseable { objectContent ->

            File file = File.createTempFile('table_name-', '.tsv.gz')
            def downloadPath = file.absolutePath

            def tsvfilePath = downloadPath.replaceAll('\\.gz$', '')
            try {
                log(fileNumber, "Download to $downloadPath")
                Files.copy(objectContent, file.toPath(), StandardCopyOption.REPLACE_EXISTING)

                log(fileNumber, "Decompress")
                "unpigz $downloadPath".execute().waitFor() // parallel gunzip

                log(fileNumber, "Import")
                db.execute("load data infile '" + tsvfilePath + "' into table table_name")

                log(fileNumber, "Done")
            } finally {
                file.delete() // 解凍されてファイル名が変わっているため、実質何も起こらないが念のため削除
                new File(tsvfilePath).delete()
            }
        }
    }
}

def log(String fileNumber, String s) {
    println "$fileNumber: $s"
}
```


```bash:実行ログ例
001: Start
000: Start
002: Start
001: Download to /var/folders/ss/hw79tp5d1v3bwgvs_rnjk7jm0000gn/T/table_name-3124187279161512834.tsv.gz
002: Download to /var/folders/ss/hw79tp5d1v3bwgvs_rnjk7jm0000gn/T/table_name-556558218486495982.tsv.gz
000: Download to /var/folders/ss/hw79tp5d1v3bwgvs_rnjk7jm0000gn/T/table_name-3422206227941372411.tsv.gz
001: Decompress
001: Import
002: Decompress
002: Import
001: Done
000: Decompress
000: Import
002: Done
000: Done
```

### 参考

- https://tech.recruit-mp.co.jp/server-side/happy-groovy-life/
- https://qiita.com/eiryu/items/aff67014421dd1f1b8f7
Python3: クッキーの使い方

こちらと同じことを、Python3 で行いました。
[jquery-cookie の使い方](https://qiita.com/ekzemplaro/items/95706b030581cd7a63c5)
[Perl: クッキーの使い方](https://qiita.com/ekzemplaro/items/cbe00d47275db0f49ba0)
[PHP: クッキーの使い方](https://qiita.com/ekzemplaro/items/71843c6685025d215d49)

クッキーを送る

```py:cookie_put.py
#! /usr/bin/python
#
#	cookie_put.py
#
#					Apr/27/2021
# ------------------------------------------------------------------
from http import cookies

C = cookies.SimpleCookie()
C["message"] = "This is a Test by Python."
C["aa"] = "富士山 by Python"
C["bb"] = "谷川岳 by Python"
C["cc"] = "阿蘇山 by Python"

print(C.output())


print("Content-Type: text/html")
print("")
print("<!DOCTYPE html>")
print("<html lang=\"ja\">")
print("<body>")
print("<p>*** cookie_put.py ***</p>")
print("<p>Apr/27/2021</p>")
print("</body>")
print("</html>")
# ------------------------------------------------------------------
```

実行結果
![cookie_put_python.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/b4949628-28bf-5c47-5c22-45a619359842.png)


クッキーを確認

```py:cookie_get.py
#! /usr/bin/python
#
#	cookie_get.py
#
#					Apr/27/2021
# ------------------------------------------------------------------
import os
from http import cookies

cookie = cookies.SimpleCookie()
cookie.load(os.environ["HTTP_COOKIE"])

print("Content-Type: text/html")
print("")

print("<!DOCTYPE html>")
print("<html lang=\"ja\">")
print("<head>")
print("<meta http-equiv=\"CONTENT-TYPE\" content=\"text/html; charset=utf-8\" />")
print("</head>")
print("<body>")
print("<p>*** cookie_get.py *** start ***</p>")
print("message: " + cookie["message"].value + "<br />")
print("aa: " + cookie["aa"].value + "<br />")
print("bb: " + cookie["bb"].value + "<br />")
print("cc: " + cookie["cc"].value + "<br />")
#
# print(session.cookies.get_dict())
print("<p>*** cookie_get.py *** end ***</p>")
print("<p>Apr/27/2021</p>")
print("</body>")
print("</html>")
# ------------------------------------------------------------------
```

実行結果
![cookie_get_python.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/9fb06e5f-9a3c-da97-6438-ff93caa4b988.png)
Rspecの処理を共通化させる

- specフォルダ直下にsupportフォルダを作る
- 共通化したい処理を書いたモジュールを追記

```ruby:json_api_helper
module JsonApiHelpers
  def json
    JSON.parse(response.body)
  end
  def json_data
    json["data"]
  end
end
```
- ```rails_helper.rb```の23行目をコメントアウトする。これをコメントアウトすると、```spec/support```に入っているファイルをループで全て```require```する。

```ruby:rails_helper.rb
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }
```
- ```rails_helper.rb```の下記のブロックに```include```したいファイルを追記。**spec_helper.rbの似たブロックと間違わないように!!!**

```ruby:rails_helper.rb
RSpec.configure do |config|
  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.include FactoryBot::Syntax::Methods
  config.include JsonApiHelpers
```
これで処理が共通化されました！
Linux mkdir コマンド


Linuxコマンド「mkdir」とは、どんな役割なのか？

「mkdir」=「make directory」を略したもの


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690032/ba07536a-a9b9-eede-3f69-116af234f413.png)
「sample」中に新しくディレクトリ（フォルダ）を作ってみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690032/4a1717a6-8cd2-a340-114f-2a241f57f3f5.png)
このように、「sample」内に新たなデェレクトリ（フォルダ）を作ることができました。

また、「mkdir」には複数のオプションがありそれらは以下になります。<img width="461" alt="スクリーンショット 2020-08-11 20.33.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690032/25d689a4-fe7f-961c-9ee0-eeeb33b37b00.png">
LaTeXでの引用の仕方メモ(論文用)。

##手順

- Mendeleyで出力したい文献のリストを作成する。出版年,タイトル, 著者名などでおかしいところがあればMendeleyで修正する。bibファイルとしてエクスポートする（例: hogehoge.bib）。
- texファイルの中で\end{document}の直前に\bibliography{hogehoge}と書く。
- \begin{document}の直後に\bibliographystyle{}を入れる。{}内には.bstファイルを入れる。bstファイルはtexファイルと同じフォルダに置いておく。論文のジャーナルのHPにどのスタイルで書くのか記載されているはずなので、調べて入手する。
- texファイル中でbibファイルに入れた文献を引用する。\citep{Suzuku2020}とか書けばいい。
- 私は文中で[1]などの数字ではなく著者名と出版年で引用したい(例: Suzuki et al. (2020))ので、プリアンブルに\usepackage[,sort]{natbib}を追加する。数字で引用したい場合は\usepackage[numbers,sort]{natbib}にする。
- 最初にLaTeX、次にBiBTeX、そのあと2回LaTeXをコンパイルすれば本文の引用も参考文献リストも正しく表示される。

##小技

- \citep{Suzuki2020}にすると本文では "(Suzuki et al., 2020)" と出力される。
- \citet{Suzuki2020}にすると本文では "Suzuki et al. (2020)" と出力される。
- 引用の直前に文言を入れたい場合は \citep[for review,][]{Mori2020}とコマンド入力すると"(for review, Suzuki et al., 2020)"と表示される。引用の直後に入れたいなら2つ目の[]に書き込む。
画像上に線や文字を加える

#実行環境
[Google Colaboratory](https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja)

#Google Colaboratoryで画像を読み込む為の準備
```python:
from google.colab import files
from google.colab import drive
drive.mount('/content/drive')
img = cv2.imread("/content/drive/My Drive/Colab Notebooks/img/Lenna.bmp")
```

#必要なライブラリの読み込み
```python:
import cv2 #opencv
import matplotlib.pyplot as plt #結果を確認するのに座標がほしいので使用
%matplotlib inline
```

#画像上に線を入れる

```python:
#書き込み情報の設定
pt1 = (50,50)
pt2 = (200,50)
color = (255,0,0)
fontcolor = (0,0,255)
width = 5
fontsize = 0.7
fontwidth = 2
r = 10
fontface = cv2.FONT_HERSHEY_SIMPLEX#フォント種類

#画像にラインを書き込み（設定は上）
cv2.line(img, pt1, pt2, color,width)

#円を書く
cv2.circle(img,pt1,r,color,width)#widthが-1の場合塗りつぶされる。

#文字を書く
cv2.putText(img,'Girl is Lenna!',pt1,fontface,fontsize,fontcolor,fontwidth)

#画像の確認(opencvとmatplotでRGBの順序が違うため変換し表示)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
```

#結果
![q1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610285/60f82d2b-2854-e967-5d16-2cb8e0243fbf.png)



#わかったこと
ラインのwidthは、プラスマイナスの幅ではなく、文字通りそのままの幅。
円の径は、半径で指定する必要がある。
文字の座標始点は、デフォルト値だと文字の左下になる。
変更したい場合、bottomLeftOrigin = True を指定すると
始点が左上になる。ただし文字もひっくり返る。
フロント童貞がReactでBootstrapを使う



## 参考
まんまです。ありがとうございますm()m
https://qiita.com/NShimpei/items/f3962353677dff00b7e6

## 手順

### サンプル用のReactアプリを用意

```
npx create-react-app bootstrap-test-project
```

```
cd bootstrap-test-project/
```

### bootstrap用モジュールのインストール

```
npm install react-bootstrap bootstrap
```

### linkタグでbootstrapの設定諸々を読み込む

```public/index.html
<!DOCTYPE html>                                                                             
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <link
      rel="stylesheet"
      href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"アクセス
      integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"      crossorigin="anonymous"
    />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
```

追記する箇所アクセスアクセス

```
    <link
      rel="stylesheet"
      href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
      integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"      crossorigin="anonymous"
    />
```

### App.jsに利用するタグ？てきなものを書く

```src/App.js
import React, { Component } from 'react';                                                   
import Button from 'react-bootstrap/Button';

class App extends Component {
    render() {
        return (
            <div>
                <Button> ボタンだよ </Button>
            </div>
        );
    }   
}
export default App;
```

### 起動

```
npm start
```

### 動作確認
- `localhost:3000`へアクセス


![Screenshot from 2020-08-14 13-50-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/d90cedb6-d38b-e397-d3da-9e4d7a5d0e49.png)
お名前ドットコムのメール無視してたら制限かけられた話

awsでデプロイしてお名前ドットコムとroute53使ってドメイン取得したから就活するぞー！！！って息巻いていたらサイトにアクセス出来なくなってしまった話です。

# 結論
お名前ドットコムから送られてくる証人メールを無視していた事
たったこれだけです！！！くだらない！！！
![スクリーンショット 2020-08-14 13.28.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431966/eb3444ec-7f9e-d70a-89e2-6c9380ca6d97.png)
もし初学者がデプロイしてこの画面になったらawsではなくメールを確認して見て欲しい。お名前ドットコムから重要メールがきているはずです。それを確認さえすればこんな事は起きないので！！

# 何故起きたのか
言い訳にしかなりませんが、きっとお名前ドットコムさんからのメールがしつこいからです。ただの責任転嫁です。
ほぼ毎日スパムかよ！ってほどのメールが送られてくるのでメールを確認する前に開封済みにしていたため重要メールすらも無視してしまったのです。

# どうすれば防げたか
メールの確認！これだけです。ちゃんとメールを見ていたらお名前ドットコムさんから制限を食らう事がなかったはずです。皆さんもメールはきちんと見ましょう！
Prettier の ifBreak を現在の group 以外に使う

Prettier の doc ユーティリティに `ifBreak` というのがあります。
現在の group が break されてるかどうかに応じて print する doc を変えることができる便利ユーティリティです。
実は、現在の group 以外の group を指定することが可能です。

group を作るときに id を付与しておくと `ifBreak` でその group を見ることができます。

```js
const printed = group(concat(parts), { id: Symbol.for("foo") });
```
```js
const printed = ifBreak("foo", "bar", { groupId: Symbol.for("foo") });
```

最近知った、大変便利。
TeraTermマクロを信じることにした

#自動化が叫ばれる昨今いかがお過ごしですか？
##作成の経緯
2020年 8月初旬 1500個のcommandをUbuntuに連続発行するという絶望的な作業が舞い込んだ。
あーめんどくせーAnsible PlayBookとかめんどくせーよと、スイカバー食べながら思った。
あ、そうだ別にTeraTermでいいじゃん！ と思い作りましたので、備忘かねて記載しました。

##要件
・テキストファイルに記載しているcommandを1行づつ実行したい。
・ついでにログの自動でとってもらおう

##コード

```text


;======================================================
;teratermマクロ
;コマンドファイルを読み込み順次実行するマクロです。
;
;コマンドファイル順次実行時、プロンプト出力を待ってから
;次のコマンドを実行するか、 指定時間ポーズするかを選択できます。
;コマンドファイル実行前に、デフォルトで最初に実行したい
;コマンドも記載可能
;ログを自動で取得します。
;======================================================

;-----------------------------------------------------------
;初期設定
;-----------------------------------------------------------

;ログ自動保存
;ログ保存先
LOGSPATH = 'C:\test\log\'

;ログファイル名
getdate LOG_NAME 'teraterm(&h)_%Y%m%d_%H%M%S.log'

FULLPATH = LOGSPATH
strconcat FULLPATH LOG_NAME

;ログ取得開始
logopen FULLPATH 1 1

;タイトル設定
settitle 'コマンドファイルの順次実行マクロ'

;コマンドファイル※commandを羅列しているファイルをフルパス指定
cmdfile = 'C:\Users\test\Desktop\apt-get.txt'

;コマンドファイル順次実行時、プロンプト出力を待つか(1)
;指定時間ポーズするか(1以外)、どちらかを設定
wait_prompt_f = 0

;プロンプト※表示プロンプトに合わせて編集
wait_prompt = 'test@testvm:~$'

;ポーズタイム(s)
pause_time = 1

;-----------------------------------------------------------
;デフォルトで最初に実行したいコマンド
;-----------------------------------------------------------

default_input = 1 ;無ければ0にする

if default_input = 1 then
sendln 'date'
sendln 'whoami'
sendln 'hostname'
sendln 'pwd'
endif

;-----------------------------------------------------------
;コマンドファイルの順次実行
;-----------------------------------------------------------
;ファイルオープン
fileopen fh cmdfile 0

;ファイル内の実行行数
count = 1

while 1
;コマンドファイルから１行読み込み
filereadln fh buf

;読み込めない時はループを抜ける
if result goto breakloop

;ファイル内の実行行数表示
int2str count_str count ;数値を文字に変換
sendln '### ' count_str ' 行目を実行します ###'

;コマンド実行
sendln buf

if wait_prompt_f = 1 then
;プロンプト出力を待つ
wait wait_prompt
else
;指定時間ポーズする
pause pause_time
endif

count = count + 1
endwhile

:breakloop

;ファイルクローズ
fileclose fh

sendln

```

###おわりに
Ansible等とは違いEngineもいらずに使えるので、とても楽ちんでした。
運用等で例えば仮想マシン払い出し作業を自動化(カタログ化）するのは、
やはりAnsible(Tower)とかが必要だが、簡単に済ませたい場合は
TeraTermマクロも捨てたもんじゃないなぁと感じた出来事でした。
PHP: クッキーの使い方

こちらと同様なことを、PHP で行いました。
[jquery-cookie の使い方](https://qiita.com/ekzemplaro/items/95706b030581cd7a63c5)
[Perl: クッキーの使い方](https://qiita.com/ekzemplaro/items/cbe00d47275db0f49ba0)

クッキーを送る

```php:cookie_put.php
<?php
// ------------------------------------------------------------------
//
//	cookie_put.php
//
setcookie('message','これはテストです。by PHP',['samesite' => 'None', 'secure' =
> true]);
setcookie('aa','りんご by PHP',['samesite' => 'None', 'secure' => true]);
setcookie('bb','ぶどうby PHP',['samesite' => 'None', 'secure' => true]);
setcookie('cc','桃 by PHP',['samesite' => 'None', 'secure' => true]);

echo "<!DOCTYPE html>";
echo "<html lang=\"ja\">";
echo "<body>";

echo "Aug/14/2020<p/>";
echo "</body>";
echo "</html>";
// ------------------------------------------------------------------
?>
```

![cookie_may0101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/02f61183-168e-efaa-d118-0352bfebf59c.png)


クッキーを確認

```php:cookie_get.php
<?php
// ------------------------------------------------------------------
//
//	cookie_get.php
//
echo "<!DOCTYPE html>";
echo "<html lang=\"ja\">";
echo "<body>";
echo "message: " . $_COOKIE['message'] . "<br />";
echo "aa: " . $_COOKIE['aa'] . "<br />";
echo "bb: " . $_COOKIE['bb'] . "<br />";
echo "cc: " . $_COOKIE['cc'] . "<br />";

echo "Aug/14/2020<p/>";
echo "</body>";
echo "</html>";
// ------------------------------------------------------------------
?>
```
5分で出来る！AndroidStudioのLiveTemplate

# はじめに
DatabindingしたViewModelから、クリックイベントなどをLiveDataでFragmentに通知するとき、privateなMutableLiveDataとpublicなLiveDataを作るの面倒だな〜と思ったことはありませんか？？
私はあります！！

```kotlin
class SampleViewModel : ViewModel() {
    private val _sampleButtonClick = MutableLiveData<Unit>()
    val sampleButtonClick: LiveData<Unit> = _sampleButtonClick
}
```

今回は、AndroidStudioのLiveTemplateを使うことにより簡単に書けることに気づいたのでそれを紹介します！
私は今までLiveTemplateは使うことはありつつ作ったことはなかったのですが、作るのもとても簡単でした！

# LiveTemplateとは？


> ライブ テンプレートにコード スニペットを入力し、コードの小さなチャンクをすばやく挿入して補完できます。ライブ テンプレートを挿入するには、テンプレートの短縮名を入力して Tab キーを押します。そうすると、テンプレートに関連付けられたコード スニペットがコードに挿入されます。
たとえば、短縮名 newInstance を入力して Tab キーを押すと、新しいフラグメント インスタンスのコードが引数プレースホルダとともに挿入されます。 また、fbc と入力すると、findViewById() メソッドがキャストおよびリソース ID 構文とともに挿入されます。
(AndroidDeveloperの[コード生産性ページ](https://developer.android.com/studio/write?hl=ja#create_custom_code-completion_templates)より)

ToastやnewInstance、java時代にはpsfsやpsfiにお世話になった人もいるのではないでしょうか。

# 実際の動き
変数名とクラスを入れるだけ！
![livetemplate2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192408/914285e5-2e41-1f41-dbd2-a94659e0a8df.gif)

# 作り方
AndroidStudioのPreferencesから作ることができます。
AndroidStudio > Preferences > Editor > Live Templates
![Screenshot at Aug 13 13-40-36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192408/41e9d12f-a0b1-5330-4366-94a4bb5b427f.png)

今回はKotlinファイルに対して追加するので、AndroidKotlinを選択して、+ボタンで追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192408/d44a5458-b369-fdde-0675-32ef2c8fb3b6.png)

下部のボックス呼び出し名や中身を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192408/d774e1ca-3d6e-bcbb-cc35-60a57561f0d3.png)

* Abbreviation
 * これが呼び出し名
* Description
 * 説明(なくてもOK。Preferencesで呼び出し名の右側に表示される)
* Template text
 * 本体
 * 変数は$$で囲むことで追加できます。
 * 画像から分かると思いますが、クラス名はフルパスで書きます。<br>
   実行時にimportしてくれます。(書かないと自分でimportしなきゃいけないので注意)
* Reformat according to style
 * これにチェックを入れると、使用時にフォーマットを掛けてくれるのでオススメ 
* Applicatable in Kotlin:
 * 適用する(補完が出てくる)箇所。これを指定しないと、LiveTemplateが出てきません。
 * 今回の`livedata`はclassのフィールドで利用するので、`class`を選択しました。<br>
   他にもTop-levelやCommentもあったりします。

```kotlin:コピペ用
private val _$name$ = androidx.lifecycle.MutableLiveData<$clazz$>()
val $name$: androidx.lifecycle.LiveData<$clazz$> = _$name$
```
すでにあるテンプレートの中も見られるので、参考になってとても助かりました。

# おわりに
ViewModelからFragmentにクリックイベントをLiveDataで伝える場合は、消費できる[Eventクラス(I/Oのソース)](https://github.com/google/iosched/blob/master/shared/src/main/java/com/google/samples/apps/iosched/shared/result/Event.kt)を使っている人も多いかもしれません。
私はeventLiveDataというテンプレートも作っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192408/75f64fa5-3d44-2f4c-6836-574cd7f23a0a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192408/f6c80cdc-c3b9-d4e5-4824-66ad92ed8735.png)
何度も書いてるな・・・と思うコードがあれば、気軽にテンプレートに追加していくと良さそうです！
Jestのpuppeteerサンプルを実行


参照したサンプルコード
[Using with puppeteer · Jest](https://jestjs.io/docs/en/puppeteer.html)

必要なライブラリをインストール

```
% yarn add --dev jest-puppeteer jest puppeteer
```

package.jsonにscriptsとjestを追記

```package.json
{
  "devDependencies": {
    "jest": "^26.4.0",
    "jest-puppeteer": "^4.4.0",
    "puppeteer": "^5.2.1"
  },
  "scripts": {
    "test": "jest"
  },
  "jest": {
    "preset": "jest-puppeteer"
  }
}
```

テストコードをgoogle.test.jsというファイル名で保存

```google.test.js
describe('Google', () => {
  beforeAll(async () => {
    await page.goto('https://google.com');
  });

  it('should be titled "Google"', async () => {
    await expect(page.title()).resolves.toMatch('Google');
  });
});
```

実行

```java
% yarn test
yarn run v1.22.4
warning package.json: No license field
$ jest
 PASS  ./google.test.js
  Google
    ✓ should be titled "Google" (4 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.772 s
Ran all test suites.
✨  Done in 8.96s.
```

ファイル構成

```bash

% ls -1
google.test.js
node_modules
package.json
yarn.lock
```
Docker Hub の新しいコンテナ・イメージ保管ポリシー（参考訳）

原文：

Container Image Retention Policy | Docker
https://www.docker.com/pricing/retentionfaq

こちらに書かれている内容を把握するためのものです。

# TL;DR（今北産業）

- Docker Hub の Free プランは、6ヶ月間使っていない（inactive）イメージが削除対象で、2020 年 11 月 1 日から適用
- 「inactive」タグとは、一定期間（現在の Free プランは 6ヶ月間）使われていないイメージ（pullもpushもしていない）が対象
- Docker Hub の容量は 15PB で、半年以上使われていないイメージが 4.5PB →運用最適化とサービス強化のため実施

 
# コンテナ・イメージ保管ポリシー (Container Image Retention Policy)

## FAQ

### Docker 利用規約とは何ですか？

Docker 利用規約（Terms of service）とは、Docker プロダクトとサービスの利用に適用する、あなたと Docker 間における合意です。リンクをクリックすると、 [Docker 利用規約](https://www.docker.com/legal) の全文を表示します。

### Docker 利用規約の発行はいつですか？

[Docker 利用規約](https://www.docker.com/legal) の更新は、直ちに発効します。

### 利用規約の何が変わりましたか？

最も著しい変更はセクション 2.5 です。全ての変更を確認するために、私たちは [利用規約](https://www.docker.com/legal) 全文を読むのを推奨します。

### コンテナ・イメージの保管期限とは何ですか？ 私のアカウントにどのような影響がありますか？

イメージの保管（image retention）は、ユーザ・アカウントで保管している各イメージの利用状況に基づきます。自分のサブスクリプション・プランで定められた期間において、もしもイメージが pull あるいは push のどちらもなければ、そのイメージにはタグ「inactive」（使用されていない）が付けられます。「inactive」タグが付いたあらゆるイメージが削除予定です。 **Free**  individual（個人）または organization プランのアカウントのみ、イメージの保管期限に従う必要があります。Docker Hub で利用可能になる新しいダッシュボードでは、コンテナイメージの全ての状態を一覧表示できるようになります。

### コンテナ・イメージ保管期限とは何が新しいのですか？

Docker はコンテナ・イメージ保管期限ポリシーを  2020 年 11 月 1 日から実施します。コンテナ・イメージ保管ポリシーは、以下のプランが適用対象です。

- Free プランでは、イメージ保管期限が6ヶ月
- Pro および Team プランでは、イメージ保管期限が無制限

### 「inactive」なイメージとは何ですか？

「inactive」イメージとは、イメージのリポジトリから6ヶ月（半年間） push も pull のどちらも行われていないコンテナ・イメージです。

### どのようにしてイメージの状態を確認できますか？

Docker Hub リポジトリ内にある全てのイメージに「Last pushed」（最終送信）の日付があり、これはアカウントでリポジトリにログインすると簡単に見つけられます。

### inactive イメージが有効期限に至るとどうなりますか？

2020 年 11 月 1 日の当初、「inactive」とマークされた全てのイメージが削除予定になります。また、アカウントの所有者は「inactive」イメージが削除予定であるというメールの通知が届きます。

### コンテナ・イメージを無期限にできますか？

イメージ保管期限が適用されるのは **Free** の個人および organization アカウントのみです。 **Pro** および **Team** アカウントは保管期限の適用対象外です。もしも **Free** アカウントをお持ちであれば、**Pro** や **Team** アカウントに定期プランで月額5ドルからでアップグレードできます。詳しい情報はこちらをご覧ください：https://www.docker.com/pricing

### なぜ Docker は「inactive」イメージ・ポリシーを導入するのですか？

Docker Hub は 15PB のデータを保管する世界最大のコンテナ・イメージ保管庫（リポジトリ）です。Docker Hub に保管されているコンテナ・イメージの詳細を解析したところ、4.5PB のデータが半年以上にわたって push または pull されていないことが分かりました。
私たちは運用の最適化にこのような取り組みを行い、そして、アプリケーションの構築と移動のために Docker Hub サービスを使う世界中の開発者と開発チームのため、一層のサービス強化を行います。


## 原文

Container Image Retention Policy | Docker
https://www.docker.com/pricing/retentionfaq
JavaScriptの制御構文(4)〜for...in命令とfor...of命令〜

# はじめに

こんにちは！
今日も備忘録として投稿させて頂きます！
昨日は、繰り返し処理で使うfor命令について投稿しましたが、今日は、連想配列(オブジェクト)や配列などの繰り返し処理を実行する際に使う、for...in命令、for...of命令について投稿します！

# for…in命令
連想配列(オブジェクト)の要素を取り出して、先頭から繰り返し処理をしていく命令には、for…in命令を使います。

```
for(仮変数 in 連想配列) {
	繰り返す処理
}
```


# for…of命令
配列などを順番に列挙し繰り返し処理をしていく命令には、for…of命令を使います。for…of命令は、ES2015で新しく追加された命令です。
配列以外にも、NodeListやイテレータ・ジェネレータなども処理できます。

```
for(仮変数 of 列挙可能なオブジェクト) {
	繰り返す処理
}
```
for...in命令とfor...of命令の両方に、共通して見られる、「仮変数」とは、連想配列(オブジェクト)のキーや、配列の要素を一時的に格納する変数のことです。名前はなんでもオッケー！
(ただし、あとで見てもわかりやすいものにすること。)

# 具体例

例)連想配列(for...in命令)

```
let datas = { apple: 300, banana: 120, watermelon: 500 };
for (data in datas) {
	console.log(data + '=' + datas[data]);
}

// 結果
// apple=300
// banana=120
// watermelon=500
```
上記の例では、変数datasに連想配列(オブジェクト)が格納されており、変数dataに、apple・banana・watermelonといったキーが一旦格納されます。
そして、繰り返し処理をする際に、
連想配列全体の変数datas[ キーを格納している変数data ]
によって、要素を順に取り出して処理をしています。
**また、配列の時にも使えます!**
が、あまり推奨はされていないみたいですね...

例)配列など(for...of命令)

```
let datas = ['apple', 'banana', 'watermelon'];
for (data of datas) {
	console.log(data)
}

// 結果
// apple
// banana
// watermelon
```
上記の例では、変数datasに配列が格納されており、変数dataに、apple・banana・watermelonといった、配列の要素が一旦格納されます。
そして、繰り返し処理をする際に、
要素を指定すると、処理が実行されて、consoleには要素の値が順に表示されます。
**ただし、連想配列には使えません。**

このように、連想配列(オブジェクト)や配列に関しては、通常のfor命令ではなく、for…in命令や、for…of命令を利用します。
これまで、いくつか個人開発をしていて思うのは、この文法結構よく使っているなと感じます！
特に、最初に紹介した、for...in命令は、ユーザーによる入力値をリスト表示したりする時など、出てきたりしましたね！

今日はここまでです！
理解不足等による、不備等ございましたら、コメントお願い致します！

# 参考文献

山田祥寛著『[改訂新版]JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで』(2018)
※第1刷は、2016年。
PKGBUILDでチェックサムを動的に取得する

Arch LinuxでFileZillaのパッケージのPKGBUILDを書いてる時、ふとsha512sumsを動的に生成したくなったのでそのためのメモです。

## やりたいこと
ネット上にチェックサムがあるのでそれを使用して`source`で取得したファイルを検証したい。

## 問題点
`makepkg`sha512sum関連の確認は`source`の取得前に行うので`source`に`sha512`のファイルを含めて`cat`という方法は使えない。
また`sha512sums`を生成する関数は存在しない。

# 解決策
`sha512sums`配列の中に無理やりコマンドを入れてネット上のテキストファイルをcurlで取得する。

```bash
sha512sums=(
    "$(
        _url='https://dl2.cdn.filezilla-project.org/client/FileZilla_3.49.1.sha512?h=Is3dK9yMEdrdZ_TqQmoXJA&x=1597380525'
        _sum=$(curl -L "${_url}" | grep "FileZilla_${pkgver}_${machine_arch}-linux-gnu.tar.bz2" | awk '{print $1}')
        if [[ ! "${?}" = 0 ]] || [[ ! -v "_sum" ]]; then
            echo -n "SKIP"
        else
            echo -n "${_sum}"
        fi
    )"
)
```

`curl`が異常終了した際には`SKIP`を返して検証をスキップする。
正常終了してしっかりと値を取得できた場合にのみ値を返して検証する。

```
$ makepke -sf
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1152  100  1152    0     0   1050      0  0:00:01  0:00:01 --:--:--  1050
==> パッケージを作成: filezilla-bin 3.49.1-1 (2020年08月14日 13時12分01秒)
==> ランタイムの依存関係を確認...
==> ビルドタイムの依存関係を確認...
==> ソースを取得...
  -> ダウンロード FileZilla_3.49.1_x86_64-linux-gnu.tar.bz2...
--2020-08-14 13:12:01--  https://dl3.cdn.filezilla-project.org/client/FileZilla_3.49.1_x86_64-linux-gnu.tar.bz2?h=B4YMUwovpvAXnVxTDxxU6w&x=1597378984
CA証明書 '/etc/ssl/certs/ca-certificates.crt' をロードしました
dl3.cdn.filezilla-project.org (dl3.cdn.filezilla-project.org) をDNSに問いあわせています... 2a01:4f8:1c0c:5ed7::1, 195.201.38.126
dl3.cdn.filezilla-project.org (dl3.cdn.filezilla-project.org)|2a01:4f8:1c0c:5ed7::1|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 9768095 (9.3M) [application/octet-stream]
`FileZilla_3.49.1_x86_64-linux-gnu.tar.bz2.part' に保存中

FileZilla_3.49.1_x86_64-linux-g 100%[======================================================>]   9.32M  1.75MB/s 時間 5.8s     

2020-08-14 13:12:09 (1.59 MB/s) - `FileZilla_3.49.1_x86_64-linux-gnu.tar.bz2.part' へ保存完了 [9768095/9768095]

==> source で sha512sums ファイルを検証...
    FileZilla_3.49.1_x86_64-linux-gnu.tar.bz2 ... 成功
==> ソースを展開...
  -> FileZilla_3.49.1_x86_64-linux-gnu.tar.bz2 を bsdtar で展開
==> fakeroot 環境を開始します...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1152  100  1152    0     0   1327      0 --:--:-- --:--:-- --:--:--  1325
==> package() を開始...
==> インストールを整理...
  -> libtool ファイルを削除...
  -> 不要なファイルを削除...
  -> スタティックライブラリファイルを削除しています...
  -> バイナリとライブラリから不要なシンボルを削除...
  -> man と info ページを圧縮...
==> パッケージの問題をチェック...
==> パッケージを作成 "filezilla-bin"...
  -> .PKGINFO ファイルを生成...
  -> .BUILDINFO ファイルを生成...
  -> .MTREE ファイルを生成...
  -> パッケージの圧縮...
==> fakeroot 環境を終了。
==> 作成完了: filezilla-bin 3.49.1-1 (2020年08月14日 13時12分18秒)
```

パッケージの作成開始の前の段階でcurlでチェックサムが生成されています。
しっかりと「成功」と表示されて検証されているのがわかります。
Perl: クッキーの使い方

こちらと同じことを、Perl の CGI で行いました。
[jquery-cookie の使い方](https://qiita.com/ekzemplaro/items/95706b030581cd7a63c5)

クッキーを送る

```pl:cookie_put.pl
#! /usr/bin/perl
#
#	cookie_put.pl
#
use strict;
use warnings;
#
print "Set-Cookie: message='Good Morning by Perl';SameSite=None;Secure;\n";
print "Set-Cookie: aa='おはようございます。Perl';SameSite=None;Secure;\n";
print "Set-Cookie: bb=Test_bb by Perl;SameSite=None;Secure;\n";
print "Set-Cookie: cc=Test_cc by Perl;SameSite=None;Secure;\n";
print 'Content-Type: text/html',"\n";
print "\n";
print "\n";
print "<!DOCTYPE html>";
print "<html lang=\"ja\">";
print "<head>";
print "<title>cookie put</title>";
print "</head>";
print "<body>";
print "cookie_put.pl<p />";
print "Aug/14/2020<p/>";
print "</body>";
print "</html>";
```

クッキーを確認

```pl:cookie_get.pl
#! /usr/bin/perl
#
#	cookie_get.pl
#
use strict;
use warnings;
use CGI::Cookie;
 
my %cookies = fetch CGI::Cookie;

my $message = ""; 
my $aa = ""; 
my $bb = ""; 
my $cc = ""; 
if(exists $cookies{'message'}){ $message  = $cookies{'message'}->value; }
if(exists $cookies{'aa'}){ $aa  = $cookies{'aa'}->value; }
if(exists $cookies{'bb'}){ $bb  = $cookies{'bb'}->value; }
if(exists $cookies{'cc'}){ $cc  = $cookies{'cc'}->value; }
 
print "Content-type: text/html\n\n";
print "<!DOCTYPE html>";
print "<html lang=\"ja\">";
print "<head>";
print '<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" />';
print "<title>cookie get</title>";
print "</head>";
print "<body>";
print "message: " . $message . "<p />";
print "aa: " . $aa . "<p />";
print "bb: " . $bb . "<p />";
print "cc: " . $cc . "<p />";
print "cookie_get.pl<p />";
print "Aug/14/2020<p/>";
print "</body>";
print "</html>";
```

Firefox でのクッキーの確認の方法
![firefox_cookie.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/99dd19bf-bf79-6395-962c-b45a562ffe8e.png)
macOSのSafariでQiitaにインライン数式を記述すると同一行内に複数数式が存在した場合に勝手に改行される

##現象
実際にやってみると以下のようになる。

```md:入力文
同一行内に複数の数式があると$eq1$数式の開始点で$eq2$勝手に改行されてしまう
```
>同一行内に複数の数式があると
$eq1$数式の開始点で
$eq2$勝手に改行されてしまう

##検証
###検証1
数式を1つにする。

```md:入力文
数式がひとつなら$eq1$大丈夫っぽい
```

>数式がひとつなら$eq1$大丈夫っぽい

###検証2
行を分けてみる。

```md:入力文
続きの行に他の数式があると$eq1$どうも
やっぱり改行が$eq2$勝手に入ってしまう
```

>続きの行に他の数式があると
$eq1$どうも
やっぱり改行が
$eq2$勝手に入ってしまう

###検証3
空行を追加してみる。

```md:入力文
空の行をひとつ挟むと$eq1$これは

なぜか大丈夫に$eq2$なるっぽい
```

>空の行をひとつ挟むと$eq1$これは
>
なぜか大丈夫に$eq2$なるっぽい

###検証4
divタグで囲ってみる。

```md:入力文
<div>divタグで囲むと1行扱いになって$eq1$空行なしでも大丈夫。</div>
<div>でもタグ終わりに$eq2$改行が入ってしまう。</div>
```

><div>divタグで囲むと1行扱いになって$eq1$空行なしでも大丈夫。</div>
<div>でもタグ終わりに$eq2$改行が入ってしまう。</div>

ちなみに`style="display: inline;"`を指定してもタグ終わりで改行を防ぐことはできない。

###検証5
スタイル指定付きのdivタグで囲ってみる。

```md:入力文
<div style="display: inline;">スタイルは$eq1$効かないっぽい。</div>
<div style="display: inline;">inline指定でもタグ終わりに$eq2$改行が入ってしまう。</div>
```

><div style="display: inline;">スタイルは$eq1$効かないっぽい。</div>
<div style="display: inline;">inline指定でもタグ終わりに$eq2$改行が入ってしまう。</div>

[以前はスタイル指定が有効](https://qiita.com/javacommons/items/0c152442213198e2c0ce)だったようだが、今は効かないっぽい。

###検証6
spanタグで囲ってみる。

```md:入力文
<span>spanタグで囲むと連続行扱いになって$eq1$意味なし。</span>
<span>全く効果なく$eq2$改行が入ってしまう。</span>
```

>spanタグで囲むと連続行扱いになって
$eq1$意味なし。
全く効果なく
$eq2$改行が入ってしまう。

##解決策
<FONT COLOR=red>$\huge{\rm{Google \;Chrome}を使う。}$</FONT>

```md:入力文
同一行内に複数の数式があっても$eq1$数式で$eq2$勝手に改行されない。そう、Chromeならね。
```
>同一行内に複数の数式があっても$eq1$数式で$eq2$勝手に改行されない。そう、Chromeならね。

<br>

まじで時間かかったけど、Chrome使ったら一瞬で解決した。俺の時間返して。
<br>
<br>
<b>尾　　張　。</b>
Google colaboratoryを使うまで



# とにかくpythonの実行環境が欲しい！

はじめまして。Qiitaを始めてみたのでブログを書く練習も兼ねて，ちょっとしたディープラーニングに使っているGoogle Colaboratoryを使えるようになるまでをまとめてみたいと思います！
対象者
・文系でプログラミングを始める人　・ディープラーニングを始めたい人，無料GPU環境使いたい人
## 背景
人工知能(AI)ブームでpythonを使う人，使おうとしてる人，が増えていると思います。その中にはこれまでまったくプログラミングを扱ったことがない人もいると思います。そんな人たちにとって，最初の関門が実行環境の構築だとおもいます。pythonを扱うのに比較的分かり易いものとしてAnacondaをインストールしてjupyternotebookを.....　なんかもありますが，非情報系の私にはとても難しくてこれだけで何日もかかってしまいました笑　こんなことにならないためにまずはGoogle colaboratoryをおすすめします。

## １．Googleドライブにログイン
Google colaboratory(以下colab)は名前の通り，Googleが提供してくれているサービスで，クラウド上で動作するjupyternotebook環境です....よく分からなければとにかくpythonを実行できるんだな~と思ってください！

colabはpythonプログラムをGoogleドライブ上で実行します。そのため，まずはGoogleドライブにログインしてください！

## ２．Colaboratoryのインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485281/0913626b-b3ce-900f-7397-b1cc9597bd74.png)

こんな感じの画面になったら...
画面の真ん中あたりで右クリック！

![colab1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485281/7b0b64ab-5b86-2271-0982-e52fe6bbdc16.png)

赤枠で囲った部分が出てきたら.....

![colab2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485281/759ed377-3beb-3a6f-808f-fcb5f18dbefa.png)

その他→アプリを追加をクリック！
するとこんなのが出てくると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485281/ab99fb43-62f7-b708-5f1f-3d36d2eca809.png)

ここで「apps内を検索」に「colab」と入力して検索...
![colab3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485281/a08881d6-9e23-59a4-aa2a-868ddcc9e9e9.png)

Colaboratoryをクリック...

![colab4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485281/3876e61b-cf4a-8cf6-f530-f14953e59c50.png)

インストールをクリック....
いろいろ許可を求められるので言われる通りクリックしていくと...

![colab5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485281/a42024f4-7d61-e14a-094e-8e34b41113ea.png)

インストール完了！
これでpythonの実行環境が完成しました！

## ３．実際にpythonプログラムを書く
それでは実際にpythonプログラムを書いてみましょう！

![colab6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485281/12a4598d-1a25-8435-6d4d-f7a63d565369.png)
ドライブ上で右クリック→その他→Google Colaboratoryをクリック....

![colab7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485281/30a95036-bba2-15f1-6ad6-cc883599b11f.png)
Untitled0となっているところを自分の好きな名前に変えましょう！

![colab8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485281/ed3df90f-e19a-077b-3a25-d6b34fed98fd.png)

`print("Hello Colab")`と入力....



矢印ボタンをクリックかCtrl+Enterキーを入力して実行....
![colab9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485281/79d88fdf-2250-4de0-10fb-b34f65895dcb.png)

`Hello Colab！`と出力されれば，実行成功です！
こんな感じでpythonプログラムを実行出来ちゃいます！


以上，お疲れさまでした！
LitElementでピュアJavaScriptオブジェクトをモデルとして使う例

```html
<script type="module">

import { LitElement, html, css } from "https://unpkg.com/lit-element?module"

const createProxy = (target, handler) => new Proxy(target, (function make(handler) {
  return {
    get(target, key) {
      if (typeof target[key] === 'object' && target[key] !== null) {
        return new Proxy(target[key], make(handler));
      } else {
        return target[key];
      }
    },
    set(target, key, value) {
      target[key] = value;      
      handler(target, key, value);
      return true;
    }
  };
})(handler));

class Model {
  constructor() {
    this.count = 0
  }
  increment() {
    this.count += 1
  }
}

class ModelElement extends LitElement {
  constructor() {
    super()
    this.model = createProxy(new Model(), ()=>this.requestUpdate())
  }
}

class ViewElement extends ModelElement {
  static get properties() {
    return {
      //model: { type: Object, noAccessor: true },
      count: { type: Number },
    }
  }
  get count() {
    return this.model.count
  }
  set count(newVal) {
    this.model.count = newVal
  }
  static get styles() {
    return css`
      button {
        font-size: 10em;
      }
    `
  }
  render() {
    return html`
      <button @click="${e=>this.model.increment()}">
        ${this.model.count}
      </button>
    `
  }
}

customElements.define("counter-element", ViewElement)

</script>

<counter-element count="10"></counter-element>
```
GCL(GnuCommonLisp)のCUIコンパイルand実行環境設定メモ

この記事ではFedora 30(64bit環境)にインストールした
GCL (GNU Common Lisp)  2.6.12を使っています。


GCLのインストールは

#dnf install gcl

です。

私の環境ではそれだけだと
GCLを起動できなかったので
エラーメッセージを読み

#dnf install redhat-rpm-config

で追加インストールをすることで正常に動作させることができました。

さてGCLをインストールすると
CUIで

$gcl

と入力することでインタプリタが起動します。

インタプリタ上での操作はネットや書籍に沢山あるので検索してください。

それではコマンドライン上でのコンパイル方法をメモしていきます。

まず以下のようなソースコードを用意します。
LISPの拡張子は .l や .lsp がメジャーなようですが、
geanyでは.lispの拡張子の時のみシンタックスハイライトが適用されるようです。
ですのでこの記事では .lispを使います。

![Screenshot from 2020-08-14 12-24-53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691859/4e0d2ba5-3672-aeb9-7223-4c5c7dec68ed.png)


コマンドライン上で

$gcl -compile Hello.lisp

で
Hello.o
オブジェクトファイルが出力されます。

あとは

gcl -load Hello.o

でGCLにオブジェクトファイルを読み込ませて実行できます。

さて、コマンドライン引数でコンパイルできると何が嬉しいかというと
プログラミング用のエディタにショートカットを設定できることです。

geanyではこんな感じになりました。
各自他にお好みの統合開発環境があれば読み替えて適用してください。

![Screenshot from 2020-08-14 12-37-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691859/52ed8dbf-0db5-ddf4-e437-2875d5da5e57.png)

これで
F8キーでコンパイル
F5キーで実行

という統合開発環境らしいプログラミング環境が設定できるかと思います。


コンパイル→実行した様子。


![Screenshot from 2020-08-14 12-46-30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691859/627c2082-a885-254c-285a-c5bedd0fb1d9.png)



めでたしめでたし。


主に参考にした文献

https://www.systutorials.com/docs/linux/man/1-gcl/

Common Lispを触る（CLISP） - 気が向いたら書くやつ https://soratobi96.hatenablog.com/entry/20190504/1556981919
IndexError: index -1 is out of bounds for axis 0 with size 0を解決

今回質問をし教えて頂いたので備忘録と共有をします。

```python
IndexError: index -1 is out of bounds for axis 0 with size 0
```

##経緯
東京都の昼間の人口予測のデータから過去から未来にかけての密集地の予測をするため、seabornのpairplotを行おうとした所、Keyエラーが発生。その後Keyエラーについて解消はしたものの。上記のエラーが。。。。

locやインデックス値の指定によってデータの表示をしようとしたのですがうまくいかず。


##内容

```python

import csv
import pandas as pd
import seaborn as sns
import matplotlib 
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import japanize_matplotlib

road = pd.read_csv("~~~~.csv",
                   encoding="SHIFT-JIS",
                   keep_default_na=False, # 空欄をNaで置き換えない
                   header=None, # headerは指定しない
                   index_col=[0],
                   engine='python')

road.columns = pd.MultiIndex.from_frame(road.iloc[:11, :].T)
print(road)

dro = road.dropna(how="all")
new = dro.loc[:,["年次（西暦）","地域階層コード","（常住地）東京都"]]
print(new)
sns.pairplot(dro)
plt.savefig("population.png")
plt.show()
```

##解決方法

```python

df = pd.read_csv('/Users/uematsuyuuki/Desktop/ty20rv0800 (1).csv',
                 encoding='shift-jis', 
                 skiprows=11, 
                 usecols=[1,2,6])
```
read_csvのパラメーターの指定をすることで解決。

#なぜか？！
###データの中身に問題があった模様。
引数を指定したことによって特定の行をスキップしたことによって解決。
>引数skiprows
特定の行をスキップ（除外）して読み込む場合、引数skiprowsを使う。
skiprowsに整数を渡すと、ファイルの先頭をその行数分スキップして読み込む。



![population.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654850/9066f4c1-4f93-a2aa-05a3-987c518b5896.png)