OmniAICreator/Qiita-1.07M huggingface dataset:
pandasで作る勤怠チェック(基本編)

# pandasで作る勤怠チェック(基本編)


## 背景
* 一日どの作業に何時間使ったか、というExcelファイル「作業管理表」がある。
![input.PNG](https://qiita-image-store.s3.amazonaws.com/0/10574/73332cd7-982c-6f48-d381-12729a23dd0c.png)

* 作業別に作業時間の集計作業のニーズ有り。
* Excelでvlookupがあるが**「ファイルを開かないとわからない」**

## 目的
* (基礎)ローカルにある１つのファイルを開き、作業別に集計する。
* (応用)ネットワーク上のファイル共有サーバにアクセス、フォルダ内にある複数のファイルを順次開き、担当者別作業別に集計する。

##　コーディングのポイント
* INPUT:「どのファイル？、そのシート？、どの番地から読み込む？」の指定。
* Transaction:「どの列情報を抜き出したい？」「サマリキーは？」の指定。
* Output:特になし。自由。

## 基礎編
```test.py
import pandas as pd

# Input_01:作業管理表を読み込む
file = pd.ExcelFile('import/作業管理表(名前).xlsx', encoding='utf8')

# Input_02:作業内訳シートを読み込む
sheet_df = file.parse('Sheet2', header=None)

# Transaction_01:ヘッダ行、空行を読み飛ばす。
sheet_df_no_header = sheet_df[3:]# データ行のみ

# Transaction_02:プロジェクト名、時間の列にデータを絞る。
sheet_df_select_loc = sheet_df_no_header.iloc[:,[2,4]]# 作業単位
sheet_df_select_loc_sum = sheet_df_no_header.iloc[:,[4]]# 合計

# Transaction_03:headerの指定と、集計キーの指定
sheet_df_select_loc.columns = ['proj', 'time']
grouped = sheet_df_select_loc.groupby('proj')# 作業名で集計

sheet_df_select_loc_sum.columns = ['totalTime']

# Output_01:コンソール表示
print("--1.稼働明細------------------------------")
print(sheet_df_select_loc)
print("--2.稼働集計------------------------------")
print(sheet_df_select_loc_sum.sum())# 合計
print(grouped.sum())# 作業別
print("--End------------------------------")

# Output_02:CSVファイル出力
sheet_df_select_loc_sum.sum().to_csv('to_csv_out_a.csv', mode='a')# 合計
grouped.sum().to_csv('to_csv_out_a.csv', mode='a')# 作業別

```
## 結果(コンソール)
``` console.log
--1.稼働明細------------------------------
        proj  time
3   既存システム保守     7
4         朝会   0.5
5     システム開発     9
6        定例会     2
7   既存システム保守  7.25
8     システム開発     4
9     システム開発     4
10    システム開発   1.5
11        朝会   0.5
12    システム開発     4
13  既存システム保守   3.5
14        朝会   0.5
15    システム開発  4.25
16       NaN   2.5
17  既存システム保守   1.5
18  既存システム保守     2
19    システム開発   3.5
20       定例会     2
21    システム開発     2
22  既存システム保守  8.25
23        朝会     1
--2.稼働集計------------------------------
totalTime    70.75
dtype: float64

proj           time
システム開発    32.25
定例会        4.00
既存システム保守  29.50
朝会         2.50
--End------------------------------
```
## 結果(csv)
```sample.csv
totalTime,70.75
proj,time
システム開発,32.25
定例会,4.0
既存システム保守,29.5
朝会,2.5
```

## 改善効果
* ファイルを開かなくなった分、集計作業が高速化。
* 大量のファイル、データを捌くと効果大。応用編で試す。
CakePHP2 のデバッグツールバーをプリチーにする

CakePHP2 のデバッグツールバー、使いにくいなァと思ったことはありませんか？　これです、これ。
![debug-toolbar.png](https://qiita-image-store.s3.amazonaws.com/0/107118/033de377-8e72-2dbc-29a9-d256c33c7db4.png)
まず、小さい。
![debug-toolbar-timer.png](https://qiita-image-store.s3.amazonaws.com/0/107118/c8d84dcb-4fbe-0525-ba85-d034f8a03175.png)
＋ボタンを押せば大きくできますが、そもそもページ右上部に配置される都合、オフキャンバスメニューの開閉ボタンと重なって押しにくかったり。

もしも、これが CakePHP3 のデバッグツールバーのように大きく、ページ右下部に配置されるようになったら便利だと思いませんか？
![pretty-debug-toolbar.png](https://qiita-image-store.s3.amazonaws.com/0/107118/b2df223b-a39e-3810-0b7a-1e720380f43e.png)
![pretty-debug-toolbar-timer.png](https://qiita-image-store.s3.amazonaws.com/0/107118/b905d7c1-d5ed-68cb-46d6-d9c95ba36b68.png)
そんな「もしも」を実現する [PrettyDebug](https://github.com/chinpei215/cakephp-pretty-debug) というプラグインを最近（といっても半年以上前）作りましたのでご紹介いたします。

## インストール手順
### プラグインの取得
Composer からインストールすることができます。

```json:composer.json
{
    "require-dev": {
        "cakephp/debug_kit": "^2.2",
        "chinpei215/cakephp-pretty-debug": "^0.1"
    }
}
```
　
PrettyDebug は DebugKit の見栄えを変えるだけのプラグインですので、 DebugKit 本体のインストールも忘れないでくださいね。

Composer なんて使いたくない、という方は https://github.com/chinpei215/cakephp-pretty-debug/releases から zip を落とすこともできます。解凍後、 PrettyDebug というディレクトリー名で plugins または app/Plugin ディレクトリーに配置してください。

### プラグインの有効化
`app/Config/bootstrap.php` 内で PrettyDebug プラグインを有効化してください。

```php:app/Config/bootstrap.php
if (Configure::read('debug') > 0) {
    CakePlugin::load('DebugKit');
    CakePlugin::load('PrettyDebug');
}
```

### コンポーネントの有効化

最後に AppController で DebugKit.Toolbar コンポーネントと一緒に PrettyDebug.PrettyDebug コンポーネントを有効にします [^1]。

```php:app/Controller/AppController.php
public function __construct($request = null, $response = null) {
    if (CakePlugin::loaded('DebugKit')) {
        $this->components[] = 'DebugKit.Toolbar';
        if (CakePlugin::loaded('PrettyDebug')) {
            $this->components[] = 'PrettyDebug.PrettyDebug';
        }
    }
    parent::__construct($request, $response);
}
```

これでインストール完了です。

さっそく、画面を表示してみてください。画面の右下に Cake のアイコンがすました顔で現れるはずです。
![pretty-debug-toolbar-collapse.png](https://qiita-image-store.s3.amazonaws.com/0/107118/833f2fce-99b5-7f72-4f27-51db36c55c9c.png)
CakePHP2 のデバッグツールバーをプリチーにするプラグイン PrettyDebug 。みなさまもぜひ使ってみてください。

[^1]: DebugKit を開発環境でのみ有効にする良い方法が思いつかないんですが、これでいいんですかね？
Amazon Interviews

Amazon is Seattle, Washington based is American electronic commerce and cloud computing multinational company. It was founded by Jeff Bezos on July 5, 1994.
[Prepare Best Interview Questions](https://www.courseya.com/) on Amazon and its services like #AWS, #EC2, #Redshift, #ELB, #VPC, #Lambda, #Dynamodb, #S3, and others.

[Amazon Questions](https://www.onlineinterviewquestions.com/amazon/)
Pythonのリストでクラスのオブジェクトを格納する

<head><meta name="google-site-verification" content="qnXlzvIG390oGYtIu0Vy0wdXcZKcVCLIGyP9dsKVicw" /></head>
##Python のリストにクラスのオブジェクトを入れる
Pythonのリストには，クラスのオブジェクトを入れることができます．
まず，Person というクラスを作ります．

```Python
class Person:
    def __init__(self, name, email):
        self.name = name
        self.email = email
```

そして，TaroとJiroというオブジェクトを作ります．

```Python
Taro = Person("Taro", "Taro@python.com")
Jiro = Person("Jiro", "Jiro@python.com")
```

そして，これらをPerson_infoというリストに格納します．

```Python
Person_info = [Taro, Jiro]
```

そして，リストの内容を表示するコードを書きました．

```Python
for member in Person_info:
    print("Name:", member.name, " Email:", member.email)
```


コード全体は次のようになります．

```Python:Person.py   
class Person:
    def __init__(self, name, email):
        self.name = name
        self.email = email


Taro = Person("Taro", "Taro@python.com")
Jiro = Person("Jiro", "Jiro@python.com")

Person_info = [Taro, Jiro]

for member in Person_info:
    print("Name:", member.name, " Email:", member.email)
``` 

結果，次のように表示されました．

```
$python Person.py
Name: Taro  Email: Taro@python.com
Name: Jiro  Email: Jiro@python.com
```

このように，Pythonのリストは，クラスのオブジェクトを格納することができます．


また，新しいメンバーがやってきてもappend()を使えば対処できます．
Person.pyを次のように書き換えます．

```Python:Person.py    
class Person:
    def __init__(self, name, email):
        self.name = name
        self.email = email


Taro = Person("Taro", "Taro@python.com")
Jiro = Person("Jiro", "Jiro@python.com")

Person_info = [Taro, Jiro]

#Add from here

Saburo = Person("Saburo", "Saburo@python.com")
Person_info.append(Saburo)

#Add until here

for member in Person_info:
    print("Name:", member.name, " Email:", member.email)

```

これを実行すると次のように表示されます．

```
$python Person.py
Name: Taro  Email: Taro@python.com
Name: Jiro  Email: Jiro@python.com
Name: Saburo  Email: Saburo@python.com
```

このように，メンバーが追加されたことが分かりました．

##追記
@shiracamusさんが教えてくださったように，Pythonでは数値，文字列，関数，クラス，メソッドのすべてがオブジェクトとして扱われるため，今回と同様の話を適用することができます．

コメントのように，intクラスについても同様のコードを書くことができます．

```Python
>>> one = int('1')
>>> two = int('2')
>>> number_info = [one, two]
>>> three = int('3')
>>> number_info.append(three)
>>> for number in number_info:
...     print("Number:", number)
...
Number: 1
Number: 2
Number: 3
```



ただ，不変オブジェクトというものもあり，intクラスのオブジェクトはその代表格です．
例えば，先程のPerson.pyのPersonクラスについてはオブジェクトを作成後も内容を変更することができます．

```Python
>>> from Person import Person 
>>> Hanako = Person("Hanako", "oops@python.com")
>>> Hanako.email = "hanako@python.com" #変更できた
```

しかし，[こちらのサイト](http://nihaoshijie.hatenadiary.jp/entry/2016/10/14/234418)を参考にintクラスのオブジェクトで同様のことをすると，

```Python
>>> a = int(1)
>>> a.real #実部
1
>>> a.image #虚部
0
>>> a.real = 100
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: attribute 'real' of 'int' objects is not writable
```
書き換えることができないことが確認できました．つまり，intクラスはPersonクラスと違い，immutableです．
いろんな汎用性の高いショートカット

[選択]
・Ctr+マウスクリック
　複数選択するとき、ここからここまでってやりたいときに使う
・Shift+マウスクリック
　個別で複数選択
　
[移動系]
・Shift+十字キー
細かい移動ができる
Djangoでのアプリ作成

PythonでDjangoアプリケーションを作成する手順の備忘録
※各コマンドはAnaconda Promptで実行

# 環境

```
Microsoft Windows [Version 10.0.17134.407]
Python 3.6.5 :: Anaconda, Inc.
Django 2.1.4
```

# プロジェクトの作成
コマンドラインよりDjangoプロジェクトを作成する。

## Djangoプロジェクトの作成
コマンドでDjangoプロジェクトを作成したいフォルダにcdし、以下のコマンドを実行する。
※[sample]は任意のプロジェクト名

```
django-admin startproject sample
```

## フォルダ構成
プロジェクト作成後のフォルダ階層は以下の通り。

```
sample                         # プロジェクトの入れ物（好きな名前に変更可能）
    │  manage.py               # コマンドラインユーティリティ
    │
    └─sample                   # Python パッケージの名前
            settings.py        # 設定ファイル
            urls.py            # Djangoサイトにおける「目次」
            wsgi.py            # WSGI互換Webサーバーとのエントリーポイント
            __init__.py        # PythonパッケージであることをPythonに知らせる空のファイル
```

## 動作確認

外側のsampleディレクトリにcdし、以下コマンドを実行する。

```
python manage.py runserver
```

```
Performing system checks...

System check identified no issues (0 silenced).

You have 15 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
December 15, 2018 - 15:37:19
Django version 2.1.4, using settings 'sample.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
```

コマンド実行後、上記の内容が出力されたらDjango 開発サーバーが起動したことになる。

```
http://localhost:8000/
```

に接続すると以下の画面が表示される。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/187508/c53aafb0-602f-5c0e-5f0a-1682336c6765.png)

# アプリケーションの作成

アプリケーションを作成する際は、「manage.py」と同じディレクトリにcdし、以下コマンドを実行する。
※[polls]は任意のアプリケーション名

```
python manage.py startapp polls
```

コマンド実行後、pollsディレクトリが作成される。
ディレクトリ構造は以下の通りとなる。

```
polls
  │  admin.py
  │  apps.py
  │  models.py
  │  tests.py
  │  views.py
  │  __init__.py
  │
  └─migrations
          __init__.py
```

## ビューの作成
polls/views.pyを開いて、以下のPythonコードを記述する。

```python:views.py
from django.http import HttpResponse


def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")
```

## URLconfの作成
ビューを呼ぶためにURLを対応付けする必要があり、そのためにURLconfが必要になる。

pollsディレクトリにURLconfを作るにはurls.pyを作成する。

```python:polls/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name = 'index'),
]
```

## ルートのURLconfへの反映
polls.urlsモジュールの記述をルートのURLconfに反映する。
sample/urls.pyにdjango.urls.includeのimportを追加して、urlpatternsのリストにinclude()を挿入する。

```python:sample/urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
    path('admin/', admin.site.urls),
]
```

include()関数は他のURLconfへの参照ができる。
これでindexビューをURLconfに紐付けができた。
開発サーバーを起動して、確認する。

```
python manage.py runserver
```

サーバー起動後以下にアクセスする。

```
http://localhost:8000/polls/
```

"Hello, world. You're at the polls index."が表示されている。

# 最後に
Anacondaをインストールしていたため、Anaconda Prompt上での作業なった。
OSはWindows 10だが、Anaconda Prompt上でWindows用のコマンドを実行すると、エラーになるので注意。

参考URL：https://docs.djangoproject.com/ja/2.1/intro/tutorial01/
react(nativeでない)でカメラを使ってみる

reactでカメラが使える「[react-webcam](https://github.com/mozmorris/react-webcam)」の簡単な紹介です。
[ここ](https://codepen.io/ozota/pen/NeqeBm/)にサンプルを作ってみました。スマホで見るとカメラ機能が試せます。
(Qiita記事へのcodepen埋め込みはカメラにアクセスできないようなので埋め込み断念しました。)

* サンプルでは次を実装しています
  * 撮影機能
  * 撮影結果の表示
  * カメラ切り替え（画面側、背面側の切り替え）


# 使い方
```javascript
class MyComponent extends React.Component {
...
  setRef = webcam => {
    this.webcam = webcam;
  }
  capture = () => {
    const img = this.webcam.getScreenshot()
    ...
  }
...
  render(){ 
  return (<Webcam
    audio={false}
    style={styles.camera}
    ref={this.setRef}
    screenshotFormat="image/jpeg"
    videoConstraints={{
     facingMode: this.state.isFacingModeUser ? "user" : "environment"
    }}
    onUserMediaError={() => window.alert('cant access your camera')}
  />)
}
```
* Webcamコンポーネントを配置すればカメラの画像を映し出してくれます。
* refでwebcamオブジェクトを受け取って保存しておきます。
  * 写真を撮るとき等は、webcamオブジェクトの`getScreenshot`を呼び出せば画像を取得できます。上記コードだと`capture`メソッドをボタンの`onClick`に指定すれば撮影ボタンが作れます。
    * `getScreenshot`の戻り値を imgタグのsrcに指定すれば撮った画像を表示できます
* `facingMode`: `"user"`を指定するとスマホの画面側のカメラ、`"environment"`だとスマホの背面側のカメラを使用します
* その他細かい内容は[マニュアル](https://github.com/mozmorris/react-webcam)を見てください（逃げ）

# うまくいかなかったところ
* カメラのキャプチャ画面上に撮影用の:camera_with_flash:等のボタンを配置するのが大変でした。
  * Webcamコンポーネントがレンダリングされると、videoエレメントと外側のdivエレメントが作成されます
  * Webcamに被せるようにボタンを配置しても、外側のdivに重なる形になってしまい、実際に目に見えるキャプチャ画面とずれてました
          * ![image.png](https://qiita-image-store.s3.amazonaws.com/0/304012/78fcf0f2-53d9-dc60-264a-18f54bb4e0db.png)
  * CSS力不足でうまい方法が思いつかず、結局divとvideoを同じサイズ指定して回避しています。指定サイズに合わない解像度のカメラだと表示がずれてると思います。

* カメラのfacingMode切り替えボタンが初回の1タップ時のみ動作しない
  * 初回のみ切り替えボタン動作せず、2回目から動作します 
  * 原因分かりませんでした。私の書き方が悪いだけかもしれません
  * componentDidMountでわざと切り替えを1回発生させて、ユーザーがボタンを押す時が2回目になるようにして回避しました
JavaFXでローディング画像を表示したあと別の画像を表示する

# 概要
JavaFXでなにか処理を始めたらロードしている画像を表示し、
処理が完了したら処理結果を表す別の画像を表示するサンプルプログラムです。

![demo.gif](https://qiita-image-store.s3.amazonaws.com/0/182261/94ef01d9-9303-54ee-f362-db1a355bfcbb.gif)
↑はボタンを押して処理を始め、3秒後に処理が終わり、処理結果が成功だったというサンプルです。


どこかのプログラムを参考したのですが、それを忘れてしまったのと以前探すのに結構時間がかかったため書いておきます。

コード全体は[GitHub](https://github.com/s1r-J/LoadingImage)に置きました。

# 環境
- Windows10
- Java10(Java8でも動くはず)

# 説明

ボタンを押すとまずローディング画像（くるくる回っている画像）が表示させます。

```Java:SampleController.java
// set loading image
this.image.setImage(new Image(getClass().getResourceAsStream("/images/loader.gif")));
```

その後、何かしらの処理（今回は3秒待つ処理）を始めさせます。

```Java:SampleController.java
Thread t = new Thread(() -> {
　　　　try {
　　　　　　　　// wait 3 seconds
	      Thread.sleep(3000);
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
...
```

さらに処理が終わったあとの処理（結果を表す青丸の画像の表示）を書きます。

```Java:SampleController.java
...
Platform.runLater(() -> {
	// after finishing some processes
	// set result image
	this.image.setImage(new Image(getClass().getResourceAsStream("/images/maru.png")));
	});
});
```

# 注意
スレッドを利用しているため、処理によっては例外が発生することがあるので、
適宜対処してください。
Django初心者の忘備録2(Applicationの作成〜Viewの作成まで)

#環境 & 目的
前回の記事と同様
[Django初心者の忘備録](https://qiita.com/Soichi888/items/2d5369a3929c9ae0dbd6)

#Applicationの作成
Projectの作成とサーバーの動作の確認が終わったら、次はApplicationを作成する。
その前にApplicationとProjectの違いはDjangoチュートリアルの説明によると以下の様。
<details><summary>プロジェクトとアプリケーション</summary>
プロジェクトとアプリケーションの違いとは何でしょうか？アプリケーションとは、実際に何らかの処理を行う Web アプリケーションを指します。例えばブログシステムや公開レコードのデータベース、単純な投票アプリといった具合です。プロジェクトとは、あるウェブサイト向けに設定とアプリケーションを集めたものです。一つのプロジェクトには複数のアプリケーションを入れられ ます。また、一つのアプリケーションは複数のプロジェクトで使えます。(Djangoチュートリアルより引用)
</details>
要は単一もしくは複数のアプリケーション＋諸々の動作の設定などをまとめたものが”プロジェクト”という事だろう。
という事で、Applicationの作成は以下のコマンドを実行すれば良い。

``` 
  $ python manage.py startapp Application名
```
ちなみに、この時点でのWebアプリケーション全体のディレクトリは以下の様。

<pre>
- your_project_name/
    - manage.py
    - your_application_name/
        - __pycache__/
        - migrations/
        - __init__.py
        - admin.py
        - apps.py
        - models.py
        - tests.py
        - views.py
    - your_project_name/ 
        - ___init___.py
        - settings.py
        - urls.py
        - wsgi.py
</pre>

#Viewの作成
Applicationの作成が終わったらViewの作成をする。
個人的に一番混乱したのはViewである。理由は至って単純で、View＝外観つまり、ページのデザインチックなものを書くものだと思っていたからだ。
単純に言ってしまえばViewはデータベースから取ってきたデータをどの様に表示するかという事などを決めるところみたいな理解でいいと思う。(もちろん、初心者大体の理解なので悪しからず。異論反論大歓迎)
閑話休題。
your_application_name/views.pyを開いて以下のコードを書き足す。

```python:your_application_name/views.py
from django.http import HttpResponse
   
def index(request):
   return HttpResponse("This is index page on your application.")
```

コードを書き足したら、次にViewを呼ぶためにURLの関連付けるをする。まずはApplicationのディレクトリにurls.pyというファイルを作成する。作成したら以下のコードを書いていく。

```python:your_applicaion_name/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
]
```
Application内での関連付けが完了したので、次はProjectのurls.pyにApplicaitonのurls.pyを関連付けしていく。

```python:your_project_name/urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('your_application_name/', include('your_application_name.urls')),
　　 #path内の'your_application_name'は'/'でもOK
    path('admin/', admin.site.urls),
]
```
*include()など他の関数も知りたいという方はチュートリアルを参照してください。

この時点でのWebアプリケーション全体のディレクトリは以下の様。

<pre>
- your_project_name/
    - manage.py
    - your_application_name/
        - __pycache__/
        - migrations/
        - __init__.py
        - admin.py
        - apps.py
        - models.py
        - tests.py
        - views.py
        - urls.py
    - your_project_name/ 
        - ___init___.py
        - settings.py
        - urls.py
        - wsgi.py
</pre>

モデルまで書こうと思ったけど、思いのほか長くなってしまったのでModelは次の記事で。
とりあえず、今日はここまで
尊師スタイルはいいぞ！という話。

# tl;dr

HHKBで尊師スタイルというのはRMS御大のコーディングまたはラップトップ利用スタイルに影響を受けて命名されたスタイルだが、
実際使ってみると結構捗るのである。
みんなも尊師スタイルで開発してみてくれよな！！


# Keyboard
- HHKB Pro2 US

    やっぱりキーボードといえばこれなんじゃないでしょうか。
市販品系のキーボードではリアフォに並ぶ最高級ラインの静電容量無接点スイッチ。
色々な理由を挙げてこのキーボードをお勧めする声がありますが、
個人的には"小さくて"、"軽くて"、"シンプル"なところが強みだと思って使っています。
BTではなく有線を選んでいる理由は入力の確実性を高めたりバッテリー切れなどで使えない事態を回避するためです。
なんだかんだで有線が確実性が高いんだよ！みたいなの、まだまだ結構ありますよね。
Apple信者なのでAirPodsを使い有線でのLAN接続もしなくなりましたがHHKBはBTだとチャタるとか、
BTのバッテリー残量とかをいい感じにモニタリングできない上に有線無線両対応じゃないとかあり有線を使ってます。


### 配列の話を少し

大きな話でいうとJIS or US の対立項は割と大きな争いだと思います。
Macユーザーなので、USを選ぶには常にCTOが必須になりPayPayキャンペーンに乗っかれないとか、
量販店ポイントで割引が効かないなどありますが、それでもUSの方がエンジニア向きというか自分向きの配列だと感じて使ってます。
USを推す理由は大きく以下の３点で

- 世界中のアップルストアでサポート受けられて、在庫がある（であろう）調達の容易さ
- ホームポジションの位置がJISに比べると中央寄りのため正対して長時間使用した際に体への負担が少ない。
- そもそもかな入力をしないので、かな入力に最適化されたJISキーが必要ない

という感じで、ローマ字打ちで海外に行くときもパソコン持ち出してしかも日がな一日パソコンを使いっぱなしもよくある。みたいなライフスタイルだとこれが一番だなという感じです。
あとは、実質Appleのリファレンスとも言える設定がUSキー端末にOSの言語設定が英語っていう状態なので、過度に自分に最適化した環境を作ってしまうとそれ以外の環境で大きくパフォーマンスが下がる。みたいな事態を懸念してあまり左右別体とか、独自配列とかには手を出さないようにしています。

# Accessory

尊師スタイルするうえであると良いアクセサリーがキーボードブリッジです。
PCによってはなくても尊師スタイルできますし、デスクトップ勢にはもはや必要ないものですが、
個人的には基本使うことをお勧めしたいです。キーボードを安定しておくことができると、それだけでタイピングがしっかりします。
自分は割高と知っっていてバード電子のキーボードブリッジを購入しましたが、自作してオリジナルで剛性のたかいキーボードブリッジを作る楽しみなどもあるなと思います。

# Mouse

Macのトラックパッドの出来がいいので特にマウスは使いません。
ホームポジションからの手の移動が最小になる位置にラップトップのトラックパッドがついているので、
マウスを取り入れることはないかなと考えています。
強いていうとMX-Masterはすごくいいマウスだったのでマウスを使うのであればそれを選ぶかもしれません。



# Coffee

特にこだわりはないですが、
コーヒーを飲むときはブラックが多いです。
ブレンディのインスタントペーパードリップのレギュラーコーヒーがなんとも普通という感じで好きです。
砂糖とミルクを入れるくらいならグリコのカフェオレとか森永のコーヒー牛乳とかを買う派。
コーヒー以外にも、ハーブティーや紅茶を淹れることもありますが、
基本ティーバッグタイプのインスタントなものです。
マグカップが10年以上前のものを使っているので、
そろそろ新しいマグカップのいい感じのやつを探していたりします。

自宅以外での作業時にはおなじみのスタバやコンビニコーヒー、ペットボトルコーヒーなどを普通に飲んでいますが、
ブラックコーヒーはブレンディのペーパードリップのインスタントが好きなのでブラック以外を買うことが多いです。


# まとめ

尊師スタイルは最高です。
ラップトップのキーボードで1日８時間も10時間もタイピングしまくるのはそれなりに辛いなか、
キーボードをラップトップの上に乗せることでいいキーボードをラップトップで使うことができます。
また、HHKB+13インチ以上のMacの場合、膝の上でも、カフェの机の上でも、自分のデスクでも常に同じ開発体験ができます。
ノートパソコンで開発をしていて、外部キーボードをつかっているのなら尊師スタイルをしない理由はないのではないでしょうか。
同じフットプリントの空間占有のなかでは最高の質の構成が尊師スタイルだと信じて疑わないため、
是非みなさんも尊師スタイルを試して尊師スタイル沼にはまっていただきたいです。
【アウトプット】HTMLとCSSの基礎についての学習

【目的】
HTMLとCSSについて知識が皆無に等しいので、理解したことをここにアウトプットすることで理解を深める
【実施内容】
スラスラわかるCSSのデザインのきほんをもとに理解したことをまとめていく
わからないとこのみかな
【いざ実施】
#一章：WebとHTML
・画像の表示方法
　imgタグを用いる。
　src属性：画像のパスを記述する。
　→相対パスと絶対パス
　→基本相対パス。相対パスは、現在のフォルダから目的のファイルまでの道のりを記述したもの。
　alt属性：画像の説明を記述する。
　width属性：画像の幅を指定する。
　height属性：画像の縦を指定する。
　-画像フォーマット
　　・jpeg:標準的な画像フォーマット。べた塗りとかの画像には向いていない
　　・gif:容量を抑えるために、使える色彩を限定したもの
　　・png:一番容量を食う。どっちのフォーマットにも対応できる。
#二章：CSSの基本
・idセレクタ
　htmlのタグについているid属性（id=hoge）で要素を選択するセレクタ
　cssとしては（#hoge{宣言}）の形式で記述
・classセレクタ
　htmlタグについているclass属性（class=hoge）で要素を選択するセレクタ
　cssとしては（.hoge{宣言}）の形式で記述
・疑似クラス
　状態に対して装飾を行うこと
　a:hoverセレクタはaタグにマウスが重なっている状態を表せ、その状態の時の装飾を宣言できる
・font-familyプロパティ
　そのページのフォントを定義するもの
#三章：ボックスモデル
https://nulab-inc.com/ja/blog/nulab/css-basics-for-engineer-boxmodel/
→要素の領域の編集にあたるkey：marginとpadding
・背景画像の挿入方法
　cssのbackground-imageセレクタに:url(パス情報)で指定した領域に対して背景画像が埋め込める
・ボーダーラインの記述方法
　定義すべき項目：色　太さ　線の形状→solid（実線など）
・テーブルの記述方法
　callapse:テーブルボーダーが一重であること。
　separate:テーブルボーダーが二重で引かれること。
　tr td:first-child:テーブルの最初の要素にマッチする
#四章：フロート・ポジションについて
・フロート：ある要素にfloatを設定（ex float:left）すると、その要素は文要素のボックス内でできるだけ左に配置しようとする。つまり横並びの表現が可能
・ポジション：ボックスの位置を座標で指定して配置するための機能。
　absolute:rerativeで定義された親ボックスからの座標位置をしていることでその位置に配置できる。
　→absolute指定で文字が重なるのは、浮かせているから。論理的に他の要素からこの要素が見えなくなているから次の要素が詰められて重なる
OculusGoでFirebaseを使う (Authentication, RealtimeDatabase)

# 概要

Firebase Unity SDK は GooglePlay 開発者サービスに依存しており、OculusGo で利用することが出来ない。
しかし、REST API を利用することで OculusGo でも Firebase が利用可能である。

この記事では、OculusGo から Authentication と RealtimeDatabase を使う方法をまとめる。
(ソースコードで `Debug.Log` を使っているが、実機での検証も済んでいる)

スライド作りました。
[Firebase + UniVRM + OculusGo で VRM をランタイムロード - Speaker Deck](https://speakerdeck.com/kawashi/firebase-plus-univrm-plus-oculusgo-de-vrm-worantaimurodo?slide=45)

# 前準備

Firebase でプロジェクトを作って、Authentication と RealtimeDatabase を有効にしておく。
プラットフォームは web を選択して、APIキーと RealtimeDatabase の URL を取得しておく。

# Authentication

[Firebase Auth REST API  |  Firebase](https://firebase.google.com/docs/reference/rest/auth/) にある API を利用。
例えば、Email と Psassword でサインインする場合は下記のようになる。

```csharp
	void Start () {
		StartCoroutine(SignIn());
	}

	IEnumerator SignIn() {
		WWWForm form = new WWWForm();
		form.AddField("email", "a@example.com");
		form.AddField("password", "testtest");
		
		var url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=[APIキー]";
		
		UnityWebRequest www = UnityWebRequest.Post(url, form);
		yield return www.SendWebRequest();
		
		if(www.isNetworkError || www.isHttpError) {
			Debug.Log("失敗");
			Debug.Log(www.responseCode);
			Debug.Log(www.error);
		} else {
			Debug.Log("成功");
			Debug.Log(www.responseCode);
			Debug.Log(www.downloadHandler.text);
		}
	}
```

# RealtimeDatabase

[Simple Firebase Unity (for Realtime-Database) - Asset Store](https://assetstore.unity.com/packages/tools/network/simple-firebase-unity-for-realtime-database-58337) を利用すると楽。
Firebaseのリファレンスは [データの取得  |  Firebase](https://firebase.google.com/docs/database/rest/retrieve-data) あたりが参考になりそう。

```csharp
	void Start ()
	{
		// 初期化
		var firebase = Firebase.CreateNew("https://[RealtimeDatabaseのURL].firebaseio.com/");
		
		// データ追加(Pushの第二引数はデータがJSONの場合はtrueにする)
		firebase.Child("OculusGo").Push("{ \"message\": \"Hello!\"}", true);

		// データ取得時のコールバック設定
		firebase.OnGetSuccess += GetOKHandler;
		firebase.OnGetFailed += GetFailHandler;
		
		// データ取得 (Childの第二引数をtrueにしないと親で設定したコールバックが走らない)
		firebase.Child("OculusGo", true).GetValue("print=pretty");
	}

	void GetOKHandler(Firebase sender, DataSnapshot snapshot)
	{
		Debug.Log("成功");
		Debug.Log(snapshot.RawJson);
	}

	void GetFailHandler(Firebase sender, FirebaseError err)
	{
		Debug.Log("失敗");
		Debug.Log(err.Message);
	}
```

# まとめ

雑なコードとまともな解説が無くてごめんなさい。
ただ、OculusGo でも Firebase は使えるよという事を広めたかったので書きました。
もっと良い方法がありましたら是非コメントで教えて頂けると嬉しいです。

それにしても OculusGo はまだまだ記事が少ないですよね。
こんな感じな些細な記事でも良いので、もっと増えることを祈ってます🙏
Raspberry Piで作ったメール通知される玄関の呼び出しブザー

# 概要
呼び出しブザーと書いているがメールを飛ばすのみ

# 環境
python3.7.0
raspbian9.4
Raspberry Pi B+

# 回路
GPIO25及びGNDにそれぞれジャンパーを接続。（ピン名がGPIOxx（で抵抗なしなら）25番以外でもOK）
ジャンパーをリード線に繋げ玄関まで引っ張る。
玄関に引っ張ったリード線にプッシュ式のスイッチをつける。（ものがなかったので[選択バサミ](https://bouldering-climbing.kyoto/blog/?p=134)で代用）

と、プッシュ式のスイッチon/offのみとシンプル構成。
リード線を10m程度曳き回しているので、ノイズ(静電気？)を拾ってそのままだと誤検知をしてしまう。
回路側で処理するのは知識が不足しているのでプログラムで対処している。

# プログラム
スイッチのonを検知してメールを飛ばすのみ

## スイッチon部分  
GPIO.wait_for_edge(pin,GPIO.FALLING)で押された時を検知。
ただし、ノイズを拾ってしまう時があるの。静電気だと一瞬なので0.1秒待ってまだ押されているかを確認している。
確認後visitmail()という関数でメールを飛ばしている。
その後の60秒スリープはブザー連打されると面倒なための処理。

```
#!/usr/bin/env python3
# coding: utf-8
import time

import RPi.GPIO as GPIO

from mail import visitmail

print("start doorphone moniter")

GPIO.setmode(GPIO.BCM)
pin = 25

GPIO.setup(pin, GPIO.IN,pull_up_down=GPIO.PUD_UP)

try:
    while True:
        GPIO.wait_for_edge(pin,GPIO.FALLING)
        time.sleep(0.1)
        if GPIO.input(pin) == GPIO.LOW:
            visitmail()
        time.sleep(60)

except KeyboardInterrupt:
    print("break")
    GPIO.cleanup()

```

## メール送信部分
単純にメールを飛ばすのみ。メール送信用パスワードだけ環境変数から読み込み
(mail.py) 

```
#!/usr/bin/env python3
# coding: utf-8
import configparser
from datetime import datetime
from email.mime.text import MIMEText
from smtplib import SMTP
import os

def visitmail():
    inifile = configparser.ConfigParser()
    inifile.read('./config.ini', 'UTF-8')

    ini_host = inifile.get('server', 'host')
    ini_port = inifile.get('server', 'port')
    ini_from = inifile.get('mail', 'from')
    ini_to = inifile.get('mail', 'to')
    ini_title = inifile.get('mail', 'title')

    with SMTP(host=ini_host, port=ini_port) as smtp:
        smtp.starttls()
        smtp.login(
                user = ini_from,
                password = os.environ['MAIL_PASSWORD'],
                )
        msg = MIMEText(datetime.now().strftime("%Y/%m/%d %H:%M:%S"))
        msg['Subject'] = ini_title
        msg['To'] = ini_to
        msg['From'] = ini_from

        smtp.send_message(
                from_addr = ini_from,
                to_addrs = ini_to.split(','),
                msg = msg,
                )  
```  

(config.ini)

```
[server]
host = mail.hoge.co.jp
port = 587

[mail]
from = kitamura@hoge.co.jp
to = kitamura@hoge.co.jp,keitaiaddr@ezweb.ne.jp
title = 呼出ブザーが押されました

```

# 追記
停止処理でバグを踏んだので[こちら](https://www.rocher.kyoto.jp/arbr/?p=1455)に修正した箇所も入っているソースをのせました。
【設計時の見落とし】請求処理系で指摘されたこと

# はじめに
これは[設計時の見落とし Advent Calendar 2018](https://qiita.com/advent-calendar/2018/overlook)の15日目の記事となります。

業務アプリケーションの設計をするときに、見落としがちなところに焦点をあてて紹介します。 
下流工程からの手戻りを少なくして 双方の負担を減らしましょう。

過去に請求処理機能を作成した際に指摘された3点を挙げてみました。

# 複数締日の設定
取引条件は顧客によって異なります。
月末締めの企業が多いと思いますが、5日、10日、15日、20日など別の日を締日としている会社も存在します。
また、締日は通常は1取引先で締日は1つですが、取引先によっては「15日締翌月末現金払い、月末締め翌々月10日払い」などというように1ヶ月に複数回締日のあるところもあります。

10日締め、20日締め、月末締めというように3回締日のある企業も存在することも考慮して、取引先マスタメンテナンスでは締日項目を3つ用意してあります。

画面レイアウト上でも、3つの数値入力を用意し、末日は31と設定して1～31の範囲チェックといずれか1つは必須入力とするようなチェック処理が仕様として記述されており、プログラムも仕様通り作成されました。

その後、設定した締日を使って処理する請求処理系の機能を製造するにあたりプログラマー側から問題提起がありました。

## 問題提起
3番目のみ入力されているとか、1番目と3番目で入力されているとか、10、5、15など昇順に並んでいないとかがあると処理が面倒になる。
3つの項目が順番通りに入っていることを保証してほしい。

## 対応
確かに締日に3つの項目の並びには特定の意味は無いわけですから、取引先マスタメンテナンス上にて空きのチェックや昇順にセットするようにチェック仕様を追加し、修正することとなりました。

**締日に限らず複数項目がある場合、並びや空き入力なども考慮をしてチェックしなくても問題ないのかまで意識して仕様書を作成しましょう。**

# 範囲指定と個別指定
請求書を発行する機能があり、その設計書には締日と請求先コードの範囲指定として開始コードと終了コードの入力項目がありました。

その設計書の画面レイアウトを見た営業兼SEの方が仰りました。
「お客さんによっては他のところより早めに請求書を要求してしてくるところがある、特に大きい会社など。範囲指定ではなく請求先一覧を表示し、チェックオンした請求先の請求書を発行するようにしたい。」 ということで、設計書の見直しが行われました。

このようなことがあるので請求書の発行機能に限らず、**安易に範囲指定で済ませていいのかどうか**、ユーザーとの検討が必要ではないでしょうか。

# 履歴持ちマスタの参照
社員マスタなど過去の情報も保持しておくために改定日をキーに含め履歴を持つようにしてあります。

例　社員00001が結婚して9/16から姓が変更した場合

|社員ID|改定日FROM|改定日TO|名前|
|:--|:--|:--|:--|
|00001|20050401|20080915|鈴木　花子|
|00001|20080916|99999999|佐藤　花子|

※最終履歴の場合は、改定日TOの項目に99999999をセット

請求年月を参照してデータ出力する項目には社員コードがあり、社員マスタを参照して社員名をセットするようになっておりました。

## 問い合わせ
稼動から数ヶ月経って、ユーザーからエラーでデータ出力が出来ないとの問い合わせがありました。
データチェックの中に社員名が未セットならエラーとなるように仕組んでいたのですが、どうやらそのエラーにひっかかり出力できていなかったのです。

## 原因
原因を調査すると、データ上の社員が途中入社で改定日が2018/08/04で登録されている場合に発生することが分かりました。
実は、仕様書に「請求年月+1」としてから、社員マスタのデータを抽出するようになっており、請求年月が2018/08の場合、2018/08/01が条件となります。(日付は数値型として年月日の8桁で登録されている)

```sql:SQLのWHERE条件
請求年月+1 BETWEEN 改定日FROM AND 改定日TO
20081801  BETWEEN 20081804   AND 99999999
```

「請求年月+1」としていた為に、途中入社の場合に抽出条件から外れてしまっていたのです。他の途中入社の方が今まで引っかからなかったのは、単純に過去入社だったからです。

## 対応
修正対応としては、履歴の先頭の改定日FROMを強制的に1日になるような社員マスタのビューを作成して、そのビューを参照させるようにしました。

## 雑感
社員名が空になるのさえ防げればいいとのことで直近の日にして抽出するようにとの指示でそうしたけれど、だったら年月だけで比較した方が簡単だったかも･･･

そもそも「請求年月+1」としている仕様の時点で整合性としてよく無かったですね。
anacondaのjupyter notebookからmecabを使うまでの手順

# mecab本体のインストール
ここにアクセスしてzipファイルをダウンロード&解凍
`https://files.pythonhosted.org/packages/ac/48/295efe525df40cbc2173748eb869290e81a57e835bc41f6d3834fc5dad5f/mecab-python3-0.996.1.tar.gz`


# mecabで使用する辞書をダウンロード

`$ brew install mecab-ipadic`

# 一応ターミナルで使えるか確認

`$ mecab`でmecabを起動して文を入力

```
ロイヤルミルクティーはミルクティーよりもカロリーが高い

ロイヤルミルクティー	名詞,一般,*,*,*,*,*
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
ミルク	名詞,一般,*,*,*,*,ミルク,ミルク,ミルク
ティー	名詞,一般,*,*,*,*,ティー,ティー,ティー
より	助詞,格助詞,一般,*,*,*,より,ヨリ,ヨリ
も	助詞,係助詞,*,*,*,*,も,モ,モ
カロリー	名詞,一般,*,*,*,*,カロリー,カロリー,カロリー
が	助詞,格助詞,一般,*,*,*,が,ガ,ガ
高い	形容詞,自立,*,*,形容詞・アウオ段,基本形,高い,タカイ,タカイ
```

使えたので次にpythonから使えるようにする
# pythonでも使えるようにバインド

そのままpipインストールしようとすると`unable to execute 'swig': No such file or directory`が出るので先にswigをインストール

`$ conda install -c anaconda swig`

その後
`$ pip install mecab-python3`


# pythonで使えるか確認


```

$ python
>>> import MeCab
>>> mecab = MeCab.Tagger("-Ochasen")
>>> print(mecab.parse("ロイヤルミルクティーはミルクティーよりもカロリーが高い"))
ロイヤルミルクティー	ロイヤルミルクティー	ロイヤルミルクティー	名詞-一般
は	ハ	は	助詞-係助詞
ミルク	ミルク	ミルク	名詞-一般
ティー	ティー	ティー	名詞-一般
より	ヨリ	より	助詞-格助詞-一般
も	モ	も	助詞-係助詞
カロリー	カロリー	カロリー	名詞-一般
が	ガ	が	助詞-格助詞-一般
高い	タカイ	高い	形容詞-自立	形容詞・アウオ段	基本形
EOS
```

# jupyter notebook で使用する
任意の`.ipynb`ファイルに行き、
以下のコマンドを実行
先頭の!を忘れずに

`$ !pip install mecab-python3`

```
Requirement already satisfied: mecab-python3 in /anaconda3/lib/python3.6/site-packages (0.996.1)
```

（Requirement already satisfiedと書いてあるのでやらなくてよかったかもしれないが...）

とりあえずこれでjupyter notebookからmecabをimportして使用できるようになる
git の文字化け

# git diff での日本語の文字化け

## Overview
git diff の出力に日本語が含まれているときに、下記のように２桁の数値ばかりの表示に文字化けしてしまうことがあります。

```bash

$ git diff
diff --git a/README.txt b/README.txt
index 0005c4e..5d6ea9c 100644
--- a/README.txt
+++ b/README.txt
@@ -1 +1 @@
-<E3><81><82><E3><81><84><E3><81><86><E3><81><88><E3><81><8A>
+<E3><81><8B><E3><81><8D><E3><81><8F><E3><81><91><E3><81><93>
このような場合は、ページャの設定 (core.pager) で下記のように LESSCHARSET を設定するようにします。
```

```bash

$ git config --global core.pager "LESSCHARSET=utf-8 less"
あるいは、システムの環境変数で Git のページャ設定を行っておくこともできます。

~/.bash_profile
export GIT_PAGER="LESSCHARSET=utf-8 less"
```

これで正しく日本語の差分が表示されるようになります。

```bash

$ git diff
diff --git a/README.txt b/README.txt
index 0005c4e..5d6ea9c 100644
--- a/README.txt
+++ b/README.txt
@@ -1 +1 @@
-あいうえお
+かきくけこ
git status
git status の表示で、日本語のファイル名が下記のように文字化けしてしまうことがあります。
```

```bash
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        "\343\201\202\343\201\202\343\201\202.txt"
```

nothing added to commit but untracked files present (use "git add" to track)
このような場合は、下記のように core.quotepath 設定を false に設定します。

$ git config --global core.quotepath false
これで正しく日本語のファイル名が表示されるようになります。

```bash
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        あああ.txt
```

nothing added to commit but untracked files present (use "git add" to track)
設定の確認と削除
上記で設定した値を確認するには下記のようにします。

```bash
$ git config --global --list
core.pager=LESSCHARSET=utf-8 less
core.quotepath=false
```

設定した値をクリアするには下記のようにします。

```bash
$ git config --global --unset core.pager
$ git config --global --unset core.quotepath
```

下記より引用

完コピしましたありがとうございます。
https://maku77.github.io/git/settings/garbling.html
正規表現のテストツールリンク集


# Webで正規表現テスト

**RegexPlanet**
いろんな言語に対応していて、各種フラグもちゃんと効くみたいです。
テストツールということを考慮しているのか、複数の入力値を入れれる。
[RegexPlanet - Online Regular Expression (Regex) Testing and Cookbook for: Go, Haskell, Java, JavaScript, .Net, Perl, PHP, PostgreSQL, Python, Ruby, Tcl & XRegExp ](http://www.regexplanet.com/)

**正規表現チェッカー PHP**
PHPerの人の定番？PHPのpreg_matchとJavaScriptのmatchが同時にテストできます。
[正規表現チェッカー PHP: preg_match() / JavaScript: match() ](http://okumocchi.jp/php/re.php)

**Online regex tester and debugger**
Regexのデバッグまでできます！ReDoS対策で正規表現のパフォーマンスを見たい場合に使えます。
[Online regex tester and debugger: PHP, PCRE, Python, Golang and JavaScript ](https://regex101.com/)

**RegExr**
GitHubと連携して、共有できるサービスです。
[Codepen](https://codepen.io/)の正規表現版みたいな感じですね。
JavaScriptとPCREが選べるんですが、
JavaScriptでやったら、「後読みは全てのブラウザでサポートされてるわけじゃありません」って感じの警告してくれた。
[RegExr: Learn, Build, & Test RegEx ](https://regexr.com/)

**Rex V**
いろんな言語に対応していて、各種フラグもちゃんと効くみたいです。
左下に正規表現のヘルプがついていていいですね。
[Rex V: an AJAX Regular EXpression eValuator - ](http://www.rexv.org/)

**Rubular**
Ruby専用。Rubyのバージョンまで指定できる。
[Rubular: a Ruby regular expression editor and tester ](http://www.rubular.com/)

**RegExp playground**
名前の通り、正規表現で遊ぶサイト。
[RegExp playground ](http://leaverou.github.io/regexplained/)

# 正規表現の可視化
JavaScriptの正規表現に対応しています
[Regexper ](https://regexper.com/)

JavaScript, Python, PCREの正規表現に対応しています
[Debuggex: Online visual regex tester. JavaScript, Python, and PCRE. ](https://www.debuggex.com/)

JavaScriptに対応していて、GETクエリに正規表現入れ込むことでWebサイトに埋め込める。
[Regulex：JavaScript Regular Expression Visualizer ](https://jex.im/regulex/#!flags=&re=%5E(a%7Cb)*%3F%24)

# IntelliJ IDEA

[IntelliJの正規表現書きが捗る機能 - Qiita ](https://qiita.com/yuichielectric/items/89220ee58fa3b34fb57b)

**IntelliJ IDEAのプラグイン**
JavaのFind、Match、Split、Replaceに対応してテストできます。
ignore case、Multiline Mode、Dot All Modeなどのフラグ切り替えもできます。
使ってみた感じ、どちらもUIが違うだけでほぼ同等の機能を提供してるっぽい…。
[RegexPlugin - Plugins | JetBrains ](https://plugins.jetbrains.com/plugin/19-regexplugin)
[RegexpTester - Plugins | JetBrains ](https://plugins.jetbrains.com/plugin/2917-regexptester)
Bitcoinの発行量は無限！？という話

みなさんご存知の通り、Bitcoinの発行量はあらかじめ決まっています。
つまり、発行量がその値に達するとそれ以上新しいコインは発行されなくなります。
もう少し詳しく言うと、新しく発行されるBitcoinの量がおよそ4年ごとに半減していき、最終的に0になるためそれ以上発行されなくなります。

## 発行量を制御しているコード

その辺を制御しているコードがこちらです。

```c++
int64_t nSubsidy = 50 * COIN;
nSubsidy >>= (nHeight / 210000);
```

簡単に解説をします。

まず最初の行で、nSubsidyを初期化しています。
subsidyは補助金や交付金という意味合いなので、nSubsidyはnumber of subsidy、つまり交付金の量という意味です。
これはブロック毎に新しく発行されるBTCの量を表しています。
COINは100000000とdefineされており、これは1BTCあたりのsatoshiの量です。
つまり初期化時のnSubsidyの値は50BTCとなります。

次のコードは、nSubsidyをbitshiftしています。
低レベルな言語ではよく、「2で割る」という演算を「右にbitshiftする」という演算で置き換えます。
右に1bit bitshiftすると1/2になり、2bit bitshiftすると1/4になります。
そして何bit bitshiftするかを決めているのが、(nHeight / 210000)の部分です。
つまり、nHeightが0~209999のときは0bit bitshift、210000~419999のときは1bit bitshiftすることになります。
nHeightが大きくなるたびに、nSubsidyが半減していくのが1行で表されています。

## お分りいただけただろうか

さて、たった2行で発行量の制御を実現しているカッコいいコードですが、このコードに潜むバグに気がつかれた方はいるでしょうか。
気がつかなかった人はもう一度、例のコードを見てみましょう。

### ヒント

上記のコードのどこにバグが潜んでいるのか。
答えは2行目です。

```c++
nSubsidy >== (nHeight / 210000);
```

どうでしょう。気がつきましたか？

### 解説

では解説をしていきます。

nHeightが大きくなっていくと、シフトする量は、0, 1, 2,,,と大きくなっていきます。
では、 **シフト量がnSubsidyのbit長よりも大きくなったらどうなるのでしょうか。**
1行目を見ると、nSubsidyのbit長は64であることがわかります。
64bitで表現されている値を100bit分シフトしたりしたらどうなるのでしょうか。

その答えは、**未定義** です。


未定義ということは、
「64を超えたら何があろうと0になるぜ！」みたいなコンパイラも、
「100を64で割った余りの36bitだけシフトするぜ！」みたいなコンパイラもありえるということです。

そして２つめのようなコンパイラでは、Bitcoinの発行量は以下のようになります。

![inflation.png](https://qiita-image-store.s3.amazonaws.com/0/105977/d921b2fe-809f-5cce-7b89-c5667c128dd1.png)

つまり発行量無限ですね。

## タネ明かし

実はこのバグはSatoshi Nakamotoのオリジナル実装にあったバグで、2014年に修正されています。
現在の実装では、(nHeight / 210000)が64を越えると、シフト量が0になるようになっています。
これでBTCの総発行量はちゃんと有限ですね。
タイトルは、「（Satoshi Nakamotoのオリジナル実装の）Bitcoinの発行量は無限！？」という意味でした。

## 参考リンク
  - https://docs.microsoft.com/en-us/cpp/cpp/left-shift-and-right-shift-operators-input-and-output?view=vs-2017#additional-details
  - https://github.com/bitcoin/bips/blob/master/bip-0042.mediawiki
  - https://github.com/bitcoin/bitcoin/pull/3842
各言語・エディタ・正規表現エンジンの正規表現の仕様リンク集

# IDE・エディタの正規表現の仕様

**IntelliJ IDEA(Jetbrains)**
[正規表現の構文リファレンス - 公式ヘルプ | IntelliJ IDEA ](https://pleiades.io/help/idea/regular-expression-syntax-reference.html)

**Notepad++(PCRE)**
[Regular Expressions - Notepad++ Wiki ](http://docs.notepad-plus-plus.org/index.php/Regular_Expressions)

**Emacs**
公式ドキュメント(英語)
[Regexps - GNU Emacs Manual ](https://www.gnu.org/software/emacs/manual/html_node/emacs/Regexps.html#Regexps)
[Regexp Backslash - GNU Emacs Manual ](https://www.gnu.org/software/emacs/manual/html_node/emacs/Regexp-Backslash.html#Regexp-Backslash)

有志による和訳
[GNU Emacs Lisp Reference Manual - 正規表現のシンタックス ](http://flex.phys.tohoku.ac.jp/texi/eljman/eljman_218.html)

**Vim**
公式ドキュメント
[pattern - Vim Documentation ](https://vim-jp.org/vimdoc-en/pattern.html)
[pattern - Vim日本語ドキュメント ](https://vim-jp.org/vimdoc-ja/pattern.html)

整理したQiita記事
[vim正規表現リファレンス - Qiita ](https://qiita.com/kawaz/items/d0708a4ab08e572f38f3)

# 言語毎の正規表現の仕様

**Ruby**
[正規表現（Ruby 2.5.0）](https://docs.ruby-lang.org/ja/2.5.0/doc/spec=2fregexp.html)

**Python3**
[6.2. re — 正規表現操作 — Python 3.6.5 ドキュメント ](https://docs.python.jp/3/library/re.html)

**Java**
[Pattern (Java Platform SE 8 ) ](https://docs.oracle.com/javase/jp/8/docs/api/java/util/regex/Pattern.html)

**JavaScript**
[JavaScript RegExp Reference ](https://www.w3schools.com/jsref/jsref_obj_regexp.asp)
[正規表現 - JavaScript | MDN ](https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions)
ブラウザによって差異があるので注意が必要ですね。
一例を出すと、正規表現の後読みは、Chromeでは対応してるが、FireFoxでは対応してないです(2018年12月現在)。

**PHP**
[PHP: メタ文字 - Manual ](http://php.net/manual/ja/regexp.reference.meta.php)

**Perl**
[perlreref - Perl の正規表現のリファレンス - perldoc.jp ](http://perldoc.jp/docs/perl/5.24.1/perlreref.pod)

**MySQL**
[MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.5.2 正規表現 ](https://dev.mysql.com/doc/refman/5.6/ja/regexp.html)

**PostgreSQL**
[9.7. パターンマッチ ](https://www.postgresql.jp/document/10/html/functions-matching.html)

**Redis**
[全データ型対応の操作 — redis 2.0.3 documentation ](http://redis.shibu.jp/commandreference/alldata.html#command-KEYS)
※`?`,`*`,`[]`しか使えないとの情報あり

# 正規表現エンジン毎の仕様

**[PCRE - Perl Compatible Regular Expressions](http://www.pcre.org/)**
[pcre2syntax man page](http://www.pcre.org/current/doc/html/pcre2syntax.html)（英語）

**[Onigmo（鬼雲）](https://github.com/k-takata/Onigmo)**
[RE.ja](https://github.com/k-takata/Onigmo/blob/master/doc/RE.ja)

**[RE2](https://github.com/google/re2)**（Google 製）
[Syntax](https://github.com/google/re2/wiki/Syntax)（英語）

**[Rust の regex クレート](https://crates.io/crates/regex)**
[Syntax](https://docs.rs/regex/1.1.0/regex/#syntax)（英語）

<b><font color="green">編集リクエストで他言語・エディタの正規表現リンク追記歓迎です</font><b>:grinning:
クラウド環境の仮想マシンにディスクを追加する（GCP）


# 概要

GCE(ComputeEngine)にディスクを後から追加する必要があったので、そのときのメモ。

# 環境

* GCPのGCE
* Debian GNU/Linux 9


# 手順
## 現状確認

```
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            1.8G     0  1.8G   0% /dev
tmpfs           371M  6.4M  365M   2% /run
/dev/sda1       9.8G  1.2G  8.2G  13% /
tmpfs           1.9G     0  1.9G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
```

## ディスク追加

WebUIから追加

## ディスクのフォーマットとマウント

追加されたディスクをここでは/dev/sdbとする。

マウントポイントを作成する。

```
$ sudo su -
# mkdir /data
```

フォーマットとマウント。

```
$ sudo su -
# mkfs -t ext4 /dev/sdb
# mount /dev/sdb /data
```

# 確認

```
# df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            1.8G     0  1.8G   0% /dev
tmpfs           371M  6.4M  365M   2% /run
/dev/sda1       9.8G  1.2G  8.2G  13% /
tmpfs           1.9G     0  1.9G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/sdb        196G   61M  186G   1% /data
```

##  マウントの永続化

再起動後もマウントしてほしい場合は、設定する。

```text:/etc/fstab
# 下記の行を追加
/dev/sdb /data ext4 defaults 1 2
```

fstabのオプションは、[ここ](https://wiki.archlinux.jp/index.php/Fstab)を参照。
息子が面白いので自分しか癒やされないLINEBot作った

[クソアプリ2 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/kuso-app2) 18日目の記事です。

アドベントカレンダー初心者のgohh56です。
input主体だったのをoutput主体にしたいと思い、なんの準備もなく、アドベントカレンダーやる！というアドベントカレンダー駆動で開発してみました。

個人開発経験があまりないときに作ったものを晒そうとすると敷居が高いですが、クソアプリなら多少どうしようもないものでもきっと大丈夫！と思い、やろうやろうと思っていてやっていなかったちょっとしたことをやってみました。

# 開発動機

- 4歳の息子がいます。仕事している最中に息子の行動を思い出すとくすっとできるので自分の癒やしのためにbotを作ってみようと思いました。そのため、なんら現実世界でのバックグラウンドとして我が息子の行動を知らないとなんの癒やしにもなんのためにもなりません。（ご注意）
- そもそもBOT開発には興味があったのでやってみました。
- そもそもサーバレスに興味があったのでやってみました。
- Python勉強してきたからPythonで書きたい。

# 作ったもの

<img width="374" alt="Image-1.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/121126/f8447565-af18-d21c-6180-e11987845aa1.jpeg">

- なにか発言すると「きんにく」と返事する
- 「きんにく」と発言すると「もりもりー！」と返事する

これだけなんですが、これだけで私個人は情景を思い浮かべて癒やされるというメンタルヘルス効果のあるBOTになりました。

# 技術的な話

- AWS Lambda
- AWS API Gateway
- Python3.6
- LINE Messaging API

AWSはほぼ触ったことがないので、IAMユーザーとポリシー作成で手間取りました。AWSのデモなどで見ていると超簡単そうですが、自分でやろうとするとそう簡単ではないですね。

## LINE Messaging APIの設定

LINE Developersにログインして、新規にMessaging APIを作成します。
基本情報など入力後、設定で

  - webhookの有効化
  - 自動メッセージの無効化
  - 友達追加時のメッセージ設定（これはwebページで設定可能。スタンプなどを表示するなどもできます。）

をします。

## AWS IAMユーザーとポリシー作成

これはやりながらなんやかんややりましたが、

- Lambda
- API Gateway
- ポリシー作成

あたりを紐付けると諸々できました。でもIAMユーザーがイマイチわからないうちはルートユーザーで作成してしまう、というのもありだと思います。とにかく動く状態になるというのがモチベーションになるので。

## AWS Lambda設定

画面が変わったようでネットの参考記事などと異なる画面でしたが、内容は大きく変わっていないので、コンソールでポチポチやるとできました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/121126/a8f0b03c-c44a-e9fc-4a0b-60e2f2ca57bc.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/121126/901bbc58-6ff1-99ac-e5ee-77f4170a69a4.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/121126/7ed84f8f-abff-d570-a75f-f6fd03f53e22.png)

設定ができたらLINEのアクセストークンなどを環境変数へ定義します。

![AWS3.png](https://qiita-image-store.s3.amazonaws.com/0/121126/c8062463-2a6a-2729-ceee-a8e05fdbe770.png)


## API Gatewayの設定

![image.png](https://qiita-image-store.s3.amazonaws.com/0/121126/9f3ccf33-3810-b14b-ced0-8df8102955c9.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/121126/d313103d-afbd-25d1-43d1-4f1b6d6c02e4.png)

設定が終わるとAPIのエンドポイントが確認できるので、この内容をLINE Messaging APIのwebhook URLに貼り付けます。

![AWS2.png](https://qiita-image-store.s3.amazonaws.com/0/121126/d80fef11-b102-cbe7-aaf4-8e55ac5a7fba.png)

## Lambda関数をPythonで記載

ログ出しなど基本的な内容を記載しつつ、受け取ったメッセージの内容で「きんにく」「もりもりー！」を制御しているぐらいです。

## 今後の継続検討

せっかくなので以下のような拡張をしていってみたいと思ってます。

- メッセージの返事のレパートリーを増やす。（randomで何種類化を出せるように）
- req側のメッセージと発信時間を溜め込んでデータ分析してみる。（いつ癒やしを求めているか？の分析）
- 妻に利用させて、上記の内容を把握して妻のストレスチェックをする。

## やってみてわかったこと

- クソアプリという敷居の低さでとりあえず出してみる！というモチベーションが維持できました。アドベントカレンダー駆動×クソアプリはアウトプット初心者にはよい場所なのかもしれません。（勝手にそんなこと思っている。）
- AWSもLINE Messaging APIもまだまだ使いこなせていないが、とりあえず使えるようになるまでまず行くことが大事。やってみてわかる課題、調べたいことがわかってくるな、と気づきました。
- AWSは簡単そうに見えてやはりいろいろ設定が大変だな、と思ったので、継続して使って知識を深めたいなと思います。

# 参考にさせていただいた情報

まだまだ雑魚エンジニアの私にはネットは救いです。感謝しかない。
[AWS Lambda の Python 3.6 で LINE Bot を動かす](https://blog.5000164.jp/2017/8/14/line-bot/)

# 利用させていただいた素材

みんなだいすき「いらすとや」さんからイラストを利用させていただきました。
こんなきんにくのイラストまであるなんて最強か！
2018年でもVBA

#Outlookを操作するVBA

Outlookを操作するVBAについて、書いてあるサイトが少なかった。

Kさんへ　VBAのススメ　SES業界で働いてる人は特におすすめ
https://www.youtube.com/watch?v=_3Yh85wlvQs
マウスジェスチャー on Neovim

マウスジェスチャーを可能にするNeovimのプラグイン[gesture.nvim](https://github.com/notomo/gesture.nvim)を作成しました。
以下のようにジェスチャーの入力をキーにマッピングできます。

```vim
" Drag中はジェスチャーが入力される
nnoremap <silent> <LeftDrag> :<C-u>call gesture#draw()<CR>
" Drag終了時に登録されたジェスチャーとマッチしたら実行する
nnoremap <silent> <LeftRelease> :<C-u>call gesture#finish()<CR>

" ジェスチャー登録
" 上下 = G
call gesture#register().up().down().noremap('G')
" 下上 = gg
call gesture#register().down().up().noremap('gg')
```

<img src="https://raw.github.com/wiki/notomo/gesture.nvim/images/demo.gif" width="1280">

## コンセプト

あまり長いジェスチャーは覚えられない、かつ入力ミスをしやすいので、
上下左右の組み合わせ以外でもバリエーションを増やせるようにしました。

### ジェスチャーの1画の長さを区別する
以下のようにジェスチャー長の最大・最小を1画ごとに設定できるため、
同じ方向でも長さによって違う動作をマッピングできます。

```vim
" 右に25文字以下移動 = tabnext
call gesture#register().right({'max_length' : 25}).noremap(":\<C-u>tabnext\<CR>")

" 右に26文字以上移動 = tablast
call gesture#register().right({'min_length' : 26}).noremap(":\<C-u>tablast\<CR>")
```

### バッファローカルなジェスチャーにする
map系のコマンドのようにジェスチャーをバッファローカルにすることが可能です。
例えば、以下のようにFileTypeイベントでファイルタイプごとに違う動作をマッピングできます。

```vim
augroup gesture
    autocmd!
    autocmd FileType vim call gesture#register().right().left().noremap(":\<C-u>source %\<CR>", {'buffer' : v:true})
augroup END
```

## 実装
プラグインを実装するにあたって、初めて触ったオプション・コマンド・関数を紹介します。

### :set virtualedit=all
通常は文字がない場所にはカーソルを移動できないのですが、以下でそれを可能にします。

```vim
set virtualedit=all
```
ジェスチャーの開始・終了時にこのオプションを操作しています。
このオプションにこんなユースケースがあるとは思いませんでした。

### :wundo, :rundo
列については`virtualedit`で文字がなくてもカーソルを移動できるようになりますが、 行についてはできません。
なので、ジェスチャーの開始時にバッファを編集して十分な空行を追加し、ジェスチャーの終了時に戻しています。
その際にユーザーのundo履歴が破壊されないように、undo履歴を保存・復元する必要があります。
それを可能にするコマンドが`wundo`, `rundo`です。
`wundo`でファイルにundo履歴を保存し、`rundo`でファイルからundo履歴を読み込みます。

以下のような流れで保存・復元しています。

```
1. ジェスチャー開始(入力前)
    1. `tempname()`でundo履歴を保存するファイルを用意する
    2. `wundo`でundo履歴を保存する
    3. 空行を追加する
2. ジェスチャー入力
3. ジェスチャー終了(実行前)
    1. `undo`で追加した空行を削除する
    2. `rundo`で保存したundo履歴を読み込む
```

結構辛い実装になっているので、他に方法があれば知りたいです。

### nvim_buf_set_virtual_text(), nvim_buf_add_highlight() (没)
`nvim_buf_set_virtual_text`は位置と[文字列, 適用するハイライトグループ名]の配列を与えて、バッファの行末後の文字のない部分に表示するapiで、
`nvim_buf_add_highlight`は位置とハイライトグループ名を与えてバッファの文字をハイライトするapiです。

以下のように両方を使えば文字の有無にかかわらずハイライトできるため、
これらを用いてジェスチャーの軌跡をハイライトする機能を作ろうとしました。

```vim
let s:b = bufnr('%')
let s:line_start = 0
let s:line_end = 0
let s:col_start = 10
let s:col_end = 15

call nvim_buf_set_virtual_text(s:b, s:line_start, s:line_end, [['    ', 'NONE'], ['virtual_text', 'TODO']], {})
call nvim_buf_add_highlight(s:b, 0, 'TODO', s:line_start, s:col_start, s:col_end)
```

当然同じバッファは同じハイライトになるので、1つのタブに同じバッファが複数あると軌跡が正確になりません。
これに気付かず途中まで作ってから没にしました。残念。


## 動機
Neovimでブラウザを操作する拙作[ctrlb.nvim](https://github.com/notomo/ctrlb.nvim)を使っていてもまだ、片手キーボード片手マウスという状況になることがあります。
ブラウザではマウスジェスチャー拡張を使っているので、Neovimとのコンテキストスイッチを減らすために欲しいなと思って作りました。
調べても過去の例が出てこなかったのでそもそも需要がなさそうですが、
マウスを触りたい気分になったら使ってみてください！
過去記事に得意げにコメントをして恥ずかしい思いをする事を防ぐプラグイン作った

この記事は[個人開発 #2 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/private-developmen2) の１５日目です


# [Qiitime Extension](https://chrome.google.com/webstore/detail/mbgcnmokfhflcfnkbhoillmmamglcnjh)　を作りました。

## スクショ

![スクリーンショット 2018-12-15 12.08.05.png](https://qiita-image-store.s3.amazonaws.com/0/180411/cb77edbd-9f62-e701-091d-763d60d9eb2a.png)
![スクリーンショット 2018-12-15 15.20.40.png](https://qiita-image-store.s3.amazonaws.com/0/180411/54aeb3a9-2b79-6fc1-ed7d-c0a42015f0b8.png)


# なぜ作ったのか

私はほぼ毎日Qiita のタイムライン、マイルストーンを見ています。
それこそ未読が無くなるまで見ているのですが、一覧表示上では投稿日が書いておらず
記事ページを開くまで**記事が古いのか新しい**のか判別がつきません。
また、とても古い記事に**ドヤ顔**でコメントを書いてしまう事もあり、恥ずかしい思いをしました。

そこで、一覧ページでも記事の投稿日を表示できるプラグインを作成しました。
(ついでに古いと色が暗くなります）

# 作るまでの苦難の道①

当初APIを使わず記事ページ内から投稿日を取得しようとしました。
投稿日は`createdAt:なんとか` という形で記事ページないに存在していたためこれを正規表現で取り出す事で投稿日を割り出す事ができました。
しかし、この`なんとか`が曲者で、記事ごとに日付データのフォーマットが違う事があり、すべてチェックできないので
APIを使って記事データを集めるよう変更しました。APIのデータは保持せず、CloudFlareにキャッシュさせています。


# 作るまでの苦難の道②

相変わらずChromeExtensionがアップロードできない件ですが、どうやら複数のGoogleアカウントで同時にログインしていると
うまくアップロードできないようです。シークレットモードで再度ログインしたらアップロードできました。

# さいごに

このプラグインは古い記事にコメントをするなというプラグインではありません。
私がレスを期待して何年も前の記事にコメントをしてしまった事があるので
コメントをする前に一旦考える時間を設けることを目的としています、
Raspberry pi3のパッケージ更新したらWiFi繋がらなくなった話

24時間運用しているRaspberry piが最近調子悪い気がするので思い切って色々とアップデートしたらWiFiが繋がらなくてハマったけど解決したので共有。

# 公式サイトのアップデート手順確認と実行
しばらく公式サイトを見ていなかったので、アップデート手順を確認してから。
https://www.raspberrypi.org/documentation/raspbian/updating.md

### インストール済みパッケージリストのアップデート
```bash
sudo apt-get update
```

### インストール済みパッケージを最新に更新
```bash
sudo apt-get dist-upgrade
```

# ファームウェアの更新をどうするのか？
公式サイトに書かれている通り、カーネルとファームウェアはDebianパッケージとしてインストールされるため、上記の手順でインストールされるようになっています。
ただ、今使っているRaspberry pi3がやや不安定な動作をすることもあるため、思い切ってBleeding Edgeな最新版を入れて見ることにしました。
そのためにはrpi-updateコマンドを使います。
以前はディストリビューションに含まれていたコマンドですが、今は安易にアップデートできないようにするためか、apt-getでインストールする必要があります。

ちなみに下記の公式ページにはrpi-updateで取得したカーネルは正しく動作することを保証しません、と書かれていますので自己責任にてやりましょう。
`Note that the latest kernel from rpi-update is not guaranteed to work correctly!`
https://www.raspberrypi.org/documentation/linux/kernel/updating.md

```bash
sudo apt-get install rpi-update
sudo rpi-update
```

再起動

```bash
sudo reboot
```

# 発生した問題

再起動してみるといきなりWiFiに繋がらない問題が発生。
安易にrpi-updateをしてしまったと後悔しましたが、内臓WiFiであるwlan0は
DOWNとなっており、ifupを試みるとデバイスの問題というよりWiFi環境に問題がありそうな感じ。
よく考えてみるとSSIDがステルスモードなのに、その設定をしていませんでした。
今までもしていなかったので、なぜ動いていたのか疑問ではありますが。

ということで気を取り直してwpa_supplicant.confにscan_ssid=1を追加。

```bash
sudo vi /etc/wpa_supplicant/wpa_supplicant.conf

<追加後>
〜〜略〜〜
network={
        ssid={SSID}
        scan_ssid=1
        psk={パスフレーズ}
}
```

再起動すると無事WiFiにも接続できました。

```bash
sudo reboot
```

最後に@manji0さんの[記事](https://qiita.com/manji0/items/d3d824d77c18c2f28569)を参考にpipでインストールしたpythonパッケージを一括更新して作業完了！

```bash
pip list --outdated --format=legacy | awk '{print $1}' | xargs pip install -U pip
```

起動速度が大幅に改善され、動作自体も安定しているようで特に問題も見受けられません。しばらく運用しながら様子を見ようと思います。
Rubyばかりやってたら一瞬戸惑ったmap() ≠ collect()

Rustのチュートリアルを読んでいて一瞬理解できなくなるところがあったからメモ。

Rubyばかり使っていたらこの部分で戸惑った。
[食事する哲学者](https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/dining-philosophers.html)より

```RUST

    let handles: Vec<_> = philosophers.into_iter().map(|p| {
        thread::spawn(move || {
            p.eat();
        })
    }).collect();
```

Rubyではmap()とcollect()は名前が違うだけで同じメソッドなので、なんで同じメソッドを繰り返しているのか、と首をかしげた。

ちょっと調べたらわかった。map()はMap型を返すので、collect::<T>()をして型変換をする必要があるらしい。

へーって思った。まる。