OmniAICreator/Qiita-1.07M huggingface dataset:
Python初学者の自分が知らなかったこと

# はじめに
[PythonでCSVのIPアドレスリストを取り込み国名を付与する](https://qiita.com/uranux_jp/items/2ef82e19ad7c69b65562) をアップしたところ [しらかみゅ(shiracamus)](https://qiita.com/shiracamus) さんがコメントで自分が作ったスクリプトを分かりやすく関数化してくれました。これをみて自分が分からなかったところをまとめました。


# Python初学者の自分が知らなかったこと


## main関数

main関数を定義して `if __name__ == "__main__":` という形で条件分岐すると、スクリプトを関数を参照するためにインポートした際にmain関数が実行されないようになります。

```python:
def main:
    #ここにメイン関数を定義

if __name__ == "__main__":
    main()
```

- 参考サイト　[Pythonのif \_\_name\_\_ == "\_\_main\_\_" とは何ですか？への回答](https://blog.pyq.jp/entry/Python_kaiketsu_180207)


## イテレータ、ジェネレータ（yield）
CSVファイルの読み出しやデータの操作にジェネレータ（yield）を用いています。yield を使うと巨大な CSV ファイルのような大きなデータでも少しずつ読み込むことでメモリを節約できます。手持ちの本を読んでも詳しく載っていないので実際に使いながら覚えていかないといけないのかなと思います。

```python:
# CSVファイルの読み出し
def load_csv(filename, encoding="ascii"):
    with open(filename, encoding=encoding) as input_file:
        # return list(csv.reader(input_file))
        yield from csv.reader(input_file)

# 読みだしたデータをもとに関数 country_name を実行する
def add_country_name(csv):
    for date, ipaddress in csv:
        yield [date, ipaddress, country_name(ipaddress)]
``` 

- 参考サイト　[python の yield。サクッと理解するには return と比較](http://ailaby.com/yield/)

## 複数行コメントアウト

```python
""" 
Pythonで複数行コメントアウトするときは
ダブルクオーテーションまたはシングルクォーテーション3つつなげた
トリプルクオートで囲む。
"""
# 1行だけ、行の途中からコメントアウトするときはシャープを使用する。
```
- 参考サイト　[Pythonのコメント、コメントアウトの書き方](https://note.nkmk.me/python-comment/)




# 参考サイト
[Pythonのif \_\_name\_\_ == "\_\_main\_\_" とは何ですか？への回答](https://blog.pyq.jp/entry/Python_kaiketsu_180207)
[python の yield。サクッと理解するには return と比較](http://ailaby.com/yield/)
[Pythonのコメント、コメントアウトの書き方](https://note.nkmk.me/python-comment/)
google_maps_flutterでMapにマーカーが立たない

鹿児島で大学院に通っております、Flutter初心者です。
はじめてのqiitaの投稿なので間違っていたり、その他まずい部分があったりした場合はコメントしていただけると助かります。
今回GoogleMapのAPIを以下の記事を参考にしていた際に詰まった点についてまとめました。
[Google公式Flutter用Google Mapsプラグインを一通り使ってみた](https://qiita.com/aoinakanishi/items/25f2526fc7c1fe8350c6)

#詰まったところ
地図上にマーカーを表示させる際に

```

The method 'MarkerOptions' isn't defined for the class '_GmapState'.
Try correcting the name to the name of an existing method, or defining a method named 'MarkerOptions'.d

The method 'addMarker' isn't defined for the class 'GoogleMapController'.
Try correcting the name to the name of an existing method, or defining a method named 'addMarker'.

```
というエラーメッセージが、

#原因
dependencyにgoogle_maps_flutterを追加する際に

```
dev_dependencies:
  google_maps_flutter: ^0.5.10
```
「とりあえず新しいの入れとけ！」ってしたのが間違いでした、、、
[google_maps_flutter公式サイト](https://pub.dartlang.org/packages/google_maps_flutter)を見てみると、なるほどgoogle_maps_flutterの新しい方のバージョンにMarkerOptionsがないのか、、、

#解決方法
```
    setState(() {
      mapController = controller;
      Marker marker = Marker(
        markerId: MarkerId(''),
        position: LatLng(31.568945, 130.545083),//マーカーを立てる緯度経度
      );
      markers.add(marker);
    });
```
新しくMarkerというClassがありましたのでそれを使うらしいです。
markerIdはないと

```
The parameter 'markerId' is required.
```

とメッセージが出たので適当に仮置きしてます。

#結果
<img width="391" alt="スクリーンショット 2019-05-05 16.34.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317162/525e601a-8bf1-1c54-04ec-97d124bcf7cc.png">
無事にマーカーが立ちました〜

#参考
[Google公式Flutter用Google Mapsプラグインを一通り使ってみた](https://qiita.com/aoinakanishi/items/25f2526fc7c1fe8350c6)
[google_maps_flutter公式サイト](https://pub.dartlang.org/packages/google_maps_flutter)
[Python]テキスト処理備忘録



#コマンドライン引数

+ Pythonのプログラム実行時に，引数を渡すことができる
+ sysモジュールのargvを利用する
+ 入力値は文字列型として扱われる
+ try-exceptは例外処理(ここで考えられる例外は引数が第3引数より少なかった場合の挙動)

```python
import sys
args = sys.argv

try:
	print(args)
	print("第1引数：" + args[1])
	print("第2引数：" + args[2])
	print("第3引数：" + args[3])
except IndexError:
	print("IndexError: list index out of range")
```


#ファイルの読込み

+ `UnicodeDecodeError: 'cp932' codec can't decode byte 0xef in position 0: illegal multibyte sequence`対策のためUTF-8でファイルをオープンする
+ 引数modeのデフォルト値は'r'なので、省略してもOK

```python
# ファイルをUTF-8でオープンする(,encoding="utf-8")
f = open("test_data.txt", "r",encoding="utf-8")

# 一行ずつ表示する
for line in f:
	print(line)

# ファイルをクローズする
f.close()
```


#ファイルの中身を配列に格納

+ rstripは任意の文字列を右から削除してくれる


```py
# 配列の初期化
Array = []

f = open("list_data.txt", "r",encoding="utf-8")

# 一行ずつ表示する
for line in f:
    Array.append(line.rstrip('\n'))

# ファイルをクローズする
f.close()

print(Array)
```
CeleryをDjangoで動かす

# やったこと
Django・Celeryで非同期ジョブ実行の仕組みを実装した

## 背景
Django上でseleniumを使ってSBI証券の売買注文をする機能を実装したので、それをSlackからinteractiveコマンドを利用して実行させたくなった。

しかしslackのinteractiveコマンドでは3秒以内にレスポンスを返さないとエラーとなる仕様のため、時間がかかる作業はレスポンスだけ返して非同期で実行する必要があった。

そこでceleryを利用して、djangoで非同期ジョブを実行できるようにした。

# 環境
ubuntu 16.04
Python 3.5.2
Django 1.11.7


# 導入手順
## 1. redis導入
celeryでメッセージブローカとして利用するredisをサーバにインストールする

下記URLに従って実行
https://weblabo.oscasierra.net/redis-ubuntu1604-install-apt/

立ち上げも忘れずに

```sh
sudo service redis-server start
sudo systemctl enable redis-server
```

## 2. celery導入
pipでインストールする


```sh
pip install celery django-celery-results redis django-redis
```

一緒にインストールしたdjango-celery-resultsで非同期ジョブの実行結果をDBに保存できる

### settings.py
下記の設定を追記する

```py:settings.py
# CELERY
CELERY_BROKER_URL = "redis://127.0.0.1:6379/1"
CELERY_RESULT_BACKEND = "django-db"
```

### celery.py
settings.pyと同じ階層に新規作成する
`environ`を用いて設定ファイルを使い分けているので、celery.pyでも同じように設定ファイルを読み込む


```py:celery.py
import os
from celery import Celery
import environ
env = environ.Env(DEBUG=(bool, False),)  # set default values and casting
environ.Env.read_env('.env')  # reading .env file

# set the default Django settings module for the 'celery' program.
settings = os.getenv(
   "DJANGO_SETTINGS_MODULE", env("CELERY_ENVIRONMENT"))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", settings)

app = Celery('プロジェクト名')

# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
#   should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')

# Load task modules from all registere
```

### ジョブ定義
関数にデコレータ`@app.task()`をつけると、ジョブとして実行できる。
seleniumでのSBI注文の実装は省略する。
下記のようにジョブ定義と実行のファイルを用意すれば良い

```python:job.py
from プロジェクト名.celery import app

@app.task()
def add_numbers(a, b):
    return a+b
```


```python:execute.py
from xxx.job import add_numbers

def execute()
    add_numbers.delay(10, 3) 
```

## 3. celery実行
サービスとして起動しておく

下記のサービスファイルを作成

```:/etc/systemd/system/celery.service
[Unit]
Description=celery daemon
After=network.target

[Service]
User=furuya
Group=furuya
WorkingDirectory=[DjangoプロジェクトのPATH]
ExecStart=/home/furuya/.local/bin/celery -A プロジェクト名 worker --concurrency=1

[Install]
WantedBy=multi-user.target
```


下記を実行

```sh
sudo systemctl daemon-reload
sudo service celery start
sudo systemctl enable celery
```

celeryが動いていれば、非同期ジョブは順次実行されていく

## 4. 実行結果の確認
DjangoのAdmin画面で、実行結果を確認できる

<img width="1377" alt="スクリーンショット 2019-05-05 16.07.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199902/bcbc5d58-6fe4-a2fd-7cdc-1c07be3e62af.png">

各レコードへのリンク先で、パラメータ等の詳細も確認可能
Moodleで課題一括ダウンロード時のフォルダ名にユーザ名を入れる

Moodleで課題の一括ダウンロードをする際，フォルダ名に，学生の名前は入るが，ユーザ名が入っていない．ユーザ名を学籍番号にしているので，ユーザ名が入ってくれるとフォルダが学籍番号順になってくれて嬉しいので，入れることにした．．ついでに，(学生ごとの)フォルダ名に assignsubmission という長い文字列が入って邪魔なので as と短縮する．
mod/locallib.php を修正する．

```php
--- locallib.php-orig   2019-05-05 15:36:20.724294366 +0900
+++ locallib.php        2019-05-05 15:53:59.152414973 +0900
@@ -3408,7 +3408,7 @@
                     $prefix = clean_filename($prefix . '_' . $this->get_uniqueid_for_user($userid));
                 } else {
                     $prefix = str_replace('_', ' ', $groupname . fullname($student));
-                    $prefix = clean_filename($prefix . '_' . $this->get_uniqueid_for_user($userid));
+                    $prefix = $student->username . '_' . $prefix;
                 }

                 if ($submission) {
@@ -3422,6 +3422,7 @@
                                 $pluginfiles = $plugin->get_files($submission, $student);
                                 foreach ($pluginfiles as $zipfilepath => $file) {
                                     $subtype = $plugin->get_subtype();
+                                    if (strcmp($subtype, "assignsubmission") == 0) { $subtype = "as"; }
                                     $type = $plugin->get_type();
                                     $zipfilename = basename($zipfilepath);
                                     $prefixedfilename = clean_filename($prefix .
@@ -3447,6 +3448,7 @@
                                 $pluginfiles = $plugin->get_files($submission, $student);
                                 foreach ($pluginfiles as $zipfilename => $file) {
                                     $subtype = $plugin->get_subtype();
+                                    if (strcmp($subtype, "assignsubmission") == 0) { $subtype = "as"; }
                                     $type = $plugin->get_type();
                                     $prefixedfilename = clean_filename($prefix .
                                                                        '_' .
```

上のpatchは，Moodle 3.6用である．私のところでは動作しているけれど，言うまでもなく無保証なので，ソースを読んでこれで良いと信じられる場合のみお使いください．
Cloud Storageの画像をリサイズして再アップロードする

# やりたいこと
Google Cloud Storage（GCS）に保存した画像ファイルを、リサイズして、別ファイルとしてGCSに再アップロードしたい。

# 困った点
どうやったらPILのImageをCloudStorageにアップロードできる形にできるのか。。。
GAEではローカルファイルシステムに書き込みできないので、ファイルを一時保存して読み込む実装は不可。

# 解決策
[こちらのサイト](https://serversmanvps.xn--ockc3f5a.com/2018/11/07/gcpgae-python%E5%88%A9%E7%94%A8%E6%99%82%E3%81%AB%E4%B8%80%E6%99%82%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E4%BB%A3%E3%82%8F%E3%82%8A-bytesio/)を参考にした。
ファイルオブジェクトでアップロードする方法だと、`ValueError: Stream must be at beginning.`が発生してうまく行かなかった。
そのため、stringからアップロードして、JPEGで保存できるように実装した。

```python
import io
from google.cloud import storage
from google.cloud.storage import Blob
from PIL import Image


# GCSから写真データを取得
client_storage = storage.Client()
bucket = client_storage.get_bucket('Bucket name')
target = bucket.get_blob('target_name')

# bytes形式で読み込み
img = Image.open(io.BytesIO(target.download_as_string()))

# resize処理
width_rev = 1200
height_rev = img.height * width_rev / img.width
img_resize = img.resize((int(width_rev), int(height_rev)))

# メモリでデータを保持する
bio = io.BytesIO()
img_resize.save(bio, format='jpeg')

# リサイズされた画像をGCSへアップロード
blob = Blob("file_name", bucket)
blob.upload_from_string(data=bio.getvalue(), content_type="image/jpeg")
```
Windows 上の仮想環境の kali linux で wifi アダプターをモニターモードにする

# wifi アダプターの準備

kali linux がサポートする wifi アダプター のチップセットは以下のものになります。

- Atheros AR9271
- Ralink RT3070
- Ralink RT3572
- Ralink RT5572
- Realtek 8187L
- Realtek RTL8812AU
- Ralink RT5370N

参考: [Buy the Best Wireless Network Adapter for Wi-Fi Hacking in 2019](https://null-byte.wonderhowto.com/how-to/buy-best-wireless-network-adapter-for-wi-fi-hacking-2019-0178550/)
参考: [Best Kali Linux Compatible USB Adapter / Dongles](https://www.wirelesshack.org/best-kali-linux-compatible-usb-adapter-dongles.html)

まずこれらを搭載した wifi アダプターを購入しましょう

私は Ralink RT3070 搭載の Alfa 社 [AWUS036NEH](https://www.amazon.co.jp/dp/B0035OCVO6/ref=cm_sw_r_tw_dp_U_x_LGNZCbKNYASJV) を使いました。

これらのチップセットのうち 5GHz 対応なのは、RT3572, RT5572, RTL8812AU のみです。
私が購入したのも RT3070 なので、 5GHz には非対応です。
5GHz も受信したい場合は注意しましょう。

ホストとなる Windows PC に接続し、アダプタに付属あるいは公式サイトからドライバをインストールしましょう。
Windows から認識されているか確認しておきましょう

# kali linux のインストール

通常のインストーラを実行しても良いですが、VMware と Virtual Box 用にイメージファイルが公開されているのでそれを使うのが楽です。
[Kali Linux Downloads – Virtual Images](https://www.offensive-security.com/kali-linux-vm-vmware-virtualbox-image-download/)
（´-`）.｡oO（昔は Hyper-V 向けにもあったのに無くなってしまった…）
VMware Tools や VirtualBox Guest Additions もインストール済みのはずです。

# kali linux に wifi アダプターを認識させる

## VMware Workstation Player の場合

Player > 取外し可能デバイス > ネットワークアダプタ > [対象のアダプタ] > 接続(ホストから切断) を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100313/61a009f1-bb18-08c6-4865-b0af95e37ec7.png)

## VirtualBox の場合

デバイス > USB > [対象のアダプタ] にチェックを入れます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100313/e2fc10a1-a6a6-e3a5-3d0b-6094c763d66d.png)

## 確認
`iwconfig` コマンドを実行して対象のアダプタが表示されていればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100313/b914a6ed-c2d1-1e30-1f22-88e0b14548e0.png)

# モニターモードに変更する

先の画像では `Mode:Managed` となっていました。これをモニターモードに変更します。

アダプタのモデルやチップセットによって変更の方法が違うようで

```shell
> airmon-ng check kill
> airmon-ng start <interface>
```

```shell
iwconfig wlan0 mode monitor
```

のいずれかのようです。

参考: [暗号通貨 とセキュリティ - Wifiアダプターをモニターモードにする](https://medium.com/ethical-hacking-%E3%83%9B%E3%83%AF%E3%82%A4%E3%83%88%E3%83%8F%E3%83%83%E3%82%AB%E3%83%BC/wifi%E3%82%A2%E3%83%80%E3%83%97%E3%82%BF%E3%83%BC%E3%82%92%E3%83%A2%E3%83%8B%E3%82%BF%E3%83%BC%E3%83%A2%E3%83%BC%E3%83%89%E3%81%AB%E3%81%99%E3%82%8B-%E6%9C%80%E9%87%8D%E8%A6%81%E3%82%B9%E3%82%AD%E3%83%AB-5ee7a57e5165)

私(AWUS036NEH)の場合後者のやり方で出来ました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100313/07d3ce2c-1f5f-8817-7527-9049342d513b.png)
【Rails】 id（並び順整数）をuuid（乱数）に変更

ユーザーidなどのIDが順番に取得されているので、
例えば下記のルートのように、 https://hogu.com/user/5 とか適当に手入力するとページ上からアクセスしなくても画面遷移してしまう。

| Path / Url |  HTTP  | Path | Controller#Action |
|:-----------------|--------------:|:------------------:|:------------------:|
| user_path | GET |/users/:id| users#show |

他のテーブルも同様で、例えばコメントの数や出品数など、どのくらいの数が登録されている等も推測できてしまい、個人的にも気持ち悪さがあったので乱数でidを登録する方法を調べながら行ったのでメモ。

``` マイグレーションファイル.
class CreateUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :users, id: false do |t|
      t.string :id, limit: 36, null: false, primary_key: true
      t.string :name, null: false
      t.binary :avater
      t.timestamps
    end
  end
end
```
今回idに入れたい乱数はUUIDになる。
既存のidのカラム型はintegerで格納できる文字数が少ないためstring型にする必要がある。
そのためcreate_table :users, id: false とした後に
t.string :id, limit: 36でカラム型を変えたidカラムを生成。

下記はモデルに使いたいUUID生成用のメソッド。
SecureRandom.uuidはrailsに既存であるメソッドになる。
rails cで確認すると下記のような結果になる。

```
[1] pry(main)> SecureRandom.uuid
=> "3f5ba6ef-ada9-43c8-b11c-b7d8f27c8d1f"
```

```models/concerns/id_generator.rb
module IdGenerator

  def self.included(uuid)
    uuid.before_create :generate_uuid
  end

  def generate_uuid
    self.id = loop do
      uuid = SecureRandom.uuid
      break uuid unless self.class.exists?(id: uuid)
    end
  end

end
```

モデルには上記のメソッドを使えるようにするためinclude IdGeneratorと記述。
私の場合は他のテーブルでもUUIDの乱数を生成したかったため、メソッドを切り分けしinclude IdGeneratorと記述するだけで他のモデル下でも使用できるようにした。
仮にUserモデルのみの場合はuser.rbに直接メソッドを記述してもOK。

```modelus/user.rb
class User < ApplicationRecord
  include IdGenerator

　（以下省略）

end
```

ここまで準備ができたら
rails db:drop、　rails db:create、　rails db:migrateを行う。
（私は始めからやり直しましたがdbを消さなくてもマイグレーションファイルのカラム型変更でもOK）

ユーザーは下記のようにidに乱数が入っている。

```
pry(main)> @user=User.all
 #<User id: "ae6cdc44-68cd-4c76-b972-26d8a39b4bbb", name: "ユーザー１", avater: "8fe81aa7-9dbd-401d-b83c-86afe728aecd.png", created_at: "2019-05-05 03:40:36", updated_at: "2019-05-05 03:40:36", email: "a@test.com">,
 #<User id: "d8d39f5e-ef4b-407b-ba23-8e4bbb83da12", name: "ユーザー２", avater: "90024ca8-f2ef-4796-ac19-e2e7adf5a2e3.png", created_at: "2019-05-05 03:40:36", updated_at: "2019-05-05 03:40:36", email: "b@test.com">,
```

上記のURLが無事下記のように推測不能なURLとなった。

```URL.
http://localhost:3000/user/1

⬇︎
http://localhost:3000/user/ae6cdc44-68cd-4c76-b972-26d8a39b4bbb
```
UbuntuでKali Linux(GUI)コンテナを利用する

Dockerコンテナを利用して、Ubuntu18.04でKali Linuxを使えるようにしました。
普通にKali LinuxのDockerイメージを利用してもいいですが、私はGUIで操作したかったので、あらかじめVNCがインストールされたDockerイメージを利用しました。
ホストであるUbuntu18.04には、DockerもVNCクライアントも導入していないので、それらのインストール方法も書いています。

###参考
基本的にこちらの記事を参考にさせていただきました。

- [Docker + Kali LinuxでCTF環境を整える](http://www.no1497.com/?p=598)



###大まかな手順
1. DockerでVNCサーバ入りKali Linuxのコンテナを作成する
2. そのKali LinuxでVNCサーバを起動する
3. UbuntuでVNCクライアントを起動して、Kali LinuxをGUIで操作する


###Dockerの導入

こちらの記事を参考にさせていただきました。

- [Ubuntu 18.04にDockerをインストールする](https://qiita.com/myyasuda/items/cb8e076f4dba5c41afbc)
- [Ubuntu16.04にDocker CEをインストール](https://qiita.com/uutarou10/items/f9483aad5153957fc6dc)

以下のコマンドを、順に入力していきます。

```
$ sudo apt-get update
$ sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
```
Dockerのインストール方法を調べていると『Docker-CE』という単語を目にしました。
『Docker-CE』とは、無償版のDockerのことだそうです。


###Dockerイメージ取得

イメージ取得は以下のコマンドで行います。

```
$ wget https://github.com/rringler/kali-vnc/archive/master.zip
$ unzip master.zip
$ cd kali-vnc-master
$ docker build -t kali:latest .
```
取得したイメージは、以下のコマンドで確認できます。

```
$ sudo docker images
```
sudoなしでdockerコマンドを実行できる方法があるそうですが、私は~~面倒で~~やっていません。

###Dockerでコンテナ作成
以下のコマンドでコンテナを作成します。

```
$ sudo docker run -it --name kali -p 6080:6080 -p 5091:5091 kali:latest
```

コンテナを作成すると、Kali Linuxのプロンプトに移ります。
まず、後ほど利用するので、コンテナのIPアドレスを調べてください。

```:Kali&nbsp;Linux
$ hostname -i
```
###VNCサーバの立ち上げ


以下のコマンドでVNCサーバを起動できます。
コマンドを実行するとパスワードを設定するか聞かれるので、設定してください。

```bash:Kali&nbsp;Linux
$ vncserver :1
```


###Remminaのインストール

Ubuntuで利用できるVNCクライアントアプリとして、『Remmina』を利用しました。
以下のコマンドでインストールできます。

```
$ sudo apt-get install remmina　# インストール
$ remmina  # 起動
```
起動するとキーリングパスワードを聞かれますが、私は無視しています(いいのかな...？)。

###VNC接続

VNCサーバの設定は以下のように行います。

1. 左上の「+」マークをクリック
2. プロトコルに「VNC仮想化」を指定
3. サーバー名に「(コンテナのIPアドレス):5901」と指定する
4. ユーザ名に「root」を指定

以上を設定できたら、接続をクリックします。
パスワードは先ほど設定したものを入力してください。


###最後に
Dockerを使う練習をかねて行ったので、方法が間違っていたらすみません…。
これからKali Linuxを使ってCTFの勉強を頑張ります！
tagヘルパーについて

例えば、ヘルパーモジュールにhtmltタグを戻り値とするメソッドを作成したかったことがあったため、
その時にrailsのtagヘルパーを使ったので、シェアします。

#前提
Rails：5.1.4
ruby：ruby 2.6.0p0

#使い方
tag.（タグ名） "タグ内のテキスト" [, 追加したい属性]　※スペースなど注意必要
こちらを参照：[Ruby on Rails API](https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html)

#例
```ruby
tag.a "hoge", class: "test" , type: "button", data: {toggle: "modal", target: "#1"}
```
と記載すると、返されるhtmlタグは、下記のようになる。

```html
<a class="test" type="button" data-toggle="modal" data-target="#1">hoge</a>
```

**data属性の書き方がポイントです！**
gcpのSDK gcloudコマンド事始め（in Docker）

gcloudコマンドで特定のプロジェクトに対しての操作するときの事始め。
毎度の操作で必要になるのでまとめる。

Docker経由で利用することを想定してるので、ホスト機で直に使う際とちょっとやり方が違うかもしれないのでご注意を。

質問・訂正・改善・苦情・ご意見あれば、コメントにてよろしくお願いします。

## gcloudコマンドで対象のプロジェクトに対して何かする前に必要なこと

以下の二つ

* アカウント認証
* 対象プロジェクトセット

プラス、操作によっては

* APIの有効化

が必要。

あ、プロジェクト自体はすでに作られている前提で。

## gcloudコマンド用意

Docker利用時は、こちらからどうぞ。

* [Dockerでgcloudコマンド使う](https://qiita.com/ideodora/items/28cd01aa587ce4e9df7f)

ホスト機に直でインストールする場合は下記を参考に。

* [公式: Cloud SDK のインストール](https://cloud.google.com/sdk/downloads)

## アカウント認証

Cliでgcloudコマンドを使って認証を通します。

```
gcloud auth login

=>Go to the following link in your browser:

    https://accounts.google.com/o/oauth2/auth?redirect_uri=...

Enter verification code: 
```

**Go to the following link in your browser:** とあるので、下部に記載されてるURLにブラウザでアクセス。

ログインを求められるので、有効なgoogleアカウントでログインして…

<img width="250" alt="スクリーンショット_2019-05-05_15_07_35.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37209/85d5bec9-f7ca-39c1-3734-af632eccc568.jpeg">

許可して…

<img width="241" alt="スクリーンショット_2019-05-05_15_07_44.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37209/f975c3bb-f821-028e-6326-ed916a2bcef5.jpeg">

こんな感じでトークンが吐き出されるので、コピー。

先の

```
Enter verification code: 4/QQH98erq7Da5h093ZVUrNrwlQq6RnLxxxxxxxxxxxxxx
```

にコピーしたトークンを貼り付けてエンター

```
=> WARNING: `gcloud auth login` no longer writes application default credentials.
If you need to use ADC, see:
  gcloud auth application-default --help

You are now logged in as [xxxx@gmail.com].
Your current project is [some-project].  You can change this setting by running:
  $ gcloud config set project PROJECT_ID
```

以降、認証したユーザーでのgcloudコマンドが実行できるようになる。

## 対象プロジェクトセット

アカウント認証した際の出力最下部に記載あるように
（直近のプロジェクトがセットされている状態？）

```
You are now logged in as [xxxx@gmail.com].
Your current project is [some-project].  You can change this setting by running:
  $ gcloud config set project PROJECT_ID
```

変更したい場合は、下記の通りにすることで変更ができる。

```
gcloud config set project other_project
```

現在の、認証状態や対象プロジェクト、その他諸々コンフィグを覗き見るには、

```
gcloud config list

=> [core]
account = xxxx@gmail.com
disable_usage_reporting = True
project = other-project

Your active configuration is: [default]
```

などとして確認できる。

## APIの有効化

以上で、対象プロジェクトに対して **gcloud** で色々できるようになるのですが、
コマンドによっては、プロジェクトで **APIを有効化** しておかないと使えなかったりするので、
適宜有効化して利用します（これが結構わかりにくい…）

自分は、GCPのConsole上でポチポチ選んで有効化してます。

公式ドキュメントでAPIが一覧に網羅されてますが、実際どれ使うねん。てのがいまいちわかりにくい。。。

ので、gcloudを利用する際必要になるAPIは利用する度にどのAPIを使う必要があるか備忘をつけておくと、後々困らないかと思います。

まぁ、変更も多いので昔使えてたAPIがアレに変わった、なくなった等もよくあるんですが。。。

## 複数の構成設定について

[公式: 複数の構成](https://cloud.google.com/sdk/docs/configurations#multiple_configurations)にある通り、複数の設定をして、利用することができるみたいですが、こちらDockerコンテナ内でプロジェクト毎に運用してるのであまり利用したことはありません。

どなたかうまいやり方があればご教授いただけたらなと思います。
.htaccessをnginx confに変換したい

nginxを使っていると、htaccessしか情報のないツールを使うときに差支えが出ることがあります。

https://timmehosting.de/htaccess-converter

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245977/9de5ee57-26a8-57cf-f684-0f0e4bf4eb68.png)

簡単に置き換えられる。
Paginate導入時のエラー　wrong number of arguments (given 0, expected 1)

初心者がRails tutorial第10章でPaginate導入後にぶつかったエラーについてお話します。

gemfileに以下のように入力。rails bundleでインストール。

```
source 'https://rubygems.org'
.
.
gem 'will_paginate',           '3.1.6'
gem 'bootstrap-will_paginate', '1.0.0'
.
.
```


その後、以下のようにindexファイルを作成、記述しました。

```
app/view/users/index.html.erb

<% provide(:title, 'All users') %>
<h1>All users</h1>

<%= will_paginate %>

<ul class="users">
  <% @users.each do |user| %>
    <li>
      <%= gravatar_for user, size: 50 %>
      <%= link_to user.name, user %>
    </li>
  <% end %>
</ul>

<%= will_paginate %>
```

記載後、tutorialの指示通りテストをすると、以下のように引数不足というエラーが出現。

```
ERROR["test_index_as_non-admin", #<Minitest::Reporters::Suite:0x000055a04b425c20 @name="UsersIndexTest">, 4.376546631000004]
 test_index_as_non-admin#UsersIndexTest (4.38s)
ActionView::Template::Error:         ActionView::Template::Error: wrong number of arguments (given 0, expected 1)
            app/views/users/index.html.erb:4:in `_app_views_users_index_html_erb___422248519655019949_47073486417860'
            test/integration/users_index_test.rb:29:in `block in <class:UsersIndexTest>'
```

初心者なりに悩みに悩みましたが、結局は解決できました。
実はこれ、gem自体のバグでした。ですのでgemのバージョンを3.1.6から3.1.7に変えて、rails bundle installとしてあげれば解決します。

```
source 'https://rubygems.org'
.
.
gem 'will_paginate',           '3.1.7'
gem 'bootstrap-will_paginate', '1.0.0'
.
.
```

2019年5月1日時点でRails tutorialの記載が変更されていないので、私自身を含め、ここで躓く方が多いのではないかと思い、記事を作成させていただきました。

ソースhttps://github.com/mislav/will_paginate/issues/589
SQL初級編

SQLを学んだので備忘録として…。

# SQLとは
リレーショナルデータベースに保存したデータを操作するプログラム言語のこと。
実際にデータを操作する際にはSQLでクエリを作成し、データベースに処理要求を行う。

# 使用する主なクエリ
**CREATE**
データベースを作成

```
CREATE DATABASE データベース名;
```

テーブルを作成

```
CREATE TABLE テーブル名(カラム名 型,カラム名 型);
```

型のほかにもオートインクリメントなどの制約をつけることもできる。

**INSERT**
データを格納

```
INSERT INTO テーブル名 (カラム名,カラム名) VALUE (値,値);
```

制約によってNULLを受け付けない場合、情報を入れなければエラーとなる。

**SELECT**
データを取得

```
SELECT カラム名 FROM テーブル名;
```

カラム名を*とするとテーブルにある全てのカラムを選択する。
条件を絞ったり、並び順を変えて表示させることもできる。

**UPDATE**
データを更新

```
UPDATE テーブル名 SET カラム名 = 値, カラム名 = 値 WHERE 条件;
```

条件を絞らない場合、すべて変更されるため要注意。

**DELETE**
データを削除

```
DELETE FROM テーブル名 WHERE 条件;
```

条件を絞らない場合、すべて削除されるため要注意。
一度SELECTで削除したい情報が選択できているか確認すると良い。

# まとめ
情報を変更又は削除する場合、復旧ができるとも限らないため慎重に行う必要がある。
なんにせよ、データベースは情報を扱うため全体的に注意が必要。
RaspberrypiでのLIRCの設定 kernel 4.19.x

本当にちょくちょく変わる設定方法ですがまた変わっていたので書いておきます．
今までのように設定したら

```terminal
>> irsend SEND_ONCE hoge hoge
hardware does not support sending
Error running command: Input/output error
```
と出たり

```terminal
>> sudo /etc/init.d/lircd status
● lircd.service - Flexible IR remote input/output application support
   Loaded: loaded (/lib/systemd/system/lircd.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2019-05-04 18:33:23 JST; 4min 55s ago
     Docs: man:lircd(8)
           http://lirc.org/html/configure.html
 Main PID: 1295 (lircd)
   CGroup: /system.slice/lircd.service
           └─1295 /usr/sbin/lircd --nodaemon

 5月 04 18:33:33 raspberrypi lircd[1295]: lircd-0.9.4c[1295]: Error: error processing command: SEND_ONCE hoge hoge
 5月 04 18:33:33 raspberrypi lircd[1295]: lircd-0.9.4c[1295]: Error: hardware does not support sending
 5月 04 18:33:33 raspberrypi lircd[1295]: lircd-0.9.4c[1295]: Info: removed client
 5月 04 18:33:33 raspberrypi lircd-0.9.4c[1295]: Info: Cannot configure the rc device for /dev/lirc0
 5月 04 18:33:33 raspberrypi lircd-0.9.4c[1295]: Error: could not get file information for /dev/lirc0
 5月 04 18:33:33 raspberrypi lircd-0.9.4c[1295]: default_init(): No such file or directory
 5月 04 18:33:33 raspberrypi lircd-0.9.4c[1295]: Warning: Failed to initialize hardware
 5月 04 18:33:33 raspberrypi lircd-0.9.4c[1295]: Error: error processing command: SEND_ONCE hoge hoge
 5月 04 18:33:33 raspberrypi lircd-0.9.4c[1295]: Error: hardware does not support sending
 5月 04 18:33:33 raspberrypi lircd-0.9.4c[1295]: Info: removed client
```
となってそもそも`lirc`が起動していないようでした．(`/dev/lirc0`が存在しなかった)

今(2019/05/05)のところ日本語でブログになってるのはココぐらいだったので
http://blog.livedoor.jp/marushin_yaoya/archives/16295088.html
検索しやすいように色々書いておきます．

結論から言うと下記の本家を参考に
https://www.raspberrypi.org/forums/viewtopic.php?t=235256

```/boot/config.txt
dtoverlay=gpio-ir,gpio_pin=24
dtoverlay=gpio-ir-tx,gpio_pin=25
```
と書くみたいです．`gpio-ir`がこれまででいう`gpio_in_pin`，`gpio-ir-tx`が`gpio_out_pin`です．
`/etc/modules`は変更する必要ありません．

送受信についても上記の本家サイトの下の方に書いてありますが，`irsend`については以前と同じで

```/etc/lirc/lirc_options.conf
driver = default
device = /dev/lirc0
```
とすれば良いらしいです．上記の設定で無事動きました．`irrecord`については試してませんので書きませんがおそらくサイト通りに設定すれば良いのではないでしょうか．

# 以前の設定方法
上の方法で直らない人はkernelが古いかもしれません．
ちょっと古いkernelでの設定方法だと
`/etc/modules`変更するなら

```/etc/modules
lirc_dev
lirc_rpi gpio_in_pin=24 gpio_out_pin=25
```

`/boot/config.txt`変更するなら

```/boot/config.txt
dtoverlay=lirc-rpi,gpio_in_pin=24,gpio_out_pin=25
```
とか，

```/boot/config.txt
dtoverlay=lirc-rpi:gpio_in_pin=24,gpio_out_pin=25
```
もしくは，

```/boot/config.txt
dtoverlay=lirc-rpi
dtparam=gpio_in_pin=24
dtparam=gpio_out_pin=25
```
ってのがありました．今の私の環境(`kernel 4.19.37+`)ではどれもダメでした．
クラスに一組は誕生日が同じっていう人達がいるというあれ

皆さんこんにちは

非常にどうでもいいことなのですが、たまに飲みの席とかで数学的なウンチクを言ってみたくなることってありますよね(?)。
そんなウンチクの中で、ワタシの頭にこびりついているのが、高校時代に数学の教員が言っていた、「これくらいの規模のクラス(36人だったか)だと、誕生日が同じっていうペアが一つはある」って言っていて、実際に誕生日を言っていったら、瞬時に同じ誕生日のペアが見つかったって言うことがあって、なんでやろうみたいな感じになりました。

そんな懐かしいウンチクを検証していきましょう。

# 問題設定

「36人規模のクラスに一組は誕生日が同じ人がいる」という命題が正しいのか否か、というのが今回の問題設定です。
これは余事象の問題に落とし込むと簡単で、つまるところ、「36人規模のクラスの全員の誕生日が違う」ことの余事象を考えればよいということです。
式にするとこんな感じです。

```math
P(一組は誕生日が同じ人がいる) = 1- P(全員の誕生日が違う)
```
これが１に近ければ命題は正しいということになります。

今回は細かいことを抜きにするため、１年は365日で計算します。

# 検証コード
## 数式の導出
次に検証していきましょう。
まず、クラス全員の誕生日が違う確率を出してみます。ここでは漸化式を使った導出が楽でしょう。

クラス人数がn人のときのクラス全員の誕生日が違う確率を$p(n)$とします。
まず、クラスが一人だけのときはどんなに頑張ってもペアはできないので、$p(1) = 1$となります。
次に、そのクラスに一人追加したとして、$p(2)$がどうなるかです。当然、二人目は一人目とは違う誕生日である必要があるので、一年365日の中から、一人目とは違う誕生日である確率、つまり、$364/365 = 0.997 = p(2)$となるわけです。
更に一人加えてクラスを３人にすると、$p(3) = \frac{363}{365} p(2)$のようになります。
これを繰り返すと、漸化式として

```math
p(n) = \frac{365 - (n-1) }{365}p(n-1)
```
これは展開すると

```math
p(n) = \frac{365}{365} \frac{364}{365} ... \frac{365-(n-1)}{365} = \frac{{}_{365} \mathrm{P} _{n} }{ 365^n}
```
となります。
割とあっさりしています。

なお、人数が365を超えると、必ず一人は誕生日がかぶるので、これ以上は考える必要はないです。

## コードにする

我々の共通言語はコードですので、これをコードに落としましょう。
例によってPHP使いますが、コード自体はエラい簡単です。

```php
<?php
$P_birthday = [];

// 全員の誕生日が違う確率を人数ごとに算出
$P_birthday[1] = 1;
for ($i = 2; $i !== 366; $i++) {
    $P_birthday[$i] = (366 - $i) * $P_birthday[$i - 1] / 365;
}

// クラス人数ごとに一組は誕生日が同じペアが入る確率を出力
for ($j = 1; $j !== 366; $j++) {
    $ret = 1 - $P_birthday[$j];
    echo "$j\t$ret\n";
}
```
コードはとても単純です。
これを実行すると、

```
1       0
2       0.0027397260273972
3       0.0082041658847815
4       0.01635591246655
5       0.027135573699794
6       0.040462483649112
7       0.056235703095976
8       0.074335292351669
9       0.094623833889167
10      0.11694817771108
11      0.14114137832173
12      0.16702478883806
13      0.19441027523243
14      0.22310251200497
```
こんな感じの数値の羅列が得られます。
これを見ていくと、36人のときは、$0.8321$となっていて、およそ$83\%$の確率で誕生日が同じペアが存在するということになります。

これをグラフ化するとこんな感じです。
<img width="523" alt="スクリーンショット 2019-05-05 14.49.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102182/b129a13f-2a96-0b15-4101-cc231aa26466.png">
40人のクラスだと$89\%$で誕生日が同じペアが存在し、50人規模であれば$97\%$で同じ誕生日のペアがいます。
100人を超えると、$99.99...\%$みたいに、S3の可用性みたいな数値が出てきます。

# まとめ

突発的に思い出したので、検証したものを書きました。
それほど学びの深い記事ではないのですが、この現象になにか名前があるのかしらと思ったら「誕生日のパラドクス」なんて大層な名前がついているのね。

というわけで、適当にドヤるのにおすすめですよと言っておいて、今回はこの辺にしておきます。

# 参考
[誕生日のパラドクス](https://ja.wikipedia.org/wiki/%E8%AA%95%E7%94%9F%E6%97%A5%E3%81%AE%E3%83%91%E3%83%A9%E3%83%89%E3%83%83%E3%82%AF%E3%82%B9)
Railsサーバー起動時のエラー解決

```
rails s
```
rails起動時以下のエラーが発生。

```
No such file or directory @ rb_sysopen - /Users/〜(railsのディレクトリ)/Gemfile.lock (Errno::ENOENT)
```

以下のコマンド入力で、gemをアップデートして解決。

```
bundle install
```
Android DevelopersのAndroid 入門でEdit Baselineの`ab`ボタンを表示する方法がわからなくて困った

Android DevelopersのAndroid 入門でEdit Baselineの`ab`ボタンを表示する方法がわからなくて困った

`Android Developers -> Docs -> ガイド -> 簡単なユーザー インターフェースの作成 -> ボタンを追加する`にて、Edit Baselineの`ab`ボタンを表示する方法がわからなくて困ったのでメモ。
当該のページは[こちら](https://developer.android.com/training/basics/firstapp/building-ui?hl=ja#button)。

Android Studioのバージョンは3.4です。

![android.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/220908/53fd77ba-1010-175f-8d36-f9f6a15f0209.gif)

Buttonを右クリックしてShow BaselineでBaselineが表示されます。
Alpine Linux + PHP5.6 の Docker コンテナで、xdebug や ssh2 モジュールをマルチステージビルドする

PHP5.6 + Apache mod_php のコンテナを、Ubuntuベースから → Alpine Linux ベースに変更した。

Alpine Linux の apk パッケージリポジトリでは、PHP5.6用の xdebug や SSH2 モジュールは無いため、PECL からソースコードを持ってきて Docker コンテナ内でビルドする必要がある。

1つの Alpine の Docker コンテナで、ビルド環境を整えて xdebug や SSH2 をインストールすると 240MB ぐらいのイメージサイズになるが、ビルド環境構築済みの Docker コンテナで必要なものだけビルドし、ビルド済みオブジェクトファイルだけを新しい Alpine ベースのイメージにコピーする方法 (マルチステージビルド) だと、Docker イメージのサイズを 50MB ぐらいに抑えられる。

ちなみに、これを書いた時点の Alpine の最終バージョンは 3.9 だが、PHP5.6系のリポジトリが充実しているのは 3.7 なので、3.7 をベースとした。

```Dockerfile:Dockerfile
# BUILDER ( xdebug, ssh2 をビルドするため)
# php5.6 が使えるのは3.7まで
FROM alpine:3.7 as builder

MAINTAINER ytyng

# pecl コマンドは pear をインストールすると使える
RUN apk --no-cache add \
 gcc\
 libc-dev\
 autoconf\
 make\
 libssh2-dev\
 php5\
 php5-cli\
 php5-pear\
 php5-openssl\
 php5-dev

# そのままだと php コマンドがないため pecl できない。
RUN ln -s /usr/bin/php5 /usr/bin/php

RUN pecl channel-update pecl.php.net

# pecl でビルド
RUN pecl install xdebug-2.5.5
RUN pecl install ssh2-0.13

# 実運用コンテナ
FROM alpine:3.7

RUN apk --no-cache add \
 php5\
 apache2\
 php5-apache2\
 php5-mysql\
 php5-imap\
 php5-zlib\
 php5-pdo_mysql\
 php5-iconv\
 php5-mcrypt\
 php5-exif\
 php5-gd\
 php5-xml\
 php5-cli\
 php5-pear\
 php5-pdo\
 php5-curl\
 php5-openssl

RUN mkdir /run/apache2
RUN rm /etc/apache2/conf.d/userdir.conf /etc/apache2/conf.d/info.conf

COPY --from=builder /usr/lib/php5/modules/xdebug.so /usr/lib/php5/modules/
COPY --from=builder /usr/lib/php5/modules/ssh2.so /usr/lib/php5/modules/
RUN echo "zend_extension=/usr/lib/php5/modules/xdebug.so" > /etc/php5/conf.d/xdebug.ini
RUN echo "extension=ssh2.so" > /etc/php5/conf.d/ssh2.ini

COPY site.conf /etc/apache2/conf.d/site.conf

COPY php-extends.ini /etc/php5/conf.d/php-extends.ini

EXPOSE 80 443

CMD ["httpd", "-D", "FOREGROUND"]
```



phpinfo() を見てみると

![phpinfo__.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68302/a9d8bee2-16d6-88b5-6dad-210b231229c7.png)

![phpinfo__.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68302/2d903a60-c6dc-b0fd-f4f1-66308369b904.png)

別コンテナでビルドしたモジュールが読み込めている。


参考までに、他のファイル

```yaml:docker-compose.yaml
version: '2'
services:
  php56-alpine:
    build: .
    image: php56-alpine:0.1
    container_name: php56-alpine
    privileged: true
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./src:/var/src
```

```ini:php-extends.ini
[date]
date.timezone = "Asia/Tokyo"

[xdebug]
xdebug.remote_enable=1
xdebug.remote_host=10.200.10.1
xdebug.remote_port=9001
xdebug.remote_autostart=0
xdebug.force_display_errors=1
xdebug.force_error_reporting=1
xdebug.idekey="PHPSTORM"

# リモートデバッグ用
# sudo ifconfig lo0 alias 10.200.10.1/24 しておく
```

```apache:site.conf
DocumentRoot "/var/src/htdocs"
<Directory "/var/src/htdocs">
    AllowOverride All
    Require all granted
</Directory>
```

```php:src/htdocs/index.php
<?php
phpinfo();
```
.NET Core CLIのプレビュー版が入っているマシンでバージョンを指定して実行するために、global.jsonを使う

2019年5月現在、.NET Coreと.NET Core CLIは、

* プレビュー : .NET Core 3
* 正式版 : .NET Core 2.2

となっています。

プレビュー版を試しながら、正式版で開発という人もいるかと思います。

さて、一つのマシンに正式版とプレビュー版が同居していると、.NET CLIを使った時、より新しい方であるプレビュー版が使われます。

製品リリースを行う場合、プレビュー版でなく製品版を使いたいですね。

.NET CLIでバージョンを指定するには、`global.json`を利用します。

詳しくは、次のマイクロソフトの公式ドキュメント「`global.json overview`」を見てください。

https://docs.microsoft.com/en-us/dotnet/core/tools/global-json
【基礎知識】sessionとcookie

#sessionとcookieとは
あいまいだったので調べてみました。

##sessionって何？
サーバー側で発行されるもの。
webサイトにログインしてからログアウトするまでの一連の操作や通信のこと。
sessionはsessionIDという名目でsession_start()で発行されます。

##cookieって何？
cookieはset_cookie()を使用しサーバー側で発行されブラウザで保存されます。
ちなみにset_cookieを使わなくても、ブラウザ側でcookieのON,OFFを切り替えることができます。

##ネットワークの通信は何が起きているのか
まずここからです。webサイトを閲覧するとき何が起きているのか。
ざっくり説明するとPCとwebサイトを保存しているサーバー間で通信が起きています。
やりとりはこんな感じ。

**PC「このページを見たいからこれに関するデータ頂戴！」
サーバー「あいよー。これだよ！」**

**PC「次はこのページを見たいからこれに関するデータ頂戴！」
サーバー「あいよー。これだよ！」**

**PC「次はこのページを見たいからこれに関するデータ頂戴！」
サーバー「あいよー。これだよ！」**

このPCが送ることをリクエストと言い、サーバーがデータを返すことをレスポンスと言います。


##なぜcookieが必要なのか
実はHTTPプロトコルという通信方法は「リクエストを送ってレスポンスを返す」という一往復で通信が切れるようにできています。
これをステートレスと言います。（ステートフルもあります）

なので、2回目の通信からは誰から要求されているリクエストなのか分からないんですね。
これを防ぐのがcookieと呼ばれるシステムです。

set_cookie();でcookieを発行しレスポンスします。
するとこのcookieはブラウザで保存されます。

でも、ブラウザ側で保存するとcookieの値を改ざんできた場合他のユーザーになりすますことだってできます。
そこで出てくるのがsessionです。

##なぜセッションが必要なのか
セッションがなぜ必要なのかを話します。

sessionはsession_start()関数を使ってサーバー側で発行します。これをsessionIDと言います。
このsessionIDはサーバー側で保存されcookieの中に入れられてレスポンスされます。

そして、ブラウザはsessionIDが入ったcookieを保存し、次の通信からcookieの情報をリクエストに付け加えて送ります。

リクエストを受け取ったサーバーはsessionIDを参考にするんですね。
もし仮に cookieだけのやり取りで、その中の情報がサイトにログインするためのパスワードを改ざんしたものだとしたらどうでしょう？

サーバーは改ざんされた人のデータをレスポンスします。
これでなりすましの完成です。

だけど、sessionIDを用いてたら。
仮にsessionIDを改ざんしても、サーバー側に正しいsessionIDが残っているので照合が合わず通信できません。
理屈はこんな感じです。

##まとめ
PolkadotのParachainを作る方法（テストネット）

![What-is-it.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327904/617875a3-61bf-1281-7498-652e7f133f56.jpeg)
PolkadotにはParachainとRelaychainがあります。RelaychainはPolkadotの本体であり、ParachainをRelaychainに繋げることによってRelaychainのセキュリティを得ることができたり、Parachain間で通信を行うことができるようになります。RelaychainもParachainも基本的にブロックチェーン作成フレームワークであるSubstrateを基にできています。Substrateを用いるとブロックチェーンをカスタマイズすることができるようになります。Polkadotで言えば、Relaychainではスマートコントラクトを動かす機能がついていませんが、Paracahibnではスマートコントラクトを動かす機能をつけることもできます。（開発者の意思決定次第）

では、ここでは、PolkadotのRelaychainにParachainを接続する方法を見てみます。

まず最初にPolkadotのcodeをローカル環境にダウンロードします。
`git clone https://github.com/paritytech/polkadot.git`

次にRustをインストールします。
`curl https://sh.rustup.rs -sSf | sh`
`sudo apt install make clang pkg-config libssl-dev`
`rustup update`

<img width="467" alt="Screen Shot 2019-05-03 at 23.00.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327904/eeaa95da-5fb3-b578-3f65-0d4927b19ea6.png">


インストールが完了したら、`test-parachains`フォルダーに以降し、ビルドします。
`cd polkadot/test-parachains`
`./build.sh`

WASMファイルは`parachains/test/res/adder.wasm`に吐き出される。 

Paracahinを動かすにあたって、collatorノードをビルドする必要がある。`test-parachains/adder/collator`に移動し、ビルドとランを行う。
`cargo build`
`cargo run`
`[ctrl-c]`で終了。

collatorの役割は[こちら](https://github.com/stakedtechnologies/PolkadotWP/blob/master/Chapter/004_Participation_In_Polkadot.md)を確認すると良いかもしれない。

<img width="1440" alt="Screen Shot 2019-05-04 at 0.40.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327904/d3b58df7-e83d-c86f-06dd-9aa46ce65b5c.png">

runをさせた状態で、[PolkadotUI](https://polkadot.js.org/apps/#/extrinsics)へ移行する。

まず自分のアカウントを作るためにAccountタブ→Create Accountを押し、独自のアカウントを作成する。
僕の場合`5HgHBm9ojGqmm7s3hMTv2McAtbxhZimioUrWy2NmXETUDCY4`

[faucet](https://faucet.polkadot.chat/)に移動し、DOTを手にいれる。これはEthereumのFaucetと同じやり方。
<img width="910" alt="Screen Shot 2019-05-05 at 13.32.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327904/0228703c-759f-06f3-dfcc-3dc4c3f3c686.png">

FaucetでDOTを得ることができない。。。。。。のでここからは追記していく。

<h2>参考</h2>
http://wiki.polkadot.network/en/latest/polkadot/build/deploy-parachains/
【イラレ不要】iPhoneアプリに使用する画像を作ってみたい超初心者向けWEBサービスまとめ

iPhone（Android)アプリに使用する画像を作成・編集したいけど、何から手をつけたらいいのか全く分からない人向けの記事です。初心者かつ画像編集って何から手をつければ…？という方は、以下のWEBサービスを利用してみてください。
![goal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395404/86f1cc27-43a7-78c1-3f23-dc3d4a5b2668.png)
👆こんな感じの画像を作成しました。クオリティは大目に見てください。
###１.画像に使うイラストを探す
自分でイラストを描くとかは無理なので、[いらすとや](https://www.irasutoya.com/) と[ジャパクリップ](https://japaclip.jp/) から、ちょうどいいものを探しました。どちらもテイストが似ているので、組み合わせても違和感がありません。

###2.画像編集ソフトを使用する
無料ソフトでは、[pixlr](https://pixlr.com/x/)が使いやすかったです。英語ですが、イラストが多用されているので、直感的に使うことができます。画像を重ねる、文字を入力する（フォントも選べる）、画像サイズを変更できる、フィルターをかけて色味を変える等の機能があります。

###3.文章を画像化する
画像に文字を入れたい場合、pixlrで直接打ち込むことも可能ですが、フォントに凝りたければ、[文字画像作成機 | 任天堂ファンサイト](http://www.nin-fan.net/tool/string_image.html)が便利です。シンプルで分かりすいUIにも関わらず、フォントの種類も豊富だし、色も自由に選べて、作成したらボタン1つで画像化してくれます。

###4.画像を薄くする
画像に文字を重ねる場合、イラストの色が濃すぎると読みづらいので、[画像半透明化ツール](http://www.webtoolss.com/box/hantouka.html)で薄く（半透明化）してあげるとよいです。画像をアップロードし、透明度を選択するだけです。

###5.文字色を検索する
文字色を指定する時、カラーグラフからではなく、カラーコードを入力したほうが正確な色が指定できます。[原色大辞典](https://www.colordic.org/)は、色味を調べられるだけではなく、カラーコードをコピペ出来るのでとても便利です。ちなみにこのサイトは、アプリ制作でもお世話になると思います。（アプリ上の文字や背景の色のカラーコードを調べるのにも便利。）

![dennou.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395404/328fd96a-ff8b-8368-5e3d-acce06f9a4a4.png)
👆宇宙区間を漂うおみくじたちの画像。スプラッシュ画面（アプリ起動時の待機画面）で表示される。
スタックとキューについて〜キュー編〜(JavaScript)

2回目であるこの記事では、主にキューについて解説します。
そもそもスタックやキューとは何なのか、スタックとは何なのかに関しては<a href="">前回<a/>の記事を参照してください。
#目次
* キューの保存(enqueue)の仕方
* キューの取り出し方(dequeue)
* FirstInFirstOut(FIFO)
* JavaScriptでキューを実装
* 参考にしたサイト一覧
* まとめ

##キューの保存(enqueue)の仕方
キューはデータを保存された場合、両端があいた箱の中にデータを入れていくように保存します。この事をenqueue（エンキュー）といいます。
図1の右側にある入り口と出口が空いている筒のようなものがキューです。
![enqueue1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355738/0d288383-3079-3dcc-10d1-a597515b2985.png)
図1 キューのイメージ

キューの中に青色のデータを保存すると、図2のようになります。
![enqueue2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355738/8af4a3c8-e433-6134-a34a-2fdbf051c1b7.png)
図2 青色のデータを保存

次に緑色のデータを保存すると、図4のようになります。
![enqueue3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355738/d2872282-1f29-0746-22e1-7334bf367b27.png)
図3 緑色のデータを保存

最後にピンク色のデータを保存すると、図4のようになります。
![enqueue4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355738/982587ce-be00-4237-6774-6a6ea881ee65.png)
図4 ピンク色のデータを保存

##キューの取り出し方(dequeue)
データを取り出すとき、キューはデータを保存した口とは別の口から順番に取り出します。このことをdequeueといいます。

![dequeue1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355738/40f6fae1-9485-4c6e-358a-2dc3b5e549f8.png)
図5 キュー　取り出し方のイメージ

先ほどの図4の状態のキューからデータを取り出すと、図6のようになります。

![dequeue2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355738/e1fb6ee7-5a04-65e2-60d5-81970c60cd5d.png)
図6 1回目の取り出しのイメージ

図6の状態で取り出すと、図7に、図7の状態で取り出すと図8のようになります。
![dequeue3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355738/63c13002-7162-0d5e-dbd6-1ac6226e9d8c.png)
図7 ２回目の取り出しのイメージ

![dequeue4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355738/6a32d30e-1176-2c4e-8e9a-a2821a0c6955.png)
図8 ３回目の取り出しのイメージ

ちなみにキューはビリヤードで使う棒が由来のようです。

##FirstInFirstOut(FIFO)
上記の例より、キューはデータを取り出しとき一番最初に保存したデータから取り出すことが分かったと思います。
このようなデータの取り出し方をFirstInFirstOut(FIFO)といいます。
文字通り、一番初めに保存したデータ(FirstIn)を一番最初に取り出す(FirstOut)という意味です。

#JavaScriptでキューを実装
ここまでキューの考え方について解説しました。ここからは実際にキューを使ってみます。
今回は配列を使って、キューを実装していきます。以下、実装例です。


```javascript
console.log('------キューの実装------');
console.log('キューのエンキューを実装');

// スタック用の配列を用意
const queue = [];
console.log('最初のqueueの中身', queue);

// データを保存
queue.push('青色のデータ');
console.log('1回目enqueueされたqueueの中身', queue);

queue.push('緑色のデータ');
console.log('2回目enqueueされたqueueの中身', queue);

queue.push('ピンク色のデータ');
console.log('3回目enqueueされたqueueの中身', queue);

console.log('------------------------------------');
console.log('キューのデキューを実装');

// データを取り出す
queue.shift();
console.log('1回目dequeueされたqueueの中身', queue);

queue.shift();
console.log('2回目dequeueされたqueueの中身', queue);

queue.shift();
console.log('3回目dequeueされたqueueの中身', queue);
```

上記のコードを実行結果は以下の画像のようになります。

![coded-queue.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355738/6814acde-25f0-a9b5-5bf4-c7fa9934891c.png)
#参考にしたサイト一覧
この記事を書くにあたって参考にしたサイト一覧です。
<a href="https://mathwords.net/stack">算数から高度な数学まで、網羅的に解説したサイト</a>
：キューだけでなく、スタックについても分かりやすく説明されています。

#まとめ
今回は以下の内容について解説しました。

　+ スタックやキューとは
　+ キューの保存の仕方
　+ キューの取り出し方
　+ キューはFirstInFirstOut
　+ JavaScriptでキューを実装する
今年の言語はRust その５３

# 今年の言語はRust その５３

Rustを学びます

Rustの日本語ドキュメント 2nd Edition
https://doc.rust-jp.rs/book/second-edition/

オリジナル(英語)
https://doc.rust-lang.org/book/


## 実行環境

```sh
$ cargo -V
cargo 1.33.0 (f099fe94b 2019-02-12)

$ rustup -V
rustup 1.17.0 (069c88ed6 2019-03-05)

$ rustc --version
rustc 1.33.0 (2aa4c46cf 2019-02-28)

$  cat /proc/version
Linux version 4.14.97-74.72.amzn1.x86_64 (mockbuild@gobi-build-64002) 
(gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC)) 
#1 SMP Tue Feb 5 20:59:30 UTC 2019

$ uname -a
Linux ip-10-100-0-8 4.14.97-74.72.amzn1.x86_64 
#1 SMP Tue Feb 5 20:59:30 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/\*release
NAME="Amazon Linux AMI"
VERSION="2018.03"
ID="amzn"
ID_LIKE="rhel fedora"
VERSION_ID="2018.03"
PRETTY_NAME="Amazon Linux AMI 2018.03"
ANSI_COLOR="0;33"
CPE_NAME="cpe:/o:amazon:linux:2018.03:ga"
HOME_URL="http://aws.amazon.com/amazon-linux-ami/"
Amazon Linux AMI release 2018.03

```

## 18. パターンは値の構造に合致する

### 18.3 パターン記法

#### ref と ref mut でパターンに参照を生成する

```rust

fn main() {

  let robot_name = Some(String::from("Bors"));

  match robot_name {
    Some(name) => println!("Found a name: {:?}", name),
    None => (),
  }

  println!("Robot name is {:?}", robot_name); // <= nameに所有権を奪われてエラーになる
}
```

これを回避するために, refを使って、参照を借りてきます

```rust

fn main() {

  let robot_name = Some(String::from("Bors"));

  match robot_name {
    Some(ref name) => println!("Found a name: {:?}", name),
    None => (),
  }

  println!("Robot name is {:?}", robot_name); // <= nameに所有権を奪われてエラーになる
}
```

__mut__ を利用し、可変参照にする.


```rust
fn main() {

  let mut robot_name = Some(String::from("Bors"));

  match robot_name {
    Some(ref mut name) => *name = String::from("Another name"),
    None => (),
  }

  println!("Robot name is {:?}", robot_name); // <= nameに所有権を奪われてエラーになる
}
```

#### マッチガードで追加の条件式

```rust

fn main() {

  let num = Some(10);

  match num {
    Some(x) if x < 5 => println!("less than five: {:?}", x),
    Some(x) => println!("{:?}", x),
    None => ()
  }
}
```


マッチガードにより__パターンがシャドーイング__ する問題を解決する

```rust

fn main() {

  let x = Some(5);
  let y = 10;

  match x {
    Some(50) => println!("Got 50"),
    Some(n) if n==y => println!("Matched n={:?}", n),
    _ => println!("Default case x={:?}", x)
  }

  println!("at the end: x={:?}, y={:?}", x, y);

}
```

ガードとパターンの両方の規則にのっとる

```rust

fn main() {

  let x = 4;
  let y = false;

  match x {
    4 | 5 | 6 if y => println!("yes"),
    _ => println!("no"),
  }
}
```

#### @束縛

```rust

enum Message {
  Hello { id: i32},
}


fn main () {

  let msg = Message::Hello {id:5};


  match msg {

    Message::Hello {id: id_variable @ 3...7} => {
      println!("Found an id in range: {:?}", id_variable);
    },

    Message::Hello { id: 10...12 } => {
      println!("Found an id in another range");
    },

    Message::Hello { id } => {
      println!("Found some other id: {}", id)
    }

  }


}

```

> @を使用することで、値を検査しつつ、1つのパターン内で変数に保存させてくれるのです。




やっとパターン終わり！！第18章まで写経完了！
Webサーバーまであと1章!!!


イエス！
Leetcode #82: Remove Duplicates from Sorted List II

First try failed at the case [1,2,2]

```swift
func deleteDuplicates(_ head: ListNode?) -> ListNode? {
    var dummyHead = ListNode(0)
    var pre = dummyHead
    var current = head
    var duplicate = false
    while current != nil {
        if current?.next == nil || current!.val != current!.next!.val {
            if !duplicate {
                pre.next = current
                pre = current!
            }
            duplicate = false
        } else {
            duplicate = true
        }
        current = current?.next
    }
    pre.next = nil
    return dummyHead.next
}
```
俺様サーバー構築記 - Arch Linux + ZFS + Xfce に vlc をインストール@ノートパソコン

DVD再生については規制の壁が鬱陶しい。著作権法とか環太平洋パートナーシップ協定TPPとか。これに違反すると「犯罪者」になってしまうのが恐ろしい… 世間には「見せしめ逮捕」というのもあるので、決して他人事ではありません。実際にそれでとっつかまってマスコミが大々的に「実名顔写真付き」で報道しちゃった事例も少なくありません。

で、法律が絡んだ案件だと、自分はこう考えているってのは一切関係ありません。だから余計に腹立たしいんですけどね。例えば私は、無断コピーを防ぎたいなら技術で禁止するんじゃなくて、衝動買い出来るほどに値段（及び視聴の為の操作を含んだ総合的なコスト）を下げるべきだと考えています。当然そんな意見は受け入れられませんよね、特に現状で利権に絡んでいる人達は。

ならばまずは現状のルールを確認しよう…と思っても、著作権絡みの案件は今ものすごい勢いでルールが変わってきています。数年前の解説は役に立たない可能性が高い。今の日本でホットな話題は、動画ではなくて静止画の方ですけども。

今年に入ってからの動きに限っても、総理が官庁に直接指示したとか、官庁の素案を完全に廃棄して有識者ヒアリングからやり直しているという珍しい事案になったとか、そんな動きになっているようです。ちなみにこれ、ホームページに貼り付けたアイコンなんかをダウンロードした瞬間に違法になるなんてのが元々の素案だったりしたようです。オタク趣味以前に、IT技術者にとって他人事じゃありません。

純粋な技術の記事、それもアプリケーションのインストールの記事において、こんなに五月蝿く法律の規制のと騒ぐ理由はですね。動画再生ソフト vlc って、どうも著作権的に怪しい部分を含んでいる可能性があるからです。

私は問題無いと思っていますが、万が一、世間的に見て違法だと判断されるようでしたら、まずは根拠と共に御一報お願いします。危ないならこの記事を丸ごと非表示にします。私は別に、こんな事で世間を騒がせたいと考えてる訳ではありませんので。

余談。少なくとも日本において、著作権を厳密に守ろうとしたら、身動きが取れなくなるでしょう。例えばムードの高まる曲を集めておいて、彼女とドライブの時にBGMで流す。これ実は一発アウトなんですよね。そして、こういうのを管理している著作権協会という組織は、も〜のすごい利権の塊です。意外と知られていないと思いますが。

> 社会のルールってのはすべて頭の良い奴が作っている
> つまりそれがどういうことかわかるか・・・
> そのルールは頭の良い奴に都合のいいように作られてるんだ。
> 逆に都合の悪いところは分からないように隠してある。

（&copy;ドラゴン桜）

# インストール

参考文献1: [VLC media player - ArchWiki](https://wiki.archlinux.jp/index.php/VLC_media_player)
参考文献2: [vlcでDVDを見る(Arch Linux) - BobbyQuineのブログ(備忘録)](http://bobbyquine.hatenablog.com/entry/2018/01/17/233142)

まずはスナップショット。

```console
$ su
パスワード:
# zfs snapshot tank/main@$(date +%Y%m%d_%H%M%S)_before_vlc
# zfs list -t snapshot
NAME                                      USED  AVAIL  REFER  MOUNTPOINT
  〈省略〉
tank/main@20190505_134512_before_vlc        0B      -  6.28G  -
```

それから関連ソフトをインストール。

```console
# pacman -S vlc libcdio libdvdread libdvdcss libdvdnav
```

# 実行

ターミナルから、rootではなく一般ユーザとしてコマンド実行。

```console
$ vlc
```

または メニュー>アプリケーション>マルチメディア>VLCメディアプレイヤー

DVDを再生するだけなら、見た感じの直感に従ってメニューを操作すればOKです。
これで昔買ったえっちなDVDをげふんげふん… え〜と、や、やったね？？:thumbsup_tone2:
PHP(Laravel)からGuzzleを使用して、connpass APIを叩いてみた

# 概要
Laravelからconnpassのイベント情報を取得する方法の備忘録です。
リクエスト処理はGuzzleを使用しました。

# コード

Guzzleのライブラリをインストール
`composer require guzzlehttp/guzzle`

```php5

<?php
namespace App\Services;

class ScrapingService
{
    // evetnt_idはconnpassのURLで表示されるIDのこと
    // https://web-engineer-meetup.connpass.com/event/128855/ → 128855
    public function getConnpassData($event_id)
    {
        $client = new \GuzzleHttp\Client();
        $res = $client->request('GET', 'https://connpass.com/api/v1/event/', [
            'query' => ['event_id' => $event_id]
        ]);

        $json = json_decode($res->getBody(), true);

        return array(
            "owner_display_name" => $json['events'][0]["owner_display_name"], // 管理者の表示名
            "hash_tag" => $json['events'][0]["hash_tag"], // Twitterのハッシュタグ
            "title" => $json['events'][0]["title"], // タイトル
            "waiting" => $json['events'][0]["waiting"], // 補欠者数
            "limit" => $json['events'][0]["limit"], // 定員
            "accepted" => $json['events'][0]["accepted"], // 参加者数
            "catch" => $json['events'][0]["catch"], // キャッチ
            "place" => $json['events'][0]["place"], // 開催会場
            "address" => $json['events'][0]["address"], // 開催場所
            "started_at" => $json['events'][0]["started_at"], // イベント開催日時 (ISO-8601形式)
        );
    }
}

```

# 参考URL
[connpass API リファレンス](https://connpass.com/about/api/)
[Guzzle Documentation](https://guzzle.readthedocs.io/en/latest/)
[今時のPHP HTTPクライアントのGuzzleを使ってみた](https://qiita.com/yousan/items/2a4d9eac82c77be8ba8b)