OmniAICreator/Qiita-1.07M huggingface dataset:
コンテナからGCS(Google Cloud Storage)にアクセスする方法

# 概要
AWS Batchで起動したコンテナ上からGCS(Google Cloud Storage)にアクセスするためにやったことを書きます。
AWS Batchじゃなくても使えると思います。

仕組みは、AWS Parameter StoreにGCPのサービスアカウントキーをKMSで暗号化した状態で格納しておき、
コンテナ起動時にParameter Storeからdecryptして、gcloud authコマンドで認証する流れです。
それでは行ってみましょう。


# 事前準備
* GCPでGCSにアクセス可能なサービスアカウントを作成、ダウンロードしておく。
* gcloudコマンドがインストールされたコンテナを用意する。
    * [Cloud SDKのインストール](https://cloud.google.com/sdk/downloads?hl=ja#interactive)にてgcloudコマンドをインストールしました。


# 手順
## AWS KMSでキーを作成
KMSでParameter Storeで暗号化するために必要なキーを作成します。

```sh
# キーの作成
aws kms create-key --description <キーの説明> --region ap-northeast-1

# キーのエリアスを設定
aws kms create-alias --alias-name alias/<キーの名前> --target-key-id <キー作成時に出力されたKeyId>
```

## Parameter Storeでサービスアカウントを格納
上記で作成したKMSのkey idを指定して、暗号化した状態でサービスアカウントキーをParameter Storeに格納します。

```sh
# パラメーターストアの作成
aws ssm put-parameter \
    --region ap-northeast-1 \
    --name <パラメーターの名前> \
    --type SecureString \
    --key-id alias/<キーの名前> \
    --value "$(cat <サービスアカウントキーのファイル>)"
```

## IAMの権限付与
(AWS Batchを利用していれば)ジョブロールに割り当てるIAM Roleに以下のPolicyを付与します。

 * AmazonSSMFullAccess
 * 以下のインラインポリシーを作成し、割り当て
    
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": [
                "<KMSのARNを入れてください>"
            ]
        }
    ]
}
```

## 認証処理
今回は[こちらの記事](https://dev.classmethod.jp/cloud/aws/aws-eaws-ecs-fetch-run-shell/)を参考に、DockerのENTRYPOINTで初期化用のスクリプト(fetch_and_run.sh)を実行させます。この初期化用スクリプトの中で `gcloud auth` を実行させました。

実際の認証処理は以下のようにしました。
`aws ssm get-parameters` で取得したサービスアカウントを `/tmp/credentials.json` に出力し、それを使って `gcloud auth` で認証しています。

```sh
# fetch_and_run.sh 
aws ssm get-parameters --name ${SSM_PARAMETER_NAME} --with-decryption --region ap-northeast-1 --output json | jq -r '.Parameters[].Value' > /tmp/credentials.json
gcloud auth activate-service-account --key-file=/tmp/credentials.json
```

## まとめ
Parameter Storeって便利。
Djangoの環境構築

# 経緯
Pythonで少しだけお仕事する事になった物の、「おじさん、Pythonやった事ないお・・・」って状況だったので、
お家パソコンにまずはDjangoでも入れて、色々作ってみるか！と言うノリ。

# このページの目的
もうおじさんなので、物忘れ激しい・・・って事で忘れないようにメモメモ・・・

# 環境
- Windows10 Pro
- Python 3.7.3
- Miniconda 4.6.14

実はPythonだけは既に入れていたりする。。。

# まずは・・・
pipでインストール。バージョンは2.1.8。

``` 
pip install django==2.1.8
```

バージョン指定には特に意味はない・・・

# プロジェクトの生成
```
django-admin startproject djtest
```

"djtest"の部分がプロジェクト名になる感じ。

# とりあえず動かしてみる
```
cd djtest
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.
June 13, 2019 - 10:40:52
Django version 2.1.8, using settings 'djtest.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
```
![Django.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123224/091d20e3-374f-7ba2-44a5-6e777b6d28c4.png)

おお・・・表示された・・・
しかし、このロケットのアイコンってDjangoの何とかかってるのかなぁ・・・

# 設定をいじってみる
プロジェクトフォルダ直下/プロジェクト名のフォルダ/settings.pyをいじいじ・・・

```settings.py
LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'
```

言語を日本語に、タイムゾーンを東京に変更。

# アプリを追加してみる

```
python manage.py startapp hello
```

"hello"の所がアプリ名になって、フォルダも作成される。

# アプリの登録
↑で登録したアプリをプロジェクトに登録しないといかんらしい。。。ふむふむ・・・

```settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'hello',   # ←追加
]
```

# コントローラー部分を触ってみる
プロジェクトフォルダ/アプリフォルダ/views.pyがコントローラになる感じ。

```views.py
from django.shortcuts import render

# Create your views here.
def index(request):
    return render(request, "hello/index.html")
```

renderの第二引数でテンプレートファイルを呼び出している。
テンプレートはどこに置くの？ってなると思うけど、プロジェクトフォルダ/アプリフォルダ/templatesの下にテンプレートファイルを置く感じ。

デフォルトだとtemplatesフォルダは無いので、自力作成、helloフォルダも自力作成。
それと、今回のテンプレートファイルの中身には"hello"だけ書いてる感じ。

# ルーティングの設定
アプリフォルダの直下に"urls.py"を作成して、以下の様に書く。

```urls.py
from django.conf.urls import url
from . import views

app_name = "hello"

urlpatterns = [
    url(r'^$', views.index, name="hello")
]
```
app_nameが無いと、「'Specifying a namespace in include() without providing an app_name」とかで怒られる。

その後にプロジェクトフォルダ/プロジェクト名のフォルダ/urls.pyを編集。

```urls.py
from django.contrib import admin
from django.urls import path, include # ←include追加

urlpatterns = [
    path('admin/', admin.site.urls),
    path("", include("hello.urls", namespace="hello")) #←追加
]
```

個人的には「なんか面倒だなー」と思ったのがルーティング設定。普段はRailsで仕事してるので、とても違和感。。。
他にもっと簡単な書き方あるのかな？とも思ったので、これは今度調べてみる。

DB接続に関してはまた今度まとめようっと。

# 感想
当然と言えば当然ですけども、普段Railsで仕事してると「あー、全然構成違うんだなぁ」と言う気持ち。
ちゃんと意味があってこういう構成にしてるんだろうなとは思うけど、その意図まで汲み取れてないので、まだまだ勉強が必要だなーと。

おーし、こっからPythonの勉強やっちゃうぞー！（順序が違うとか言わないで！）
DeepRacer実機を動かしてみたinAWS Summit Tokyo time12.94 

#使ったモデル

強化学習もAWSも未経験だったのでまず[AWSの公式ドキュメント](https://docs.aws.amazon.com/ja_jp/deepracer/latest/developerguide/deepracer-console-train-evaluate-models.html)を参考にモデルを作ってみました。
コース上に4輪が留まる且つ直近のwaypointの角度と車体の角度に大きなずれがなければ高い報酬を得るように設計しました。コース内に留まることを目的としたモデルです。

```model_1.py
def reward_function(params):
    import math
 
    # paramsの取得
    waypoints = params['waypoints']
    closest_waypoints = params['closest_waypoints']
    heading = params['heading']
    all_wheels_on_track = params['all_wheels_on_track']
    distance_from_center = params['distance_from_center']
    track_width = params['track_width']

    # 報酬の初期値
    reward = 1e-3

    # コースのセンターに近いほど高い報酬を設定
    if all_wheels_on_track and (0.5*track_width - distance_from_center) >= 0.2:
        reward = 1.0
    elif all_wheels_on_track and (0.5*track_width - distance_from_center) >= 0.1:
        reward = 0.8
    elif all_wheels_on_track and (0.5*track_width - distance_from_center) >= 0.05:
        reward = 0.5

 
    # 現在の位置から最も近い次のwaypointと前のwaypointを取得する
    next_point = waypoints[closest_waypoints[1]]
    prev_point = waypoints[closest_waypoints[0]]
 
    # 前のwaypointから次のwaypointに向かう角度(radian)を計算する
    track_direction = math.atan2(next_point[1] - prev_point[1], next_point[0] - prev_point[0]) 
    # degreeに変換
    track_direction = math.degrees(track_direction)
 
    # コース上の基準軸に対する車体の向きと直近のwaypointを繋ぐ向きの差分を取る
    direction_diff = abs(track_direction - heading)
 
    # 算出した方向の差分から車体の向きが大きくズレている場合にペナルティを与える
 
    DIRECTION_THRESHOLD = 10.0
    if direction_diff > DIRECTION_THRESHOLD:
        reward *= 0.5
 
    return float(reward)
```

DeepRacer内の強化学習がどのようになっているのか把握できてないのですが、報酬に傾斜をつけた方がモデルの学習が進みやすいと考えて、コースのセンターと車両の距離に対して報酬の傾斜をつけています。

学習は5時間（クローン前のモデルで2時間学習済み）
ハイパーパラメータは初期値のままです。

#実機を動かしてみて
このモデルではMaximumSpeedを約40％ではほぼ確実に完走できました。
それより上げるとout側にコースアウトすることがほとんどでした。

会場でちらっと聞いた話ではMaximumSpeedが60％でも完走できるモデルだと、
タイムはかなりいいそうです。

ちなみにシミュレーションのEvaluationでは
| 1 | 00:00:23.434 | 100% |
| 2 | 00:00:23.029 | 100% |
| 3 | 00:00:25.052 | 100% |
でした。

初日に僕が見た時間でtopだった方がアウトインアウトするように報酬を与えたと言っていたけど、
どういう報酬関数を組んだのだろう。。。

![Screenshot_20190613-123637.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374876/a1341b82-c8d4-483a-bdfa-91eec93a616f.jpeg)
スキルチェックで使えるpython3のきほん D RANK ver. 

#はじめに
paizaをやっている人なら知っているスキルチェック！
初心者がいざやろうとすると、わからなくて嫌になっちゃうのではないでしょうか。
わからないところがあまりにも基本的すぎてネットにあまり載ってないんですよね:disappointed_relieved:
私も最初解けなくてしばらくやっていませんでした。:frowning2:
答えや問題は載せられませんが、解く際の参考になればいいなと思います。:relaxed:
#使用言語
Python3

#標準入力
入力された文字を受け取る方法です。

##ひとつの値を受け取る
```python
n = input()
```
nの部分は代入するためのものなので、なんでもいいです。
わかりやすく打ち込みやすいものにしてください！

##複数の値を改行ありで受け取る
問題の入力が以下ようなものだった場合です。
２つ以上のこともあります。

```
2
3
```
コードは以下のようになります。

```python
n = input()
s = input()
```
改行の場合はこのように入力を増やしていくことで、複数の値を受け取ることができます！
２つ以上の場合も同様に増やしていくことができます。

##複数の値を改行なしで受け取る
問題の入力が以下のようなものだった場合です。数字が複数、半角で区切られて入力されます。
これ調べても全然出てこなくて最初のにつまずいた問題です。:cry:

```
2 3
```
コードは以下のようになります。

```python

n = input().split()
```
例では値が２つしか入力されていませんが、もっと多くの値を受け取ることも可能です。
このように入力されるとリストの中に値が入ります。
そのため、値を取り出すときは、例を参考にすると、以下のようになります。

```python

n_1 = n[0]   # 2　を取り出す
n_2 = n[1]   # 3　を取り出す
```

#入力を変換
標準入力されたものは基本的に”文字”として扱われます。
よって数字も"文字"として扱われることになります。

##入力された数字を"数字"に変換
入力した数字が”文字”として扱われてしまうと、計算などの処理ができなくなってしまいます。
その時に使用するのが```int()```です。これを使うと数字を”数字”として扱うことができます。
入力が

```
３
```
であるとして、コードは以下のようになります。

```python
#文字として入力を受け取る
n = input() 

#数字に変換
n = int(n)
```
これでnを用いて計算などの処理を行えるようになります！

でもこれ入力された時点でやりたいなぁ:thinking:と思いませんか？
できます！コードは以下のようになります。

```python
n = int(input())
```
このように```int()```で```input()```を囲むことで最初から数字として受け取ることができます！
便利ですね！:blush:

#出力
pythonの基本の出力は以下のコードになります。

```python

print("@@@@") # @@@@ と出力されます。
```
複数出力する際もこのコードを増やしていけばできますよね。
しかしこの場合、改行が必ず入ってしまいます。

##改行なしで出力
改行を入れないで連続して出力したい場合、例えば、

```
11
```
としたい場合のコードは以下になります。

```python
print(1 , end = "")
print(1)
```
例えが微妙なので便利さが不明かと思いますが、```print()```を複数使っても改行されないのはとても便利です！

##改行なしで半角で区切って出力する
改行は入れたくないけれど、半角で区切りたいという場合

```
neko panda
```
と出力したい場合は以下のようなコードになります。

```python
# "" の間に半角スペースを入れる
print("neko" , end = " ")
print("panda")
```

#おわりに
paizaのスキルチェックはコードの考え方を勉強するにはとてもいい教材だと個人的には思うので、ぜひチャレンジしてみてください！
簡単なコードの組み合わせも考え方次第でいろんなことができるようになります！
ぜひ色々と試行錯誤してみてください！:grinning:
virtualbox(centos)でapache+mysql+phpの環境を作る

# 内容
タイトル通り。
#なんで書いたの？
備忘録代わり & 共用者と共有するため。
#環境
・virtualbox6.0
・centos7.0
・apache2.4
・mysql5.6
・php7.0
#apacheのインストール
apacheのインストール
```yum install httpd```

apacheの起動
```systemctl start httpd.service```

自動起動したい場合
```systemctl enable httpd.service```

#mysqlのインストール
デフォルトでインストールされているmariaDBとの競合を避けるためmariaDBを削除
```yum remove mariadb-libs```

念の為
```yum remove mysql* ```

mysqlのインストール
```yum install http://dev.mysql.com/get/mysql57-community-release-el7-9.noarch.rpm```
```yum -y install mysql-community-server```

mysqlの起動
```systemctl start mysqld.service```

logから初期パスワードを探す
```grep 'password' /var/log/mysqld.log```

初期設定
```mysql_secure_installation```

#phpのインストール
リポジトリの更新が必要なので更新する

epelリポジトリの更新
```yum install epel-release```

Remiリポジトリ
```rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm```

PHP7をインストール
```yum install --enablerepo=remi,remi-php70 php php-devel php-mbstring php-pdo php-gd```

#apacheでphpが動くかチェックする
```phpinfo.php
   <?php
     phpinfo();
   ?>
```

/var/www/html/　にこのファイルを置いてlocalhostにアクセスすればphpinfoが見れる。

#仮想環境ができたら
いろいろ突っ込んで遊びましょう。
仮想環境のOS内で動かすことはほぼ無いと思います。SSH接続してコマンド打つのがデフォです。
dockerがあるのにこんなクラシックなやり方をなんで今さらやってるかっていうとminikubeの予行練習です。

#ホストPCから仮想環境のmysqlに接続
mysqlworkbench使って接続しましょう。
上のタブのDatabase→connect to databaseをクリック。connect methodはstandard TCP/IP overSSHです。
SSH hostnameは接続したい仮想環境のIPアドレス。
usernameはcentos起動時に設定したもの
mysql hostnameは127.0.0.1 portは3306
usernameは設定したものを入力。
これで繋がります。

#接続できない場合
virtual boxのネットワークタブを開いて割り当てをブリッジアダプターに変更する
centosのユーザー権限をスーパーユーザーにする
mysqlユーザーの権限を変える（grant all privileges on *.* 'username'@'127.0.0.1'）
mysqlユーザーの権限のhostを%か127.0.0.1にする(localhostと127.0.0.1は区別される)

#参考にさせていただいたサイト
CentOS7 + Apache2.4 + MySQL5.7 + PHP7 で作る最新LAMP環境 on さくらVPS
https://qiita.com/kyophp/items/0110d4307eff747c7092
VirtualBox (Windows) 上に CentOS 7 をインストールする
https://qiita.com/100/items/80a899fbaeb1e82b3f67
[Python]ArduinoのCOMポートが変わってもコードを編集せずにポートを開く方法



TL;DL　``Pyserial``の``list_ports``の`description`を使えばデバイス名でArduinoがどのポートに接続されているかわかる

## イントロダクション

``Pyserial``を使用したシリアル通信を行う場合、COMポートオープンするには以下のようなコードになると思います。

```Python
import serial

arduino_ser = serial.Serial('COM5')
```

この方法だとArduinoのCOMポートが変わってしまった時にエラーが出てしまいます。

また、接続されているCOMポートのリストを取得し、接続する方法もありますが、**Arduino以外のCOMポートを利用する機器が接続されている状況**では正しく動作しません

```Python
import serial
from serial.tools import list_ports

ports=list_ports.comports()
for port in list_ports.comport():
    arduino_ser=serial.Serial(list_ports.device)

```

私の使用状況では、Arduinoの他にCOMポートを利用する機器が接続されている状況のため、上記コードを利用する事が出来ませんでした。

この記事ではCOMポートが変わった場合でも**デバイス名からArduinoのポートを特定**し、コードを編集せずにArduinoのポートを開くことが可能なコードを紹介します。

## 環境

- Windows10 64bit
- Python 3.6.3
- Pyserial 3.4
- Arduino Uno Rev3

## 方法

```Python
import serial
from serial.tools import list_ports

ports=list_ports.comports()
device=[info for info in ports if "Arduino" in info.description] #.descriptionでデバイスの名前を取得出来る
if not len(device) == 0:
   arduino_ser=serial.Serial(device[0].device)
else:
    print('Ardunoは接続されていません')
```

### 注意点

- デバイス名に`Arduno`が入っているデバイスが複数個接続されている場合は、一つのArduinoのポートしか開けません

## 別の方法

StackOverflowで`win32com`を利用した方法も見つけたため紹介いたします。

``` Python
import win32com.client

wmi = win32com.client.GetObject("winmgmts:")
for ser in wmi.InstancesOf("Win32_SerialPort"):
    if "Arduino" in ser.name:
            arduino_ser = serial.Serial(ser.DeviceID)
```

### 参考リンク

StackOverflow : [python : How to detect device name/id on a serial COM](https://stackoverflow.com/questions/7756695/python-how-to-detect-device-name-id-on-a-serial-com)

Gist : [pyserialでシリアルポート一覧を表示し選択させて，読み込むプログラム](https://gist.github.com/TonyMooori/bd276abc8d149ef33225)
【WordPress】WordPressのここがイイ

以前、[WordPressのここがダメ](https://qiita.com/fallout/items/3de7ece4acd3ae968628) という記事を書きましたが、私自身は別に、WordPress に親を殺されたわけでもありませんし、業務でも普通に採用しています。

散々ダメ出ししながらも何故使うのか、主に PHP 開発者＆サーバー管理者の観点から、改めて考えてみました。

--------------------------------------------------------------------------------

## メリットとデメリットとは隣り合わせ

WordPress のメリットとして、よく紹介されているのは…

1. セットアップが簡単
2. コンテンツの更新が簡単
3. ユーザーが多い ＝ 情報も多い
4. プラグインやテーマが豊富
5. 問題が見つかってもすぐにバージョンアップされる

…こんなところでしょうか。

しかし私は、これらがメリットだとは全く思いません。

1. でも、方法によっては手間がかかるし、危ない
2. でも、思い通りにしようとすると、相応の知識は要る
3. でも、情報が多すぎて、何を信じれば良いか分からない
4. でも、脆弱性もよく発見されている
5. でも、セキュリティ意識が低ければ無意味

結局、運用者次第では、**それらは全てデメリットにもなり得る**からです。

--------------------------------------------------------------------------------

## 自分が楽できるから

突き詰めれば、これに尽きます。

WordPress には、[WP-CLI](https://www.google.co.jp/search?q=WP-CLI+WordPress&ie=utf-8&newwindow=1) という超素敵なものがあります。

私自身のシェル力は、ヤムチャ…サイバイマン…下手するとヤジロベー以下ですが[^1]、そんな私でも shell をゴリゴリと書けば、セットアップやバージョンアップなどは、自動化できます。

[^1]: この古臭い例えから、色々と察してください。

こんな古臭い方法でも、あまり困った事はありません。

作業とも呼べない作業をして、管理画面のログイン情報を渡せば、基本的に自分の仕事は終わりです。

デザインやコーディングは、デザイナさんへ丸投げですし、プログラムを書く必要もありません。

極稀に、PHP コードレベルで多少手を加える事はありますが、わざわざ自分で何かを書かなくても、大抵はどこかの誰かが素敵なプラグインを作ってくれています。

プログラマなんて、楽して何ぼの世界です。自分が楽をするための努力だけは、惜しみませんが。

WordPress 万歳。

--------------------------------------------------------------------------------

### 設計が古い？

[WordPressのここがダメ](https://qiita.com/fallout/items/3de7ece4acd3ae968628) では、設計の古臭さに起因する問題点も、いくつか指摘しました。

しかし、ずっと前にもどこかの記事で似た事を書きましたが、クライアントさんやサービス利用者にとっては、そんなのはもの凄くどうでも良い事です。

「WordPress の設計は古いんです！」と言って、「そうなのか！！」と納得する人なんて多分いません。

「オタクっぽい人が、なにか意味不明の事を言ってるよ…ｗ」で終わりでしょう。

目に見える結果をコミットして何ぼです。

--------------------------------------------------------------------------------

### 重い？

[簡単なベンチマーク](https://qiita.com/fallout/items/3de7ece4acd3ae968628#7-1%E7%B0%A1%E5%8D%98%E3%81%AA%E3%83%99%E3%83%B3%E3%83%81%E3%83%9E%E3%83%BC%E3%82%AF)からも分かる通り、素の状態の WordPress はとんでもなく重いですが、そこは世界中の賢い人達が、解決方法を生み出してくれています。

今は、ウェブブラウザからポチポチしていくだけでも、素敵な WordPress 環境が手に入る時代です。

そんな素敵なものを、~~情報商材だかアフィリエイト塾だか、何だか訳の分からないものに騙されて、昔ながらのレンタルサーバーなんて使って、~~使わない人が悪いだけです。

自分が楽をするために、これまで色々と作ってきたものも、きっと近い将来、無意味なものになる（もうなってるかも）と思います。

--------------------------------------------------------------------------------

## 楽できる理由

楽？ それって、あなたのポジションがそうだから、楽できてるだけでしょ…。

確かにその通りです。WordPress 案件には、「最低限の事」以外は、なるべく関わらないようにしてます。

でも、自分に求められている「最低限の事」って何でしょう？

「最低限」というのは、とても曖昧な表現だと思います。

- 「あれ？ここはやってくれないの！？」「いや、そんな話は聞いてない」
- 「いや、それもあなたの仕事でしょ…」「いやいや、これはうちの仕事じゃない」

…よくある話ですが、線引きが曖昧だから、そういう面倒くさい話になるのだと思います。

--------------------------------------------------------------------------------

### WordPress の場合

1. ドメインを割り当て URL を見れる状態にする
2. デザインする
3. コーディングする
4. コンテンツを更新する
5. ユーザーサポート
6. サーバーの面倒を見る

私の仕事は、1 と 6 です。デザイナさんの仕事は、2 と 3 です。クライアントさんの仕事は、4 と 5 です。

…あら、何て分かりやすい。

これが、WordPress の一番のメリットなのだと思います。

もし WordPress を使ってなかったら、「PHP や JS 書けるんだったら、これもあなたの仕事じゃね？」なんて話になるかもしれません。

クライアントさんから、「ついでにこれもやってよぉ！」と頼まれるかもしれません。

WordPress なら、「それ、WordPress でできますので (=ﾟωﾟ)ﾉ」で終わりです。
WordPress さん、ありがとう。
Sign In with Appleをアプリに実装したい[iOS13 Xcode11]

#この投稿は
WWDC2019も終わり、例年通り時期iOSの発表もありました。
いろいろ気になるものはありましたが、「Sign In with Apple」で会員系のサービスを促進したいなと思って調べてみました。

#実装方法
※いわずもがな、まだiOS13はβ版です。今後のアップデートで何かしら変更が入る可能性がありますし、私の理解が誤っている場合もありますので参考までにとどめてくださいね。
##準備
- XcodeでCapabilitiesにSign In with Appleを追加
![スクリーンショット 2019-06-13 13.31.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132494/f7eeb5ac-5f40-ca4f-88cd-37ac58db7399.png)

- Certificatesでも該当アプリのCapabilitiesに追加を忘れずに
![スクリーンショット 2019-06-13 13.33.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132494/3850a49a-7414-1d5c-79ff-567b65afa0f2.png)
- AuthenticationServices.frameworkを追加
- とりあえず、「Sign In with Apple」的なボタンを適当につくってメソッドと紐づけておく。

以上で準備完了です。あとは実装するだけです！

##コーディング
###ボタンに紐づいたメソッドでリクエストを実行します
```ObjectiveC
/**
 *  SignInWithApplenボタン押下
 */
- (IBAction)signIn:(id)sender {
    
    ASAuthorizationAppleIDProvider *provider = [[ASAuthorizationAppleIDProvider alloc] init];
    ASAuthorizationAppleIDRequest *request = [provider createRequest];
    [request setRequestedScopes:@[ASAuthorizationScopeFullName,ASAuthorizationScopeEmail]];
    
    ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
    controller.delegate = self;
    [controller performRequests];
}
```
うまくいけばこんな感じの画面が出てきます。
<img width="1112" alt="IMG_F4D89F868B06-1.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132494/e3a1c4cd-b68e-ead9-0f3d-46af65997f41.jpeg">

###ASAuthorizeの成功、失敗のデリゲートメソッドを実装
```ObjectiveC
/**
 *  SignIn成功時
 */
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(nonnull ASAuthorization *)authorization
{
    ASAuthorizationAppleIDCredential *appleIDCredential = [authorization credential];
    
    // appleIDCredentialから情報取得（初回のみ？）
    NSString *user = [appleIDCredential user];
    NSString *email = [appleIDCredential email];
    NSString *fullName = [NSString stringWithFormat:@"%@ %@", [[appleIDCredential fullName] familyName], [[appleIDCredential fullName] givenName]];

    // 二回目以降はjwt形式でエンコードされている値でのみ返すっぽい
    NSData *tokenData = appleIDCredential.identityToken;
    NSString *tokenDataString = [[NSString alloc] initWithData:tokenData encoding:NSUTF8StringEncoding];
    
    NSLog(@"user:%@\nemail:%@\nfullName:%@",user, email, fullName);
    
    // ここでサーバーに送るなどログイン処理
}
```
```ObjectiveC
/**
 *  SignIn失敗時
 */
- (void) authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error
{
    // エラー処理
}
```
こんな感じですかね。
とりあえず成功時に最低限の処理を書きましたが、エラーハンドリングもベストプラクティスがわかれば追記していきますね。
どうも2回目以降はappleIDCredentialにemailとfullNameが入ってませんでした。
なので、appleIDCredential.identityTokenをデコードして取り出す必要がありそうです。

#感想
超簡単。どこぞのめんどくさいOAuthを思い出せばめっちゃ簡単でした。
ぶっちゃけそこまでドキュメントを真面目に読んでいないのでまだまだ色々やるべきことはあると思いますが、必要最低限のデータ取得はこれでできました。
これで会員増えたらいいな。
GraphiQLがフリーズした時にやること

<img width="1026" alt="スクリーンショット 2019-06-13 14.17.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32950/cc310b55-d5a4-837f-9a31-bcf11810d7d6.png">

GraphQLのアプリケーションを開発している時に
必須なデバッグツール「GraphiQL」（ぐらふぃーきゅーえる？）。
https://electronjs.org/apps/graphiql

たまにフリーズしてしまって使えなくなることがあるんです。

「GraphiQL freeze」とかで検索をしてみても中々答えが見つからず
多分キャッシュだろうなと思ったので、キャッシュを削除したら直りました。

# GraphiQLのキャッシュを削除する
```bash
rm -rf ~/Library/Application\ Support/GraphiQL
```

上記実行後、GraphiQLを再起動する。

# 雑談

GraphQLとGraphiQLは、ややこしいので改名してほしい！
特にRailsでGraphQLを使った開発する時
参考文献に
> `graphiql-rails` をインストールする。

と書かれているのをみて写経していたのですが
私のような、コピペをしない残念な開発者は `graphql-rails`(「**i**」がない) と書いてしまいました。
これ、`module not found` ですよ。
コピペしていきましょうね。

例えば「GraphQL Debug Tool」とかオーソドックスな名前でもいいから...！


以上です。

Happy Coding!
タイピングを速くするための覚え書き

# タイピングを速くするための覚え書き

自分のクセを見抜いて修正する習慣をつけたい
目指せ爆速エンジニア

## 要旨

- とにかくホームポジションを崩さないように打てることが大事
- ホームポジションを崩す弊害は、訓練か代替キーで解消する

## 覚書一覧(随時追加)

### 右手の薬指と小指で打つべし

左利きの人間は右手の扱いに長けておらず、使いやすい中指と人差し指ばかり使いがち。とりわけ`ctrl+m`できないときにを右手中指で押しに行くせいで右手がガチャガチャ動く。カギカッコ周りのキーを小指でうまくタイプできるように初めは丁寧に叩くべし。
もし右利きならタブキーを左手小指で打つ習慣はつけておくべし、になるかな。

### (Macの)Emacsバインドを打つべし

- `ctrl+h`= delete
- `ctrl+m`= enter
- `ctrl+a,e,f,b,n,p`=各種カーソル移動 


ホームポジションから離れた位置にあるキーは、ショートカットで代替できるものが多いので、そちらの打ち方になれるべし。

### 左側のキーの大文字シフトは右のシフトキーで打つべし

これも左利きの弊害。右小指のシフトを使わないと`A`とか左手の小指と左手の薬指で打ってしまっているので非効率。

### 右手小指の可動域を広げるように打つべし

- 右手小指は`;`より右側のキーを全て担当するので非常に担当範囲が広い。右手小指を制するものはホームポジション取得を制する。
k-meansにカーネルトリックを適用する

#参考にした論文
[Inderjit S. Dhillon,Yuqiang Guan,Brian Kulis:Kernel k-means, Spectral Clustering and Normalized Cuts](http://www.cs.utexas.edu/users/inderjit/public_papers/kdd_spectral_kernelkmeans.pdf)





#k-means

設定された距離に従って、近い者同士でグループに分ける。通常はユークリッド距離で分ける。

詳しい理論は[K-means 理論編](https://takutori.blogspot.com/2018/06/k-means_29.html)をどうぞ。

結果のイメージは下の図のような感じ。centroidは各グループの平均ベクトル。

![d](https://4.bp.blogspot.com/-EC-0KrFW3Og/Wzios7xy_oI/AAAAAAAAAJU/xYZpaeN7SJ4GA2IAtbInuKpxnjyen40pQCLcBGAs/s1600/data%253Drandom_data_kernel%253Dlinear_k-menas.png)


ユークリッド距離だと下の図のようなデータはうまく分類できない。

![d](https://2.bp.blogspot.com/-0lTumyvVfxY/WzigZAQk-NI/AAAAAAAAAI4/mhPa_-BYOs8jn1zPwXBYVWaUor9pNMlRwCLcBGAs/s1600/data%253Dcircle_data_kernel%253Dlinear_k-menas.png
)


そこで、カーネルトリックを使って次のように分類することができた。

詳しい理論は[カーネルK-means 理論編](https://takutori.blogspot.com/2018/07/k-means.html)をどうぞ。

結果はこんな感じ。

![d](https://3.bp.blogspot.com/-0KYrQ0WL_eU/Wx6FvQL28iI/AAAAAAAAAHU/60JlVjvJCD0Kxc85aOUmS8WsDgc0COXrwCEwYBhgL/s1600/data%253Dcircle_data_kernel%253DRBF_k-menas.png)


実装編の記事は[カーネルk-meansの実装](https://takutori.blogspot.com/2018/06/k-means.html)をどうぞ。


#終わり。

homepageは[こちら](https://takutori.github.io/)をどうぞ。
AppleDeveloperProgramメンバーシップの住所変更 2019

# 概要
- オフィスの移転等でメンバーシップの住所を変更する場合  
Membership Detailsの「Need to edit this information?」から申請するしかない
- 確認日：2019-06



# 対象
- AppleDeveloperProgramメンバーシップの住所変更がしたい人
- Target Entity Type：Company / Organization (組織向けアカウント)
 - Individual 個人向けアカウントでは一部文言が違う

# 問題点
- 本当にそこでeditできるのか怪しく見える

# 試したこと
Apple IDのページで住所を変更してもメンバーシップの住所は変わらない
https://appleid.apple.com/account/manage

# 手順
それではスクショ付き手順です。
個人のアカウントならとりあえず試せますが、会社のとなると慎重になるのでエビデンスになれば幸いです。

## Membershipから編集画面へ
![membership-detail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275986/b877603f-c58e-ba52-b228-0a1461ea3984.png)
右下の「Need to edit this information?」をクリック
(ここは直感通りだと思います)

## 確認画面
ダイアログが出ます。見かけないチェックボックス風のリンクが気になりますね。
<img width="661" alt="organization-confirm.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275986/5f1d48e5-a9f2-28bb-8f48-065cd0511cf6.png">
「Provide your updated information」をクリックして先に進みます。

### 個人の場合
こんな画面が表示されます
<img width="661" alt="individual-confirm.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275986/2f16fcab-7274-8a09-5fd5-6354ec328733.png">
- 上 Provide your updated information：住所変更
- 下 Provide your new organization information：組織化手続き

## 編集画面
問題の画面、振り番でいきます！
概要は、`Appleとの契約情報なので、変更にはAppleの承認が必要`という感じです。
![update-detail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275986/b2a6bba9-edd0-831b-a363-f112a53e7837.png)

1. 名前、変更不可
2. Email：変更不可
3. Region：Japanを選択 (海外の場合はもちろん合わせてください)
4. 組織名：変更不可
5. AppStoreにアプリをあげているか？
6. アプリ譲渡や組織変更か？  
Noを選択しないと「New Organization Information」(住所変更のフォーム含む)が表示されません
7. 新組織名：元と同じでOK
8. 新電話番号：住所変更の場合は電話番号も変わっている場合が多いでしょう  
日本の国際電話prefix81をつけて市外局番の0を消しましょう
9. 住所変更するか？  
Yesを選択しないと住所変更のフォームが表示されません
10. 住所：※住所記載例参照
11. 組織の種類が変更されたか？
12. Company Tax Registration Numberが変更されたか？
13. 追加情報：Required (必須) です。`I moved.`等で良いでしょう。


### 住所記載例
自由記述過ぎてびびりますがMembershipのページ同様に記載しましょう。

日本語で以下の場合

```
〒123-4567
東京都港区六本木1丁目2番地3号
```

入力フォームには以下のように記述

```
1-2-3, Roppongi
Minato-ku, Tokyo 123-4567
Japan
```
※基本的に逆に書いていきますが、ユニバーサル対応の為か、割とごっちゃでも通ります。


## 依頼完了画面
Snedをクリックして送信完了です。
![finish.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275986/2f3ecb19-ac39-9524-4714-e6032590ab59.png)
Appleからメールが来るので1～2営業日待ちましょう。
git commitしたときにTypeScriptコードを自動修正する方法(tslint, prettier, lint-staged使用)

git commit時にリントツールでソースコードをチェックし、問題があればコミットを拒否するようにする設定はよくある。コミットが拒否されたら、開発者はソースコードを手直ししてもう一度コミットするわけだが、この手順は結構機械的だったりする。

tslintは`--fix`オプションを渡せば、自動修正してくるものもある。なので、考え方を一歩進めて、問題を報告するのではなく、問題があるなら勝手に直してそのままコミットに含めてしまったほうが、だいたいのケースで無駄な手順が省ける。そうなっていれば、開発者も「コミットする前にリントしなくちゃ」といったことを意識しなくても良くなる。

本稿では、この考えのもと、コミット時にコードを自動修正する方法を紹介する。

必要なパッケージを入れる:

```
yarn add --dev husky lint-staged tslint prettier tslint-config-prettier tslint-plugin-prettier
```

* husky: git commit したときにlint-stagedを走らせるために必要
* lint-staged: git addされたファイルに対してtslintなどをかけるようにするために使う
* tslint, prettier: TypeScriptコードのスタイルを整形する
* tslint-config-prettier: tslintのルールのうちprettierとぶつかるものを無効化してくれる
* tslint-plugin-prettier: prettierをtslintの中で使う

必要なパッケージが入ったら、まず`package.json`を変更する。

package.jsonの`scripts`(NPMスクリプト)に`precommit`を追加し、`lint-staged`を呼び出すようにする。こうすることで、`git commit`したタイミングでリントが自動的に走るようになる。

```package.json
{
  "scripts": {
    "precommit": "lint-staged"
  }
}
```

同じく、package.jsonに`lint-staged`のフィールドを追加する。

```package.json
{
  "lint-staged": {
    "*.{ts,tsx}": [
      "tsc --noEmit",
      "tslint -p tsconfig.json -c tslint.json --fix",
      "git add"
    ]
  }
}
```

この設定例は3つのステップに分かれる:

1. `tsc`でコンパイルできるかチェック
2. `tslint`でチェックしながら、直せるコードは自動修正
3. 最後に(チェックがここまで問題なければ)、ステップ2で修正されたコードを`git add`

その後、`git commit`に続く流れになる。つまり、開発者はとくに意識することなく、コミットしたコードが自動修正された状態になる。


続いて、prettierの設定。

```json:.prettierrc
{
  "singleQuote": true,
  "semi": false,
  "trailingComma": "all"
}
```

最後に、tslintの設定。`extends`で`["tslint-plugin-prettier", "tslint-config-prettier"]`を追加しておく。また、`rules`に`"prettier": true`も加える。


```tslint.json
{
  "defaultSeverity": "error",
  "extends": ["tslint:recommended", "tslint-plugin-prettier", "tslint-config-prettier"],
  "jsRules": {"no-unused-expression": true},
  "rules": {
    "arrow-parens": [true, "ban-single-arg-parens"],
    "interface-name": [false],
    "linebreak-style": [true, "LF"],
    "max-line-length": [true, {"ignore-pattern": "<\\w+>"}],
    "member-access": [true, "no-public"],
    "no-any": true,
    "no-irregular-whitespace": true,
    "number-literal-format": true,
    "object-literal-sort-keys": [true, "match-declaration-order-only"],
    "prettier": true, // ここ
    "quotemark": [true, "single", "jsx-double"]
  },
  "rulesDirectory": []
}
```

以上で、git commitしたときに、tslint+prettierで自動的にコードを修正できるようになる。
JavaScriptでfor文を使わずに、<ul>の全ての子要素を消す方法

# やりたいこと
JavasScriptリストに子要素があったら、その子要素を全て消したい！

```html:index.html
<ul id="abc_list">
  <li>a</li>
  <li>b</li>
  <li>c</li>
</ul>
```
# やりたくないこと

要素分ループさせて、子要素をひとつずつ消していく

ちょこっと調べてみて一番回答の多かったのはこの方法でした。
･･･やりたくなかった。だっていついかなるときだって全部消すんだもん！
ひとつひとつのデータなんて意識せずにコード書きたい！！

```javascript:index.js
var ul = document.getElementById("abc_list")
var ulLen = ul.children.length

for (var i = 0; i < ulLen; i++) {
  ul.children[0].remove()
}
```

# お気に入りの逸品

```javascript:index.js
document.getElementById("abc_list").innerHTML = ""
```

# 感想

なんだ、簡単なことだったや！
Google Apps Script でのwebアプリ開発時に html ファイル分割を複数階層にできるようにする

## 概要

Google Apps Script でのwebアプリ(SPA)開発においては, [公式ドキュメント](https://developers.google.com/apps-script/)で[複数のhtmlを統合して表示する方法](https://developers.google.com/apps-script/guides/html/best-practices)が紹介されています。
しかし, この公式の方法を直接用いると, `doGet()` で呼び出された html ファイル内でのみしか他のhtmlファイルを読み込むことはできず, そのため, 複数階層に html ファイルを分割するようなことはできません。
そこで, 本稿では, 公式の提示した実装に若干の変更を加えることで, 複数階層にわたる html ファイル分割を実現するための実装を提示します。

## 背景:公式の提唱手法とその限界
Google Apps Script においては, gs ファイルと html ファイルのみが許容されています。

しかし, 公式ドキュメントの[HTML Service: Best Practices](https://developers.google.com/apps-script/guides/html/best-practices)の Separate HTML, CSS, and JavaScript の項目には, 以下のようなコード(抜粋)を用意することで, 疑似的に html, css, JSファイルを分けることができると紹介されています。

```code.gs
function doGet(request) {
  return HtmlService.createTemplateFromFile('Page')
      .evaluate();
}

function include(filename) {
  return HtmlService.createHtmlOutputFromFile(filename)
      .getContent();
}
```

```Page.html
<html>
  <head>
    <base target="_top">
    <?!= include('Stylesheet'); ?>
  </head>
  <body>
    <h1>Welcome</h1>
    <p>Please enjoy this helpful script.</p>
    <?!= include('JavaScript'); ?>
  </body>
</html>
```

ここで,` <?!= … ?>` はサーバサイドの式を呼び出す構文です。
`code.gs` で定義された`include()`をそれぞれの場所で評価することで, `Stylesheet.html` および `JavaScript.html` を展開できるということです。

しかし, この実装では, たとえば `JavaScript.html` 内で再び ` <?!= include(...); ?>` を記述して(`Page.html`から見れば)孫の呼び出しを行うことはできません。行うと, ` <?!= include(...); ?>` が文字列としてそのまま表示されます。

サイトの規模が多少大きくなってくると, これでは不便なことが出てきます。

## 本題

そこで, サーバサイドの`include()` 関数を以下のように書き換えます。

```code.gs
function include(filename) {
  var template = HtmlService.createTemplateFromFile(filename);
  var html = template.evaluate().getContent();
  return html;
}
```

ファイルから直接 [htmlOutput オブジェクト](https://developers.google.com/apps-script/reference/html/html-output) を得るのではなく,  まず [template オブジェクト](https://developers.google.com/apps-script/reference/html/html-template) を得て, その中身を評価(`template.evaluate()`)してから htmlOutput を得るようにしています。

すると、呼び出し先の`html`ファイルにおいて記述した`include()`も評価されるようになり, 結果として再帰的にファイルを読み込めるようになります。

## 補足

循環的に `include()` が呼ばれると無限ループになるので, それは防ぐようにしたほうがいいかもしれません。
Blender歴２年で覚えておいてよかったショートカットキーを列挙してく

#はじめに
 **Blenderって無料で使い勝手良いらしいけど、
何から触ったらいいか分からねえ　_:(´ཀ`」 ∠):**

<br>
ってことが２年前の私にもありました。

ので

###**今回はBlender初心者必見！**
**使えるショートカットキー集です！！！**

#これは覚えとけ！
###①３種の神器　【R S G】

**この3つのキーがあれば、とりあえず出来る。**
下絵を付けたらさらにいい感じになる。

- #### Rキー（回転）
    - オブジェクトの原点を軸に回転ができる

- ####Sキー（拡大・縮小）
    - 同じく原点を軸に拡大・縮小ができる

- ####Gキー（移動）
    - オブジェクト単位で自由自在に動かせる

###②テンキーでカメラ制御　【１〜０キー】　

**テンキーがついてなくても模倣出来るので絶対覚えておいてほしい**
<img width="208" alt="スクリーンショット 2019-06-13 12.32.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436651/525eaef5-f663-45f2-2170-78eb59bfad58.png">
####個人的に、１、３キーには常に指を置いてます。

######これを知ってると知ってないとでは差がすごい（小並感

##実践しながら覚えるリスト
| キー　| 　何ができる？　|備考|
|:---:|:--:|:---:|
| A|**オブジェクト全選択**||
| E|　**押し出し**|”如意棒”を想像してほしい|
| C|**選択するときに使う**|色を塗るように面など選択できる|
| K|　**カット**|複雑な模様、修正に使うイメージ|
| X|　**削除**|Deleteじゃない|

##実践しながら覚えるリスト（Shift＋　編）
| キー　| 　何ができる？　|備考|
|:---:|:--:|:---:|
| Shift＋A|**メッシュ生成**|あんまり使わない|
| Shift＋D|　**オブジェクト複製**|使用頻度高め|
| Shift＋Z|**レンダーモード**|別窓でレンダー開く方が楽かな|

これくらいあればなんとなく操作できます。


## さいごに
2017年からBlenderに触れ、2年経ちましたが
**”創造物をどれだけ早く綺麗に作れるか”**のレベルが上がったような気がします。
ショートカットキーも　**どれだけ早く作れるか**という点で必須になってくるので
慣れておいて損はないと思います( ´ ▽ ` )。

<br>
最後まで読んでいただきありがとうございました。
ショートカットキーを覚えずに、画面管理をトラックパッドでしたい人にオススメのSwish

画面管理には[Spectacle](https://www.spectacleapp.com/)や[BetterSnapTool](https://folivora.ai/bettersnaptool)などがよく使われるかと思われます。
十分便利なのですがショートカットキーを覚えないといけなかったり、
元々使用していたショートカットキーが使えなくなるなど、ちょっと困ったこともあります。

そこで紹介したいのが **[Swish](https://highlyopinionated.co/swish?ref=producthunt)** 
トラックパッドでの操作がメインで、ショートカットキーもすごく少ないです。
現在は一週間無料で使えます。

操作感は以下の動画が参考になります。
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Swish — The missing gesture layer for macOS. <a href="https://t.co/Sn3aIb10Ct">https://t.co/Sn3aIb10Ct</a> <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a>さんから</p>&mdash; muuuuminn (@4ho_v) <a href="https://twitter.com/4ho_v/status/1138992531792777216?ref_src=twsrc%5Etfw">2019年6月13日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#操作概要
基本的にウィンドウの上部かDockのアイコン上でスワイプ or ピンチをして操作します。
なかには ⌘ や shift を押しながらスワイプをする操作もあります。
fnキーを押している間は、Swishの操作は無効になります。
<img width="1020" alt="スクリーンショット 2019-06-13 12.04.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241915/095ed40c-4661-1e28-1c67-32633494e251.png">

<img width="98" alt="スクリーンショット 2019-06-13 12.17.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241915/72b00faa-91d5-f78f-d686-966789869bab.png">

#設定
###Windows
<img width="802" alt="スクリーンショット 2019-06-13 12.28.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241915/e5945122-49ae-4074-828e-79d57b7619e2.png">
**General**
ウィンドウの拡大縮小、閉じる、アプリケーション終了など。
自分の環境だとピンチが動作しないです…。
なのでFullscreen、Close、Quitの操作はoptionを押しながら実行しています。

**Snapping**
Move Cursor with Windowの設定はデフォルトでoffになっています。
onにするとスワイプしたウィンドウに対してカーソルが追従するので、さらに快適になります。

**2×2 grid**
画面分割
VerticalやQuartersの操作のコツとしては、細かく動かすことです。

**2×3 grid**
同じく画面分割
shiftを押しながら操作する。
細かく分けたいときはこちらの操作をよく使う。

###Dock
<img width="800" alt="スクリーンショット 2019-06-13 12.26.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241915/fe703e5c-1072-e8b7-7f2f-5ac9673b17e2.png">
**Dock**
Dockのアイコン上でスワイプしていきます.
ウィンドウを開いたり閉じたり。
CycleとChainの操作がイマイチわからない…。

**MenuBar**
この操作だけ画面上部のメニューバーでのスワイプになります。
<img width="1096" alt="スクリーンショット 2019-06-13 12.37.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241915/68198f93-b640-ea9f-df1d-3da4ca2bd1e5.png">

###Screens
<img width="801" alt="スクリーンショット 2019-06-13 12.23.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241915/bf76211b-b712-9aed-6ea5-f204d9963b1d.png">
初期設定ですと ⌘ を押しながらスワイプでディスプレイ間を移動できます。
ディスプレイを二枚以上使用している場合に、便利です。
一枚の場合は、移動先のディスプレイがないため機能しません。

##最後に
まだ若干操作が安定しないですが
機能がシンプルにまとまっており、今後に期待です👍

##参考
[Product hunt](https://www.producthunt.com/posts/swish-7)
Flutterで作ったアプリをストア公開するときの手間取った話

先日初めてFlutterで作成したアプリをiOSおよびAndroidのストアに公開しました．公開手順は公式ドキュメントに従っていれば基本的に問題はないですが，手間取ったところをまとめました．

なお，私は日頃からiOSアプリをネイティブで開発しており，ストア公開の経験もあります．Androidアプリに関しては数年に一度作成して遊ぶ程度で，Playストアに公開は今回が初めてです．

今回のFlutterの環境は以下の通りです．

```shell
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.5.4-hotfix.2, on Mac OS X 10.14.5 18F132, locale
    ja-JP)
 
[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.2.1)
[✓] Android Studio (version 3.4)
[✓] VS Code (version 1.34.0)
[✓] Connected device (1 available)

• No issues found!
```

### 追記

- 2019/07/11 Andoridアプリの64bitビルドに関して


# Androidアプリ 

公式ドキュメント

- [Preparing an Android App for Release](https://flutter.dev/docs/deployment/android)

## Proguard

ソースコード難読化のProguardで，一部のサードライブラリが機能しなくなりました．そこで，そのサードライブラリを対象から外しました．サードライブラリのパッケージはそのドキュメントを見るか，実際にAndroidプロジェクトを開けば，分かりました．

```
-keep class hogehoge.piyopiyo.**  { *; }
```

この確認作業はリリースビルドと実機インストールで念入りに確認しました．

```
$ flutter build apk --release
$ flutter install -d {device_id}
```

なお，device_id は ```flutter install``` をオプションなしで打てば一覧表示されます．



## Androidアプリの64bit対応

ストアに提出するには，32bitおよび64bitに対応する必要があります．推奨される app bundle (aab) でビルドするコマンドが用意されています．

```
$ flutter build appbundle
```

しかしながら，現状 (ver 1.5.4-hotfix.2, channel stable) だと，そのaabには64bitは含まれていません．すでにissueが立っており，ver 1.7 で対応予定だそうです．なお，dev channel に切り替えて使ってみましたが，Playストアからダウンロードするとクラッシュする不具合がまだ残っていました．

そこで，32bitおよび64bitそれぞれのapkを作成して，それら2つで申請しました．

(0) android/app/build.gradleに各アーキテクチャの設定を加える．

```gradle
defaultConfig {
   ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
}
```

(1) 32bitアプリをビルドする

```
$ flutter build apk --release --target-platform=android-arm
```

(2) ビルドした 32bit アプリを Google Play Console にアップロードする
(3) versionCode を増やす
(4) 64bit アプリをビルドする

```
$ flutter build apk --release --target-platform=android-arm64
```

(5) ビルドした 64bit アプリを Google Play Console にアップロードする

Play Consoleにアップロードすると「aabを使って」など警告が表示されますが，仕方ないのでそのままで公開しました．


### Flutter 1.7が公開されました （追記, 2019/07/11）

aabビルドの64bit問題を解決した Flutter 1.7 が公開されました．上記のように32,64bitそれぞれをビルドしなくても，aab1つで解決すると思います（自作アプリのアップデート予定が直近でないので未確認です，報告まで）．


# iOS アプリ 

公式ドキュメント

- [Preparing an iOS App for Release](https://flutter.dev/docs/deployment/ios)

基本的にFlutterのビルドコマンドを行うだけで，後は通常のiOSアプリのリリース作業と同じです．

 ```
 $ flutter build ios
 ``` 

以下を忘れずに

- バンドルIDや表示名を書き換える
- 証明書関連を設定する

なお，アーカイブ時に結構の数の warning が表示されてましたが，アプリ審査は無事に通りました．

---

### 参照

- [Preparing an Android App for Release](https://flutter.dev/docs/deployment/android)
- [Preparing an iOS App for Release](https://flutter.dev/docs/deployment/ios)
- [flutter build appbundleの64bit対応について - Continuity is The Father of Success](https://dr1009.hatenablog.com/)
- [Flutterで作ったアプリをiPhoneとAndroidの実機用にリリースビルドする｜nbht｜note](https://note.mu/nbht/n/nd4338701daa5)
- [Support APKs with 32-bit and 64-bit binaries within them · Issue #18494 · flutter/flutter](https://github.com/flutter/flutter/issues/18494)
ICカードで施錠、のメモ

ICカードで施錠 https://qiita.com/carpenders/items/94d29098127faaffe1fc

### Raspi NFC ラジコンサーボ
https://coro.hatenadiary.jp/entry/2015/12/23/233434

### Raspi nfc アプリケーション
https://coro.hatenadiary.jp/entry/2015/12/23/233434
https://kokensha.xyz/raspberry-pi/raspberrypi-sony-pasori-rc-s380-read-nfc-felica/
https://sunpro.io/c89/pub/hideo/ch03
http://pongsuke.hatenablog.com/entry/2017/05/17/164317
https://uepon.hatenadiary.com/entry/2018/06/12/223307
http://uchan.hateblo.jp/entry/2016/11/18/190237
https://qiita.com/LinaNfinE/items/945a795e53427e768e47

### Raspi NFC
https://kokensha.xyz/raspberry-pi/raspberrypi-sony-pasori-rc-s380-read-nfc-felica/
https://blog.shibayan.jp/entry/20150427/1430067533
https://9bo.hateblo.jp/entry/2016/06/26/215419
https://raspida.com/sony-s380-rpi0w

### Raspi NFC undefined symbol: ECDH_OpenSSL
https://github.com/nfcpy/nfcpy/issues/59

### Raspi ラジコンサーボ
https://www.indetail.co.jp/blog/170519/
https://wp.developapp.net/?p=3351

### Raspi GPIO
https://karaage.hatenadiary.jp/entry/2017/02/10/073000
http://oohito.com/nqthm/archives/2151
https://www.fabshop.jp/%E3%80%90-%E7%AC%AC30%E5%9B%9E-%E3%80%91pigpio%E3%81%A7%E3%82%82led%E4%B8%8D%E8%A6%81%E3%81%AEl%E3%83%81%E3%82%AB%EF%BC%81/
https://qiita.com/yuuri23/items/597fd1a40c63627e59c2
https://tomosoft.jp/design/?p=8768
https://www.fabshop.jp/%E3%80%90-%E7%AC%AC30%E5%9B%9E-%E3%80%91pigpio%E3%81%A7%E3%82%82led%E4%B8%8D%E8%A6%81%E3%81%AEl%E3%83%81%E3%82%AB%EF%BC%81/
http://nw-electric.way-nifty.com/blog/2018/11/rpigpio-pigpio-.html
https://l-w-i.net/t/raspbian/pigpio_001.txt
https://l-w-i.net/t/raspbian/pigpio_002.txt

### Raspi ReadOnlyFileSystem
https://teratail.com/questions/71314
https://flogics.com/wp/ja/2017/10/raspbian-os%E3%81%AEsd%E3%82%AB%E3%83%BC%E3%83%89%E3%82%92%E3%83%AA%E3%83%BC%E3%83%89%E3%82%AA%E3%83%B3%E3%83%AA%E3%83%BC%E5%8C%96%E3%81%99%E3%82%8B%EF%BC%88initrd-%E7%B7%A8%EF%BC%89/
http://rapidnack.com/?p=1891
https://gist.github.com/yoggy/8ddd630005d012635706f6813e10b334

### raspi シリアルコンソール
http://invalid-log.blogspot.com/2017/01/raspberry-pi-3.html

### Arduino RFIF ラジコンサーボ
https://ehbtj.com/electronics/diy-smart-lock/

### Arduino ラジコンサーボ
http://jobless-fish.com/1334

### Raspi SESAME
https://www.otwo.jp/blog/raspi_sesame_1/
http://www.otwo.jp/blog/raspi_sesame_2/

### ICカード記録情報
https://www.wdic.org/w/RAIL/%E3%82%B5%E3%82%A4%E3%83%90%E3%83%8D%E8%A6%8F%E6%A0%BC%20%28IC%E3%82%AB%E3%83%BC%E3%83%89%29
https://qiita.com/YasuakiNakazawa/items/3109df682af2a7032f8d

### サムターン機構
http://w3-works.blogspot.com/2015/03/blog-post.html
awsのmysql passwordを変更したい

awsでmysqlのpass設定を少し変えたくて探してました。

結果だけ書く。
成功した。成功した。成功した。成功した。成功した。成功した。成功した。成功した。（byシュタゲ）
``` sudo service mysqld stop
```
stopして、
```
mysqld_safe --skip-grant-tables &
```
を行なった。

すると、
```mysqld_safe A mysqld process already exists
```
が出たため、
```ps aux | grep mysqld
```

でprocessを調べ

sudo kill -9 0000(プロセス番号)

killした。

すると、safe modeで入れたので、
``` mysql -u root
```

```mysql> use mysql
```

```mysql> UPDATE user SET authentication_string=password('NEW_PASSWORD') WHERE user='root';
```

NEW PASSWORDのところに、passwordをいれて、enter!!!!!

```Query OK, 4 rows
```

みたいな奴が出ればOKです。　rowsは0とか 3とかなんでもいいかと。



localのmysqlと違うところは

``sudo
``
をつけるところがミソです！！！！
うまく行かなかったら、sudo つけて試してみんしゃい。

そうしないと、権限がない！と怒られちゃうのでね〜。
Dockerコンテナ上のChromeの動きが悪い時の対応方法

- 環境(Dockerコンテナ)
    - CentOS Linux release 7.6.1810 (Core)
    - Google Chrome:バージョン: 75.0.3770.80（Official Build） （64 ビット）
        - Googleアカウントにログインして同期済

# 事象:Chromeでなかなかページを表示できなくてタブを2つ開くと落ちる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/25e53418-59e5-ebc7-c204-15649b538832.png)

# 原因:メモリが不足しているから
[メモリ不足っぽいからメモリを見たい時に使ってみるコマンド - Qiita](https://qiita.com/ponsuke0531/items/fb81129723eb813a2c77)
## コマンドでChromeを起動してみる

```bash
# Chromeを起動する
$ /opt/google/chrome/chrome
[12536:12592:0613/104137.316187:ERROR:object_proxy.cc(619)] Failed to call method: org.freedesktop.Notifications.GetCapabilities: object_path= /org/freedesktop/Notifications: org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.Notifications was not provided by any .service files
[12567:12567:0613/104137.444963:ERROR:sandbox_linux.cc(368)] InitializeSandbox() called with multiple threads in process gpu-process.
[12536:12536:0613/104137.783170:ERROR:pref_model_associator.cc(111)] Failed to deserialize value of preference 'autofill_profile_validity': Line: 2, column: 2, Unexpected token.
# ページが表示されない・・・
[103:106:0613/104149.229263:ERROR:validation_errors.cc(76)] Invalid message: VALIDATION_ERROR_UNEXPECTED_NULL_POINTER (null field 1)
[103:111:0613/104149.229513:FATAL:memory.cc(22)] Out of memory. size=4194304
[12536:12536:0613/104421.877311:FATAL:memory.cc(22)] Out of memory. size=131072
[12571:12595:0613/104422.007226:ERROR:broker_posix.cc(43)] Invalid node channel message
[12571:12595:0613/104422.008593:ERROR:broker_posix.cc(106)] Error sending sync broker message: Broken pipe (32)
# タブを2つ目のタブを開いてページを表示しようとしたら落ちた
Trace/breakpoint trap (core dumped)
```

## 対応1:メモリを節約しながら使う
- Googleアカウントでログインして同期するのをやめる
- キャッシュをクリアする
- [メモリ使用量を減らし軽くする方法8選| Aprico](https://aprico-media.com/posts/2094)
- [タブのメモリを自動解放 - PC設定のカルマ](https://pc-karuma.net/google-chrome-improved-memory-use-enable-tab-discarding/)

## 対応2:Chromeが使う/dev/shmのサイズを増やす
- [Docker上のpuppeteerがPage crashしてしまうときはshmサイズを疑う - Qiita](https://qiita.com/windyakin/items/00b085902547570eebc6)
- [/dev/shmってなんだ？ | 日経 xTECH（クロステック）](https://tech.nikkeibp.co.jp/it/article/Keyword/20070330/267007/)
- [Dockerで使っているコンテナを作り直す方法 - Qiita](https://qiita.com/ponsuke0531/items/9336172e812e7271a966)
たくさんのサーバーにコマンドを投げるbashスクリプト

# はじめに
覚書レベルのメモです。
いろいろ不備があると思いますが、ご容赦くださいませ。

## たくさんのサーバーにコマンドを投げる
たくさんのサーバーにコマンドを投げる要件って、結構あったりします。
sshコマンドをエディタで作って、シェルに貼り付けながら実行するって、サーバー運用している経験のあるエンジニアではよくある話かと思います。

### それシェルで
１０数年前になんかの本をみて書いた手前のシェルスクリプトを使って、全体にコマンドを投げ終えると
「え？もう？」という感じの反応をまわりから受けます。
物理サーバー時代の老兵な私が使い回している、とてもとても古いシェルですので、見せるものではないと思っていたのですが、何故か意外と好評みたいなので、その手前シェルをこちらに公開します。

https://github.com/yuzukaki/my-tools/blob/master/ryz.sh

```
    
#!/bin/bash
function kill_children {
    pkill -P $$;
    wait;
}
trap "kill_children" EXIT
cmd=$1
shift
for host in web01 web02 web03 web04 #web05 web06 web07 web08;
do
	ssh $host $cmd $* &
#	echo $host $cmd $* &
done
wait
```

対象サーバーは

```
for host in web01 web02 web03 web04 #web05 web06 web07 web08;
```

ここのところを調整します。
このスクリプトを改良してhostsから自動取得する処理を書いた同僚もいましたが、用途に合わせてご自由にどうぞです。

### 注意
唯一不具合として「tail -f」みたいなコマンドを投げると全サーバーのログをtailできたりして便利なのですが、
「tail -f」に関しては、このスクリプト終了後にリモート先のサーバーにプロセスが残ってしまう場合があるらしいです。
.zsh-history がこわれたというエラーの対処法

zshでコマンドを入力するたびに、下記のようにエラーメッセージが出力されるようになった

```
zsh: corrupt history file /home/xxx/.zsh_history
```

## 原因
.zsh_historyで@が連続した行が生成されて解読不能になっている

## 対処法
.zsh_historyの@が連続した行を削除すればOK.
GPSの研究　その51

#概要

gpsを理解したかった。
アグリナビで、遊んでみた。
wemosで、gpsシュミレータ作って、動かしてみた。
wifiなgpsに見える。

#写真

![DSCN0336.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/c344405c-5818-ad77-e569-49bcc67c3d24.jpeg)
![DSCN0337.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/d7e16134-88b3-c34b-8718-f52e73a2a89f.jpeg)

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/949827a2-3dca-22df-fb95-d7b3e7ce8377.png)

#仕掛け

wemosをwifi親機にする。アグリナビから、wifiに入ると192.168.1.100のipアドレスを与える。
アグリナビのGPSを0,0,0,0　2019にする。
wemosから、192.168.1.100のポート2019に偽nmeaを送りつける。


以上。
Androidのエミュレータでhostsを書き換える

## 概要
Androidのエミュレータでhostsを書いていないと見れない環境にアクセスする場合の対処方法です。

## 準備
adbコマンドを使えるようにします。恐らく、Androidを開発している人であればSDKが入っているので、下記のような方法でPATHを通しておきます。 

```bash:.zshrcなど
export PATH=$PATH:/Users/musclemikiya/Library/Android/sdk/platform-tools
```

エミュレータがGooglePlayベースではないことを確認します。（adb rootになれない）
https://stackoverflow.com/questions/43923996/adb-root-is-not-working-on-emulator


## 手順
ローカルの/etc/hostsファイルを同期します。

```bash
adb root && adb remount && adb push /etc/hosts /system/etc/
```

## トラブルシュート

### エラーが出る場合
```
adb: error: failed to copy '/etc/hosts' to '/system/etc/hosts': remote couldn't create file: Read-only file system
```

上記のエラーが出る場合は、一旦エミュレータを落とし、下記コマンドで立ち上げます。（端末名のところは適宜書き換え）

```bash
$ emulator -writable-system -netdelay none -netspeed full -avd Pixel_2_XL_API_28
```

emulatorはadbコマンドと同じくsdkフォルダの中にあります。

### 127.0.0.1に接続したい
PC上のローカル環境で開発していて、そこに接続したい場合、エミュレータからはlocalhostでは接続できません。そのかわり、ローカルPCには10.0.2.2というIPが割り当てられているので、一時的にhostsを書き換えると接続できます。
Pythonでソートアルゴリズムの再発明をしてみる: 挿入ソート

# 概要
* Pythonでソートアルゴリズムを再発明してみるだけ
* 今回は挿入ソートについて
* 参考サイトのサンプルコードをできるだけ見ずに実装する
* とりあえず昇順ソートのみの対応とする

# 挿入ソートの概要
* ソート済みの配列の中の適切な位置に未ソートの要素を挿入することを繰り返すアルゴリズム
* シンプルで実装が容易である一方、基本的に遅い
* 遅いけどバブルソートよりはマシ
  * 要素を挿入する処理について、挿入箇所が見つかればそこでループが終わる
  * ほぼソート済みの配列を処理する場合は速い
* 安定ソート

## 基本的な手順
1. 左端の要素を「ソート済み」とみなす
2. 左端の次の要素を「未ソート」とみなす
3. ソート済み要素（の右端）と未ソート要素を比較し、大小関係が逆なら、未ソート要素をソート済み要素の中の適切な位置に挿入して「ソート済み」要素とする。大小関係が合っていれば、その位置のまま「ソート済み」要素とする
4. 比較する要素両方を1つ右にずらしながら手順3を繰り返す。
5. 右端まで処理が終わったらソート完了

# ソース
```python
import random

def insertion_sort(lst):
    # 配列走査するループ
    # 左端は「ソート済み」なので1から開始
    # 「ソート済み」といってもコード上ではその概念は登場せず、ループカウンタのある時点の値より前がソート済みということになる
    for i in range(1, len(lst)):
        # ソート済み要素の右端（つまりソート済み要素の中での最大値）と、未ソート要素の左端の大小関係比較
        # ループカウンタiの現在の値は未ソート要素、i-1はソート済み要素の右端を指す
        # 未ソート要素のほうが小さい場合は、未ソート要素をソート済み要素の中に挿入しないといけない
        if lst[i-1] > lst[i]:
            # 挿入箇所を探すためのループ
            # ソート済み要素の左端から見ていって、未ソート要素のほうが小さくなる最初の位置に挿入すればいい
            for j in range(0, i):
                if lst[j] > lst[i]:
                    # Pythonにはinsertメソッドがあるので便利
                    # そのような機能がない言語の場合は、挿入箇所以降を全部後ろにずらす処理が必要になる
                    lst.insert(j, lst[i])
                    # insertメソッドの機能は移動ではなく新規追加なので、元の要素を消す必要がある
                    # insertメソッドで要素が一つ増えているため、iではなくi+1が元の要素の位置
                    del lst[i+1]
                    break


lst = list(range(10))
random.shuffle(lst)

print("ソート前: " + str(lst))

insertion_sort(lst)

print("ソート後: " + str(lst))
```

# 参考サイト
* https://ja.wikipedia.org/wiki/%E6%8C%BF%E5%85%A5%E3%82%BD%E3%83%BC%E3%83%88
クイズ-出力されるのは何でしょう？-

# もんだい
以下のA,Bではそれぞれ"OK"と"NG"のどちらが出力されるでしょうか？


```javascript:javascript
text = ["OK"];
function hoge(array){
    array[0] = "NG";
    return array;
}

console.log(hoge(text)); // A
console.log(text); // B
```

# こたえ

<details><summary>クリック！</summary><div>

```:出力
> ["NG"]
> ["NG"]
```
どっちも["NG"]が出力されます。
javascriptでは配列を引数にとると参照先が渡されるので、中身を直接操作することになります。

</div></details>

# じゃあこれは？

```javascript:javascript
text = ["OK"];
function hoge(array){
    array = ["NG"]; // ここだけ変更。
    return array;
}

console.log(hoge(text)); // A
console.log(text); // B
```
# こたえ
<details><summary>クリック！</summary><div>

```
> ["NG"]
> ["OK"]
```

`array = ["NG"];`と代入した時点で参照先が変更されるため、元の配列には影響しません。

</div></details>

# まとめ
要するにこれ↓読めばわかります。

【Javascript】値渡しと参照渡しについてあらためてまとめてみる https://qiita.com/migi/items/3417c2de685c368faab1

代入の形をとるか直接操作するかで結果が変わる。
その仕様がわからなくてめっちゃ詰んでたのでメモしました。
我が家のIoT状況

# 我が家のIoT状況


自宅のIoT機器の構成どうなってるの？聞かれることが多いので、図を作ってみました。

Wi-Fiが２つ登場しますが、これは同じ個体です。データが左から右へ流れるような図にしたかったので、こう書きました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/99557613-9ebd-f7eb-5046-f2810993a6b6.png)


# Nature Remo

Nature Remoのおかげで、IoTに対応していないプロジェクターやエアコンも、赤外線経由で制御ができるようになります。おすすめです！

# IFTTT

ほとんどのIoT製品が、専用のスマホアプリを持っており、細やかな制御ができるようになっていますが、複数のIoT製品を一括で管理したかったので、すべての制御をIFTTTに集約させています。

IFTTTに出勤時、帰宅時、就寝時等の設定を作り、そこに様々なIoT製品の制御内容を登録すると便利です。
𠮷野家は何文字ですか？👍🏽は？

# 新たな刺客👍🏽 (U+1F44D + U+1F3FD)
https://github.com/sallar/stringz
𠮷野家は四天王のうちで最弱だったのかもしれない。

# 各言語の結果
## JavaScript
"𠮷野家".length -> 4
[..."𠮷野家"].length -> 3

"👍🏽".length -> 4
[..."👍🏽"].length -> 2

## Go
len(“𠮷野家“) -> 10
len([]rune(“𠮷野家“)) -> 3

## Python2
len("𠮷野家") -> 10

## Python3
len("𠮷野家") -> 3
len("𠮷野家".encode()) -> 10

## Ruby
"𠮷野家".size -> 3
"𠮷野家".bytesize -> 10

## PHP
strlen("𠮷野家") -> 10
iconv_strlen("𠮷野家") -> 3
mb_strlen("𠮷野家") -> 3

## Java
"𠮷野家".length() -> 4
"吉野家".codePointCount(0, "吉野家".length()) -> 3

## C# ##
"𠮷野家".Length -> 4
new StringInfo("𠮷野家").LengthInTextElements -> 3

## C
strlen("𠮷野家") -> 10
wcslen(L"𠮷野家") -> 3 または 4 ※
※ ワイド文字が何かによって異なる。LinuxなどUTF-32の場合は3、WindowsなどUTF-16の場合は4。

# 簡単な解説
バイト長 -> 10
UTF16表現での長さ -> 4
コードポイントでの長さ -> 3

## 他の言語の結果
編集リクエスト募集中です

## おまけ
昔app engineで作ったサイトが出てきました。
https://unicodechar.appspot.com

「㍾㍼㋿」とかを互換分解(NFKD)してニヤニヤしてください。
Windowsで素早く画面ロック

# はじめに
自分向けの覚書レベルのメモです。
いろいろ不備があると思いますが、ご容赦くださいませ。

> 2020/11/12追記
> Windows7のときの記事でしたが、Windows10でも使えました。

## 素早く画面ロック
古今、いろんなインシデントがある世の中。
席を外すときはできるだけ画面ロックする癖をつけると良いと私は思っています。
なので、席を外すときは以下を意識的にやってます。

### 画面ロックのショートカット

```
Windowsキー + L
```

## 間違えるショートカット
急いでいるとLキーを間違えてショートカットを作動させてしまうことがあります。

### 拡大鏡
いきなり画面の一部が拡大されるので、ちょっとびっくりします。

```
Windowsキー + ; (セミコロン)
```
慣れてないと拡大鏡の終了のさせ方に慌てるかと思います。
でも、そんなときは慌てずに

```
Windowsキー + ESC
```
で拡大鏡を終了できるので、これも覚えておくと良いかもしれません。