OmniAICreator/Qiita-1.07M huggingface dataset:
GCP Cloud FunctionsでMeCab + Neologdの分かち書きAPIをデプロイする（Python）

# 背景
Neologdの辞書が重すぎて、Cloud Functionsに乗らない。
でも、サーバ料金を押さえたいので、なんとかして乗せたい。お金ない。

・環境
Mac macOS Mojave(10.14.2)

・Cloud Functions
言語はPython3、トリガーはhttpです。

# 参考記事
https://qiita.com/carrotflakes/items/d3bab5a81817c7e7edc0

# 方針
参考記事に書かれているように、neologd辞書を```--eliminate-redundant-entry```で縮小し、zip化することで100MB以下に納め、デプロイするという作戦です。

--eliminate-redundant-entry オプションとは
[mecab-ipadic-NEologd](https://github.com/neologd/mecab-ipadic-neologd/blob/master/README.ja.md)
>"--eliminate-redundant-entry" オプションを指定した場合は、正規化済みの日本語テキストを単語分割するための別称・異表記・表記揺れなどを一切考慮できない辞書を、512MByte 程度の空きメモリ領域があればインストールできます。

## Functionのデプロイ方法
1. APIのコードとneologd辞書をzip化(mecab.zip)してCloud Storageに配置
2. Storageのパスを指定してFunctionを作成します

デプロイコマンドはこんな感じ。

```bash
gcloud beta functions deploy mecab \
  --source=gs://<バケット名>/mecab.zip \
  --stage-bucket=<バケット名> \
  --trigger-http \
  --memory=512MB \
  --runtime=python37 \
  --region=asia-northeast1 \
  --project=<プロジェクト名>
```

## mecab.zip
mecab.zipは下記ファイルとフォルダを一つのzipにしたものです。
このmecab.zipは、上記デプロイコマンドを打つ前にStorageにデプロイしておきます。

```bash
$ tree
.
├── main.py  # Functionのコード
├── neologd-light  # 辞書
│   ├── char.bin
│   ├── dicrc
│   ├── left-id.def
│   ├── matrix.bin
│   ├── pos-id.def
│   ├── rewrite.def
│   ├── right-id.def
│   ├── sys.dic
│   └── unk.dic
└── requirements.txt
```

下記コマンドでmecab.zipを作成します。

```bash
$ zip -r mecab.zip *
```

```bash
$ tree
.
├── main.py
├── mecab.zip  # 作成されたmecab.zip
├── neologd-light
│   ├── char.bin
│   ├── dicrc
│   ├── left-id.def
│   ├── matrix.bin
│   ├── pos-id.def
│   ├── rewrite.def
│   ├── right-id.def
│   ├── sys.dic
│   └── unk.dic
└── requirements.txt
```

# 各ファイルの説明

## neologd-light（辞書）
Mac上でMeCabとNeologdをインストールし、作られた辞書データを使用します。
環境依存だと思っていたのでダメ元だったのですが、Cloud Functions上でそのまま動作しました。

ここでは、MeCabのインストール方法は割愛させてください。

Neologdを```--eliminate-redundant-entry```オプション付きでビルドします。

```bash
$ git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
$ cd mecab-ipadic-neologd/
$ ./bin/install-mecab-ipadic-neologd -y -p $HOME/neologd-light -n --eliminate-redundant-entry
```

ホームディレクトリに```neologd-light```が作成されました。

## main.py

```python
import os
import json
import MeCab

# MeCab準備
# リクエスト毎ではなく、インスタンスが立った時にだけ読み込まれる
neologd_path = os.path.join(os.path.abspath(
    os.path.dirname(__file__)), "neologd-light")
mcb = MeCab.Tagger('-d ' + neologd_path)
mcb.parse('')


def mecab(request):
    if request.method == 'GET':
        if request.args and 'text' in request.args:
            text = request.args.get('text')
            parsed_text = mcb.parse(text)
            return json.dumps({'p_text': parsed_text}, ensure_ascii=False)
        else:
            print('No text.')
            return ('Bad Request', 400)
```



## requirements.txt

```text
mecab-python3==0.996.2
```
ObjectMapper failed to serialize responseが出たらJSONを疑え

##はじめに
APIでJSONを取得してくる時に、静かにエラーになっていた。
ニュースアプリを作っているのですが、記事の筆者の情報が取れていなかった。

##環境
pod 'AlamofireObjectMapper', '~> 5.2'
pod 'ObjectMapper', '~> 3.4'
Swift4.2
Xcode11
target🎯 iOS:12.1

##エラーと対処法
```NetworkUtils.swift
let requestReference = Alamofire.request(url, method: .get).responseArray(keyPath: keyPath) { 
  (response: DataResponse<[T]>) -> Void in
      if let result = response.result.value {
            observer.onNext(
            observer.onCompleted()
       } else if let error = response.result.error {
            (こっちに入っていた)
       }
```

errorを見てみると、
↓
ObjectMapper failed to serialize response
とある。

調べてみるとJSONの内容が怪しいとのこと。

JSONが正しいか判断してくれるサイト↓
https://jsonlint.com/

ここで、無駄な改行を消したらソースは変更せずに解決しました！
Udemy 「Unityゲーム開発入門」講座受講ノート　3 - 8 Unity でゲームを作るには


Udemyの講座 「Unityゲーム開発入門」で学習した内容まとめ


# 8.Unity でゲームを作るには

##Unityエディタを使ってみる
◎トランスフォームのx、y、zをマウスでドラッグしてで数値を変更できる（手動）
◎コンポーネントを操作する「スクリプト」を作成し、オブジェクトに貼り付ける


##関数
:gear:GetComponent関数
スクリプトで　:tools:Transform コンポーネントの値を取得して変化させる
その他、 :tools:Box Collider などいろいろなコンポーネントを取得して操作する



##タイミングに関する関数
:gear:Start (オブジェクトが生成された時に実行される)
:gear:Update  (1/60秒とかで更新されるたびに実行される)


##:bulb:ゲームの作り方まとめ
:one:ゲームはゲームオブジェクトによってできている
:two:ゲームオブジェクトはコンポーネントの集まりでそのパラメータで設定される
:three:開発者はそれらのパラメータをスクリプトで取得して操作する
:four:どのタイミングで動かすかをStart,Update、その他のUnityが準備した関数で設定する
:five:何を動かすかは開発者が作成し、適切なタイミングにコードを設定していく

-------------------------------------------------------------------------
##教材
**Udemy Unity ゲーム開発入門：インディーゲームクリエイターが教えるマリオのようなゲームを作成する方法**
https://www.udemy.com/course/studio_shimazu_sideview_action/
OpenpyxlでExcel操作入門＆TIPS

pythonでExcelを操作できるライブラリはいくつかありますが、
私が調べた中で唯一「.xlsm」の拡張子を扱うことのできたライブラリ**Openpyxl**について記事にします。

## Openpyxl概要
公式ドキュメント：[https://openpyxl.readthedocs.io/en/stable/index.html](https://openpyxl.readthedocs.io/en/stable/index.html)

最新バージョン：2.6.2(2019/9/27現在)

ライセンス：MITライセンス

対応officeバージョン：office2010～

xlsx、xlsm等には対応できるが、**xlsは非対応**。


## インストール
以下のように、pipコマンドでインストールするだけ。

```:cmd
pip install openpyxl

```

## Excelを開いてみる

```python
from openpyxl import Workbook, load_workbook

# xlsm形式ファイルを開く場合
wb = load_workbook(filename="Excelファイルのパス", read_only=False, keep_vba=True)
ws = self.wb['シート名']

```

最低限、Excelファイルのパスを指定してload_workbookの引数に渡せば、pythonでExcelファイルを開くことはできる。

>read_only = False

読み取り専用(True)か書き込み可能(False)かを指定する。

>keep_vba = True

開いたExcelのVBマクロを読み込むかどうかを指定する。
読み込む → True、読み込まない → False
※ここで、Falseを指定すると、**保存時にVBマクロが動かなくなるので**、保存後もマクロを有効にしたい場合は、Trueを指定する。

## Excelを編集してみる

```python

# 書き込み
ws['A1'] = 'A1'

# R1C1形式でも指定可能
# 列数、行数は1から開始
ws.cell(row=2, column=3).value = 'C2'

# 読み取り
data1 = ws['A1']
data2 = ws.cell(row=2, column=3).value

# Bookの保存
wb.save("保存先Excelファイルのパス")

```

簡単な読み書きだけであれば、以上のことを覚えておくだけで完結する。

## より複雑な編集をしてみる
以下にただの読み書きよりも少し高度なExcel編集をTIPSとして羅列する。
まず、importしなければならないライブラリ

```python
from openpyxl.workbook.protection import WorkbookProtection
from openpyxl.styles.borders import Border, Side
from openpyxl.styles import Alignment
from openpyxl.styles.fonts import Font
from openpyxl.worksheet.datavalidation import DataValidation
from openpyxl.styles.fills import PatternFill
```

以下、ソースコード抜粋

```python

# 罫線の適用
# 罫線を定義
thinside = Side(style='thin', color='000000')
thisborder = Border(top=thinside, bottom=thinside, left=thinside, right=thinside)
ws['A1'].border = thisborder

# セルの塗りつぶし
# 塗りつぶしルールを定義
fill = PatternFill(patternType='solid', start_color='ffff0000', end_color='ffff0000')
ws['A1'].fill = fill

# ズームの変更
ws.sheet_view.zoomScale = 75 # 75%に変更

# データの入力規則の適用
# 選択肢A~Dで空白を許可する
data_valid = DataValidation(type='list', formula1='"選択肢A,選択肢B,選択肢C,選択肢D"', allow_blank=True)
data_valid.add(ws['A1'])

# シートの保護
ws.protection.enable()

# ブックの保護
wb.security = WorkbookProtection()
wb.security.lockStructure = True

```

## さいごに
今回は、xlsmのファイルを扱うためにOpenpyxlを使用したが、
他のExcel操作のpythonライブラリも試して、
各ライブラリの比較とかできたらよいなと心の片隅に思った…(思っただけ)
PythonでJSON 読み込み


## 下準備
使用する json ファイルを作成しておきます。
ファイル名は`qiita_json.json`にしました。

```json
{
    "section1":{
        "key":"key1",
        "number": 1
    },

    "section2":{
        "key":"key2",
        "number": 2
    }
}
```

## モジュールをインポート
まずはモジュールをインポートしましょう。

```python
import json
```
# ファイルを開く
下のように読み込みたいファイルを指定して**open関数**で開いてあげます。
**r**はreadのrです。
`変数1 = open('読み込みたいjsonファイルのパス','r')`

```python
json_open = open('qiita_json.json', 'r')
```

## 開いたファイルをJSONとして読み込む
先ほど開いたファイル(**変数1**)を**json.load関数**でJSONにします。
`変数2 = json.load(変数1)`

```python
json_load = json.load(json_open)
```

## 一旦見てみましょう
ではここまでの成果を確認してみましょう。

```python
import json

json_open = open('qiita_json.json', 'r')
json_load = json.load(json_open)

print(json_load)
```

### 実行結果
```
作業ディレクトリ>python qiita_json.py
{'section1': {'key': 'key1', 'number': 1}, 'section2': {'key': 'key2', 'number': 2}}
```

無事読み込めましたね!

### とりあえず何か値を取り出してみる
次は読み込んだJSONから**欲しいデータ**を取り出します。
例) `section1`の`key`の値を出力する。

```python
import json
json_open = open('qiita_json.json', 'r')
json_load = json.load(json_open)

print(json_load['section1']['key'])
```
### 実行結果

```
key1
```

はい、ちゃんと取れましたね!

このようにJSONで読み込むとpythonの辞書型として保存されます。
辞書型が不安な人はどっかで確認しておきましょう。

## for文で値をとる

```python
import json

json_open = open('qiita_json.json', 'r')
json_load = json.load(json_open)

#valuesで値をとってくる
for v in json_load.values():
    print(v)
```

### 実行結果
```
{'key': 'key1', 'number': 1}
{'key': 'key2', 'number': 2}
```

`section`ごとの値が取れましたね!!
でも多分これだと実用的じゃないので更に`number`の値だけとってこれるようにしましょう。

`print(v)`を`print(v['number'])`に変えるだけでおけです。

```python
import json

json_open = open('qiita_json.json', 'r')
json_load = json.load(json_open)

for v in json_load.values():
    #ここを変えました。
    print(v['number'])
```

### 実行結果
```
1
2
```

はい、できましたね!!

お疲れさまでした!!
# 参考
・[【Python入門】JSON形式データの扱い方](https://qiita.com/Morio/items/7538a939cc441367070d)
・[Pythonの辞書（dict）のforループ処理（keys, values, items）](https://note.nkmk.me/python-dict-keys-values-items/)

5 年くらいの時を経て書き込み編を書きました...
良かったら見てあげてくださいまし...

https://qiita.com/kikuchiTakuya/items/77be59dbd80c1117728a
esa.ioで図を書くならUML記法を使うと手軽にきれいにかける

esa.ioで図を書く場合は、UML記法を使うと、簡単にきれいに図を書けます。

詳細な書き方は、[PlantUML](http://plantuml.com/)を参考にしてください。

枠と要素を用いた例を書いてみます。

# 四角枠と要素の関連

```text
title:(例)クーポンを登録する

' 要素を左から右に並べる
left to right direction
'  四角枠の外の要素
(ラッパーAPI)

' 四角枠
rectangle フロント {
    (ラッパーAPI) <-- (処理1)
    (ラッパーAPI) <-- (処理2)
    (ラッパーAPI) <-- (処理3)
}
rectangle 基幹API {
    (ラッパーAPI) --> (クーポンを登録) :registCoupon
}
```

```plantuml
title:(例)クーポンを登録する

' 要素を左から右に並べる
left to right direction
'  四角枠の外の要素
(ラッパーAPI)

' 四角枠
rectangle フロント {
    (ラッパーAPI) <-- (処理1)
    (ラッパーAPI) <-- (処理2)
    (ラッパーAPI) <-- (処理3)
}
rectangle 基幹API {
    (ラッパーAPI) --> (クーポンを登録) :registCoupon
}
```

# 矢印の向きを変える

矢印の向き変更は良く使うのでまとめておきます。

矢印を縦向きにする場合は、「-」を2つにする。
矢印を横向きにする場合は、「-」を1つにする。

四角の枠内の要素が横に並んで、小さく縮小されてしまう場合は、
矢印の向きを縦とか横とか向きを変えると、想定通りに表示できたりします。

```uml
' 縦方向でAPI←処理1
(API) <-- (処理1)

' 縦方向でAPI→処理2
(API) --> (処理2)

' 横方向でAPI→処理3
(API) -> (処理3)
```

以下のように書いても矢印の向きを変更できます。
-right->
-left->
-down->	
-up->

詳細な表記は[PlantUML](http://plantuml.com/ja/sequence-diagram)を参照
うっかり屋さんのためのgit stash

# うっかりミスを技術で防止

僕は普段よくうっかりミスをします。
CLI上での時の流れは無慈悲なもので、エンター１つでけっこう面倒なことになったりします。
そんな無慈悲な時間を少しでも減らすために少し苦労をしてみましょう。

# git stashを慎重に

`git stash`コマンド使ってますか？
僕はこのコマンドでよく痛い思いをしました。

`git stash pop` ←これを連続で打ってCONFLICT起こしたりもしました。とても面倒です。

ですので今回は`git stash`をもっと対話的に実行しようということでShellでコマンドを自作しました。
普段はGoの[cobra](https://github.com/spf13/cobra)などを使っているのでShellには馴染みがなかったので今回色々勉強になりました。

# [2020/09/05更新] homebrewでコマンドを配布中

homebrewを通してこのコマンドを配布しておりますので、よろしければ使ってみてください。

https://github.com/RyuseiNomi/stpop

# 対話型コマンドのキーとなるread

うっかり屋さんはひとりで突っ走りがちですので、「〜だけど大丈夫？」みたいなワンクッションあると安心します。
それを実現するためにread構文を使って対話型のコマンドを実現できます。
例えば下は、stashしたブランチと現在いるブランチが違った時に確認をする処理です。

```shell
if [ $CURRENT_BRANCH != $TARGET_BRANCH ]; then
          echo "----------------------------------"
          echo "取り出そうとしているstashは現在のブランチの作業ではないです。取り出しますか？[y/N]"
          read IS_POP
          case $IS_POP in
              [yY])
                  echo "-------------------------------"
                  echo "選択したstashを残しますか？ [y/N]"
                  read IS_REMAIN_STASH
                  case $IS_REMAIN_STASH in
                      [yY]) eval git stash apply ${TARGET_STASH%%:*};;
                      [nN]) eval git stash pop ${TARGET_STASH%%:*};;
                  esac
                  ;;
              [nN]) exit;;
          esac
```

`read [変数名]`でユーザからの入力を受け取り、その情報を元にcaseで分岐しています。


# 入力の手間を少しでも省いてタイポを防止する

うっかり屋さんは誰から見られているわけでもないのにすごく焦ります。
異常なほどタイポします。
ですので、例えば
`git stash save "hogehoge"`
と打つ場合は`"`とか高確率でタイポします。
そんなタイポを減らすために以下のような処理を書くことが出来ます。

```shell
if [ "$1" = "save" ]; then
      echo "-----------------------------"
      echo "Stash内容の説明を入力"
      read STASH_MESSAGE
  
      eval git stash save "$STASH_MESSAGE"
```

こんな感じで引数に何かを渡すだけでメッセージの部分を形成して良い感じのコマンドに直してくれる。
やっていることは大したことありませんが、かなと英字を頻繁に入れ替える必要もなくなるので少し便利です。
Webプログラマがアプリ開発（ios,android）

* swift Objective-cは敷居が高い。
* 使い慣れたVS Codeでコーディングがしたい。
* はじめは簡単なアプリ作りたい

**そんな方にReact Native**
 ※少しReactかじった方が良いかも

## 環境
* mac
* XCode シュミレーター必須

# React Nativeのはじめ
[公式チュートリアル](https://facebook.github.io/react-native/docs/getting-started)

Expoの方ではなく、「React Native CLI Quickstart」を実施

- homebrewで各インストール

```
brew install yarn
brew install node
brew install watchman
brew tap AdoptOpenJDK/openjdk
brew cask install adoptopenjdk8
```


 - npmでreact-native-cliをグローバルへインストール

```
npm install -g react-native-cli
```

 - ソースを置くフォルダでinitして実行

```
react-native init AwesomeProject

cd AwesomeProject
react-native run-ios
```

Reactのモジュールが無いよとビルドエラーになった場合、以下のコマンドで、モジュール取得して再ビルドしたらいけた。

```
cd ios
pod install
```
[こちら参考](https://github.com/facebook/react-native/issues/25838)

動いたあとは、App.jsを修正していくことでアプリの開発が行える。　簡単
[JavaScript] console.time() で処理時間を計測する

# 方法

```js
// delay ミリ秒だけ待機するスリープ関数
let sleep = async delay => new Promise(resolve => setTimeout(resolve, delay));

console.time('タイマー');
await sleep(5000);
console.timeEnd('タイマー');
// タイマー: 5313.85595703125ms
```

# 参考

* MDN Web Docs
  * [console » タイマー](https://developer.mozilla.org/ja/docs/Web/API/console#Timers)
  * [Console.time()](https://developer.mozilla.org/ja/docs/Web/API/Console/time)
  * [Console.timeEnd()](https://developer.mozilla.org/ja/docs/Web/API/Console/timeEnd) // 非標準
kubernetes install/configuration (ubuntu18)

- common task for master/worker 

```
sudo apt install docker.io
sudo systemctl enable docker

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"

sudo apt update
sudo apt-get install kubeadm

sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

adding --node-ip=XXXX 
====
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=WWW.XXX.YYY.ZZZ"
====

sudo swapoff -a

```

- only master node

```
IPADDR=$(ip a show eth1 | grep inet | grep -v inet6 | awk '{print $2}' | cut -f1 -d/)
HOSTNAME=$(hostname -s)
sudo kubeadm init --apiserver-advertise-address=$IPADDR --apiserver-cert-extra-sans=$IPADDR --node-name $HOSTNAME --pod-network-cidr=10.244.0.0/16

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

kubectl get nodes
```

- only worker node

```
(on master)
kubeadm token create --print-join-command

(on worker)
sudo kubeadm join 172.16.33.100:6443 --token xq971v.l54h1ha31qii2s7h     --discovery-token-ca-cert-hash sha256:ef3dbf8ff3f0199b22265dca47d381852007b8e53ae4bd79c143628a5541f08e
```

-
https://qiita.com/ysaito8015@github/items/26a208f9c482b2d2d24a

```
ネットワーク設定を行った後にkubeadm resetコマンドを実行してクラスタを作り直す場合、以下のようにして作成された「flannel.1」や「cni0」という仮想ネットワークインターフェイスを先に削除しておく必要がある。

# ip link delete cni0
# ip link delete flannel.1
```

https://knowledge.sakura.ad.jp/20955/

https://qiita.com/sugimount/items/7606bd84426f85adea01

-- kubeadmで Pod-network-cidr を変更する
https://qiita.com/sugimount/items/7606bd84426f85adea01

-- KubernetesでCoreDNS立ち上がらない(flannel, cni)
https://qiita.com/Minatoo/items/c968e42f7c7d579bc473
Windows updateでUserファイルにアカウント名.000が生成された話

（おそらく）WindowsUpdateのせいで、ユーザーファイルに「アカウント名.000」が生成された話。

使えるようにするまでに非常に苦労したのでメモとして書きます。




おそらく9月28日にアップデートしたときに不具合が起きた模様。




状態としてはユーザーファイルに
アカウント名
アカウント名.000
といったファイルが生成されてしまい

様々なソフトで、設定されたpathが元のアカウント名で設定しているので、pathが合わなくなった

![Inkedwindowsupdate事故_LI.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295405/1c6f5096-e2c5-1793-f70c-deee108fee2b.png)



基本的に前のアカウントに入っていたファイルはすべて「アカウント名.000」に入っていて、「アカウント名」のユーザファイルに入っていたのはAppDataファイルのみ。（入っているのは一つのファイルのみ）







今回行った処理としては、
まず元のアカウント名に紐付けされたMicrosoftアカウントをすべてログアウトし,前のアカウントをローカルアカウントにする

↓

次に新しいローカルアカウントを管理者権限を付与して作成

↓

元のアカウントをサインアウトした状態で新しいアカウントにサインイン

↓

Userファイルのデータを新しいアカウントに移行する



といったのが大まかな手順でした。



しかし自分は元のアカウントのファイルが120GBほどあり、エクスプローラーでファイル移動をすると、


ファイルの移動速度が「81 B/s」という待つのが馬鹿らしくなる速度だったので（おそらくものすごく小さいファイルを大量に移動したため）

「fastcopy」というソフトを使用しました。（こちらを使うと「5 MB/s」ぐらいにはなります）
(URL:https://fastcopy.jp/)

またAppDataファイルは管理者の許可が別途必要なため、AppDataファイルのみエクスプローラーで移動しました。
（~~ユーザー環境変数は移行の場所がよくわからなかったので、気合で手打ちしました~~）






蛇足
レジストリをいじることで治る方もいらっしゃるようですが、失敗してしまう方も海外の掲示板では多く見つけた事と、
私の環境だとファイルをバックアップできる環境がたまたま用意できなかったので、こちらのやり方で復旧しました。

ファイルのバックアップが可能なHDDやSSDがあるならそちらをやってみるのも良いかもしれません。（あくまで自己責任で!）

今回はログインする時のアカウント名の表示は変わらなかったので気づくのが遅れてしまい、土壇場でエラーが出て非常に焦りました


今のところは基本的に前の状態に復旧できましたが、後々不具合が出たら追記します。
Google Apps Scriptで共有ファイルのダウンロードを不可にする設定をする

# 概要
Googleドライブの共有の詳細設定で「閲覧者（コメント可）と閲覧者のダウンロード、印刷、コピーを無効にします」という項目がありますが、これをGoogle Apps Scriptで設定するやり方を書きました。


# 手動で設定する場合
1. 対象のファイルを選択して右クリックで共有を選択する
![スクリーンショット 2019-10-03 11.49.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172809/22935ab0-620b-1e8c-673c-f9e6916474c3.png)

2. 共有画面にある詳細設定を選択する
![スクリーンショット 2019-10-03 11.42.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172809/9b619730-a78f-9fd4-b3eb-02879a80de9f.png)

３． 「閲覧者（コメント可）と閲覧者のダウンロード、印刷、コピーを無効にします」のチェックを入れる
![スクリーンショット 2019-10-03 11.35.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172809/42d93456-47f0-e2d2-d67b-7f3c96408168.png)

４． これで閲覧者（閲覧権限とコメント可権限）はダウンロードが不可となる
![スクリーンショット 2019-10-03 11.52.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172809/c5082cca-b957-b6bd-4226-90264f214de7.png)


# Google Apps Scriptで設定する場合

## Drive APIを有効にする

### DriveAppではなくDrive APIを使う

1. メニューの「リソース」から「Googleの拡張サービス」を選択する
![スクリーンショット 2019-10-03 11.28.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172809/7073eaa6-d277-b9a4-7f80-67976ce92df5.png)

2. Drive APIを「ON」にする
![スクリーンショット 2019-10-03 11.27.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172809/6b3474c2-160e-1624-3cf7-d424caf08291.png)

3. `Drive.` と入力すると入力候補が出てくるようになります
![スクリーンショット 2019-10-03 11.28.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172809/bfb5984b-b15b-53cd-4b3f-12b84567df00.png)


## フォルダ内のファイルにダウンロード不可の設定をする

### updateメソッドでファイルのプロパティを変更する
#### 変更するプロパティ
**copyRequiresWriterPermission**
値を`true`にする

```
function dtest() {
  var folder = DriveApp.getFolderById(folderID);
  var files = folder.getFiles();

  while(files.hasNext()) {
    var file = files.next();
    var fileId = file.getId();
    Drive.Files.update({
        copyRequiresWriterPermission: true
      }, fileId)
  }  
}
```


# 参考にしたページ
Google Apps Script Advanced Drive Service リファレンス
https://developers.google.com/apps-script/advanced/drive

Google Drive API v2 リファレンス
https://developers.google.com/drive/api/v2/reference/files
pyTorchでlist(torch.Tensor, torch.Tensor, ...)をtorch.Tensorにまとめる

全ての要素がlistで完結しているなら何も問題はないと思いますが、tensor in list -> tensorsの際にひっかかったため
なお、list内のtensorは全て同じshapeを持つとします。

```python
arrs = [torch.Tensor(), torch.Tensor(), torch.Tensor(), ...]
arrs = torch.cat(arrs).reshape(len(arrs), *arrs[0].shape)
```
Azure Web Appのコンソールでアプリを作成した場合にローカルgitでデプロイする方法

ポータルから作成した場合に概要の箇所にFTPのアドレスしか表示されなかった。
どうやってコードを編集すればいいかわからなかったが以下の方法でgitを有効にできた。

```
$ az webapp deployment source config-local-git --name <app-name> --resource-group <group-name>
```

* \<app-name>がポータルから作成したアプリ名
* \<group-name>がリソースグループ名

画面を更新すると概要の欄に[GitクローンURL]が表示される。

あとはローカルの特定のディレクトリにCloneしてやればソースが編集可能。

Azureにプッシュする場合は

```bash
git remote add azure <GitクローンURL> #リモートの登録
git push azure master #プッシュ
```
PHP5で16進数を符号付10進数に変換する方法(4byte)

## 経緯
仕事でPHPで0xから始まる16進数を符号付きの10進数に変換する必要があったが、ネットで探してもなかなか見つからなかったため備忘録として記載。

## 結論
```php5

    //16進数を符号付き10進数に変換する
    private function hex_to_decimal($val)
    {
        //0x表記の場合
        if (strpos($val,"0x") === 0) {
            //「0x」の箇所を削除する
            $hex = substr($val,2);
        }

        //先頭文字の1ビット目が1→マイナス
        if (hexdec(substr($hex,0,1)) & 8 && strlen($hex) === 8) {
            //2の補数で絶対値を取得
            $hex = (hexdec($hex) ^ (16 ** strlen($hex)-1)) + 1;
            //マイナスに変換
            $dec = 0 - $hex;
        } else {
            //先頭文字の1ビット目が0→プラス
            $dec = hexdec($hex);
        }
        return $dec;
    }
```

## 解説
符号付16進数はビット列の最初の値で正負の判断をしている。
・先頭ビットが1→負
・先頭ビットが0→正
例として負の値-1(16進数:0xFFFFFFFF)で解説。

まずは、下記の箇所

```php5

    if (hexdec(substr($hex,0,1)) & 8) {
```
hexdec(substr($hex,0,1))で16進数の最初の文字「F」の10進数(=15)を取得。
15(2進数で1111)と8(2進数で1000)のビット積を求めることで、最初のビットが1か0かを判定することができる。(&はビット積の意)
最初のビットが1の場合は負の値のため、下記の処理に移る。

```php5

    $hex = (hexdec($hex) ^ (16 ** strlen($hex)-1)) + 1;
```
ここでは元の16進数(0xFFFFFFFF)と３２ビット分全て"1"の数値を排他的論理和でビット演算を行い、その数値にプラス１をすることで2の補数で負の値の絶対値を取得している。

その後に、下記の計算で負の値に変換して終了。

```php5

    $dec = 0 - $hex;
```

## 最後に
もっといい方法あったら教えてください！
ExpressでさらっとAPI

まずは読み込み

```js
const app = new (require('express'))()
const port = 3000
const bodyParser = require('body-parser')
const mysql = require('mysql')
```

dbの設定(localhost)

```js
const connection = mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: 'ぱすわーど',
    database: 'でーたべーすめい'
});
```
dockerを使う場合は
> host: 'localhost'

をDockerのコンテナに合わせて変える。

bodyPaserの設定

```js
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());
```

hogeテーブルの一覧を表示

```js
app.get('/hoge',(req,res) => {
    connection.query('select * from hoge_table', function (error, results, fields) {
        if (error) throw error;
        res.send(results);
    });
})
```

hogeテーブルにデータを追加

```js
app.post('/hoge',(req,res) => {
    const fuga = req.body.fuga;
    connection.query('INSERT INTO hoge_table SET ?', { fuga: fuga }, (err, result) => {
        if (err) throw err;
        res.send(result);
    })
})
```

hogeのidで返す

```js
app.get('/hoge/:id',(req,res) => {
    const id = req.params.id
    res.send({'id': id})
})
```

サーバーを呼ぶ

```js
app.listen(port, error => {
    if (error) {
        console.error(error);
    } else {
        console.info('listen: ', port);
    }
});
```

オワオワリ
シンプル設定でREST API（Lambda と API Gateway）を作成してみた

#目的
とりあえず、付加的な設定は除いて超シンプルにREST API(Lambda+API Gateway)を作成する。
それによって、API作成の全体の流れをつかむこと

#作業の流れ
①Lambdaで、”関数：getTextData”の作成
　→リターンは、"{"statusCode": 200, "body": "\"Hello from LambdaMethod:getTextData\""}"

②API Gatewayで、Lambdaを関連づけ、APIを作成

#①Lambdaで、”関数：getTextData”の作成
###1.Lambda関数の設定
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350277/1f44ffb9-6ee2-fca1-e146-ec59b450f190.jpeg)
※ランタイムは、pythonやnode.jsなどから選択します。
###2.関数getTextDataにpythonコードを記述
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350277/a90b96c9-a010-b40e-7847-399d4903d7bc.jpeg)
※ハンドラからプログラムが実行される（lambda_function.pyのlambda_hundler関数）

#②API Gatewayで、Lambdaを関連づけ、APIを作成
###1.APIの設定
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350277/c199c124-8272-6cb3-179a-b34c7c042a2d.jpeg)
▼メモ
・Swagger
　REST Full APIのインターフェースのフォーマット。海外ではデファクトスタンダード
　（Open API Initiative　という団体が推進）
・エンドポイントタイプ
　リージョン（クライアントがリージョンに集中している場合）
　or　エッジ（クライアントが分散している場合）
###2.REST APIのリソース（URL）とhttpメソッド（GET）の設定
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350277/2ec84910-4e5e-c279-23bb-54f61177da8e.jpeg)
例）
－－－－－－－－－－－－－－－
　GET http://XXX.com/test
－－－－－－－－－－－－－－－
リソース→test
メソッド→GET　※POST/GET/DELETEなどのhttpメソッド
###3.APIからLambda関数を実行するための、紐づけ設定
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350277/8f907002-dd38-62c4-00e1-1d797aee1421.jpeg)
###4.API動作確認（テスト実行）
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350277/a90d31a3-acf5-f644-b850-a299b5fc3590.jpeg)
###5.httpアクセスできるように、デプロイする
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350277/7808ea74-a6bd-df54-f55c-b2156938733a.jpeg)

###6.API実行確認（ブラウザからURLをたたき出力を確認！）
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350277/4510b12b-2928-93b7-fa49-4f228c07966f.jpeg)

これにて、シンプル設定でREST API作ってみた、は完了です！簡単 (*´ω｀)
App StoreのPVを作るスクリプト

## こんな人向け
iPhoneX Max持ってない、iPhone8持ってない、iPad Pro持ってない…けど、
iPhoneX(R)、iPhone(6sとかなんでも)、普通のiPadなら持っている人が、AppStoreで必要なPVの動画を作る方法。
※もちろん引き伸ばすので解像度の最適化はされけど、とりあえず用意したい

## 準備
各iPhoneX系、iPad、iPhone6系でそれぞれ、QuickTime Playerで動画を取る。
※INPUTファイル名とOUTPUTファイル名は適宜変更してください。

```shell:iPhoneX向け
ffmpeg -i ./iPhoneX.mov -r 30 -vf scale=886:1920 886x1920.mov
```

```shell:iPhone向け
ffmpeg -i ./iPhone.mov -r 30 -vf scale=1080:1920 1080x1920.mov
```

```shell:iPad向け
ffmpeg -i ./iPad.mov -r 30 -vf scale=1200:1600 1200x1600.mov
```

## 注意事項
アップロードはSafariで
ムービーの長さは15秒〜30秒で
iPad Pro(第２世代・第３世代)

詳しくは
https://help.apple.com/app-store-connect/?lang=ja-jp#/dev4e413fcb8

## 番外編
### iPhoneX用に作ったサイズの動画の上下を切って、16:9にして、iPhoneのサイズにする
```shell:iPhoneX->16-9
ffmpeg -i ./iPhoneX.mov -vf crop=w=886:h=1575:x=0:y=172 tmp16x9.mp4
```

### iPhoneX用に作ったサイズの動画の上下を切って、4:3にして、iPadのサイズにする
```shell:iPhoneX->4-3
ffmpeg -i ./iPhoneX.mov -vf crop=w=886:h=1181:x=0:y=370 tmp4x3.mp4
```
[初学者]findメソッドについて（ruby）

#目的
学習の備忘録と初学者の参考資料として投稿

#findメソッド
該当するモデルのテーブルからデータを検索する際に使われるメソッド。

例えば・・・

userテーブル

| id | name | age | gender |
|:-:|:-:|:-:|:-:|
|1   |taro   | 12  | male  |
| 2  |hanako   | 11  |   female|
|  3 |jiro   | 10  | male  |
|   4|keiko   |  9 | female  |

検索して表示させたい→

| id | name | age | gender |
|:-:|:-:|:-:|:-:|
| ○○○| ○○○| ○○○|○○○|

```ruby:users_controller.rb

 def show
  @user = User.find(user:id)　idを引数として検索する
 end

　＊viewは省略
```

findは検索条件として指定できるものは「idのみ」です。データを複数取得できます。

#findとfind_byの違い
find_byは、複数の条件を指定したりid以外のカラムでも検索できます。データは条件があった中で最初の一つのみ取得できる。

```


find_by(gender:"male")

上の例から、こんな感じで検索する。
```

#まとめ
テーブルからデータを表示や更新や削除する場合によく使うメソッドです。他にもwhereというメソッドもあります。

今後も学習で気づきや参考になるものがあれば、アップしていきます。
もし参考になったらいいね！！よろしくお願いします:bow_tone1:
AppleWatchをブルブルさせようとしたら少しハマった

https://qiita.com/koogawa/items/3dcc72e77ce9e5b106b1
この記事を参考に，ブルブルさせようとしたが少しハマった話

以下をとりあえずコピペするが、もちろんバージョンアップされまくってるのでエラーが出る

```
WKInterfaceDevice.currentDevice().playHaptic(type: WKHapticType)
```
`currentDevice`は`currunt`に
`playHaptic`は`play`にrenameされているらしい

とりあえず，これで実行してみる

```
WKInterfaceDevice.current().play(WKHapticType.notification)
```

が，実行されないしなぜかエラーも出ない

```
WKInterfaceDevice.current().play(.notification)
```
これで動きました
Blackできれいに自動整形！flake8とBlack導入と実行

こんにちは！
とあるITベンチャーで長期インターンをしている京都の学生です。
今回はBlackを導入しろ！というカリキュラムがあったので、実際にやって、ちょこっとBlackのアウトプットをしようかなと思っています。
基本的に参考文献に書いてあること書いているだけなので、詳細を見たい方は参考文献を見てください。

##Blackについて
僕のインターン先では**flake8**と**Black**を組み合わせて使用しています。
[flake8についてのアウトプット](https://qiita.com/tsuyoshi0514/items/949827f6a1cfca32dc65)に書いたとおり、**flake8**はコーディングチェックツールのラッパーです。
**flake8**はコードのチェックにはとても便利で優秀です。
しかし、`エラーの修正まではできません。`
そこで、このエラーを自動で修正してくれるのが**Black**というわけですね。

##Blackの導入
**Black**を導入するには下記のコマンドを打ちます。

```
$ pip install black
```
しかし、僕だけかもしれませんが次にようなエラーが出ました。
`Cannot pip install black: No matching distribution found for black`
ただ、一瞬で解決する方法があったのでそちらも一緒に紹介します。
[こちら](https://github.com/psf/black/issues/478)を参考にして下記のコマンドを打つだけでいけました。笑

```
python3.6 -m pip install black 
```

**Black**は`Python3.6より新しいもの`でないと機能しないみたいなので、これでも駄目だったら、一度Python3のバージョンを確認してみてください。

##VSCodeの設定
**Black**のインストールが完了したら、次にVSCodeの設定をいじっていきます。
僕は[こちら](https://qiita.com/psychoroid/items/2c2acc06c900d2c0c8cb)を参考にしたので、詳しく知りたい方は一度目を通してください。
VSCodeのsettingsの設定を以下のようにしていきます。

| 設定名 | 機能 | 設定値 |
|:--|:--|:--|
| python.linting.enabled | Lint機能を有効にするかどうか | true |
| python.linting.pylintEnabled | Linterにpylintを使用するかどうか | false |
| python.linting.flake8Enabled | Linterにflake8を使用するかどうか | true |
| python.linting.lintOnSave | ファイル保存時にLintを実行するか | true |
| python.formatting.provider | Pythonコードの整形に何を使用するか | black |
| editor.formatOnSave | ファイル保存時に自動整形するかどうか | true |
→[引用元](https://qiita.com/psychoroid/items/2c2acc06c900d2c0c8cb)（丸パクリ）
上記の引用元から引っ張ってきた表です。
変えたところとしては`python.formatting.provider`の設定値を僕のインターン先では**Black**を使用しているので**Black**に変えたくらいです。
この設定を行うことで[flake8についてのアウトプット](https://qiita.com/tsuyoshi0514/items/949827f6a1cfca32dc65)でインストールした**flake8**と**Black**を使用できます。
引用元には上記の設定の一つ一つの解説をしてくれているので一度見ることをおすすめします。

##実際に使ってみる
では、実際に使ってみましょう。

```python

 def foo():
    print(
                "Hello"
        "World"
        )
```
上記のコードを保存したときに、下記のコードのようにきれいな状態になっていれば導入成功です。

```python

def foo():
    print("Hello" "World")
```

##まとめ
今回は**Black**について書きました。
flake8に関しては[flake8についてのアウトプット](https://qiita.com/tsuyoshi0514/items/949827f6a1cfca32dc65)に書いてあるので今回ははしょりました。
僕が書いたことはほとんどコピペなのでもっと詳しく知りたいという方は参考文献を見てください！！
最後まで読んでいただきありがとうございます。

##参考文献
[【VS Code】BlackとFlake8を使ってきれいなPythonコードを書く！！](https://www.macky-studio.com/entry/2019/07/04/152323)

[VSCodeのPython開発環境でpylintの代わりにflake8を導入し自動整形を設定する](https://qiita.com/psychoroid/items/2c2acc06c900d2c0c8cb)

[もうPythonの細かい書き方で議論しない。blackで自動フォーマットしよう](https://blog.hirokiky.org/entry/2019/06/03/202745)

[pip install blackできない人用](https://github.com/psf/black/issues/478)

[Vimメモ : flake8でPythonのコードをチェックする](https://wonderwall.hatenablog.com/entry/2017/02/05/214004#flake8%E3%81%A8%E3%81%AF)

[flake8についてのアウトプット](https://qiita.com/tsuyoshi0514/items/949827f6a1cfca32dc65)
【AWS：節約】使ってないElasticIPは月額400円掛かるので解放しましょう

# AWSのElasticIPはインスタンスに紐づけてないとお金がかかる

1ヶ月3.6$なので400円ほどですね、積極的に消していきましょう。

公式ドキュメントに記載があります。

https://aws.amazon.com/jp/ec2/pricing/on-demand/

```
0.005USD: 実行中のインスタンスと関連付けられている追加の IP アドレス/時間あたり（比例計算）
0.005USD: 実行中のインスタンスと関連付けられていない Elastic IP アドレス/時間あたり（比例計算）
0USD: Elastic IP アドレスのリマップ 1 回あたり – 1 か月間で 100 リマップまで
0.1USD: Elastic IP アドレスのリマップ 1 回あたり – 1 か月間で 100 リマップを超える追加分
```
なぜVimを学ぶべきか？Vimを学ぶメリット【簡潔に箇条書き】

プログラミングを勉強している人であれば目や耳にしたことはあるであろうエディタ論争。
必ずと言っていいほど名前が挙がる「**Vim**」についてメリットと学ぶ理由を簡単にまとめておきました。

Vimがそもそも何者かという解説は、この記事にたどり着く前に通っていると思います。

Vimは初めのうちはCUI特有の操作方法に手間取って非効率に感じることもあります。
ただプログラミングに慣れてくると触れてみて損のない技術になってくるので、常用とまではいかなくてもぜひ扱えるようになっていただくことをオススメします。

## Vimのメリット

- **軽量で環境を選ばない**エディタ(LinuxでもwindowsでもMacOSでも)
- 操作が初めはとっつきづらいが、覚えてしまえば**高速で編集**することができる
- プラグインの導入で、IDEやVSCodeなどの**エディタアプリと同じくらい便利に**プログラミングできる

## なぜVimを学ぶべきか

- **様々なweb解説記事がvimコマンドを叩くよう誘導**してくるため、仕組みは知っておいて損はない(常用はしないにしても)
- **Git**など**Web開発で必要**な技術で用いるため

## Vimを学ぶ方法

- **vimtutor :** vimの公式チュートリアル(Vimをインストールして、任意の場所で`vimtutor`とタイプするだけ)
- **vimadventure :** vimのキーバインドをゲームで体に覚えさせることができる https://vim-adventures.com/
- **ドットインストール vim入門(無料) :** https://dotinstall.com/lessons/basic_vim
- **VSCodeの拡張 vscodevim :** https://github.com/VSCodeVim/Vim

普段使いのエディタをvim縛りにすることで使う機会が増える。

## 参考
この記事は「CodeShip」内での実際の質疑応答や指導・アドバイスの一部を基に作成しています。
@nuxtjs/sentry で全てのエラー送信にタグを追加する

# @nuxtjs/sentry のインストール
https://github.com/nuxt-community/sentry-module#readme

```
$ yarn add --dev @nuxtjs/sentry
```

# 初期設定
```nuxt.config.js
modules: [
  '@nuxtjs/sentry'
],
sentry: {
  dsn: 'https://xxxxxx', // SentryのDSNを記述
  config: {
    // configを追加したい場合は記述
  }
}
```

# Nuxtプラグインを作成
```plugins/my-sentry.js
export default ({ app }) => {
  app.$sentry.configureScope(scope => {
    scope.setTag('tagName', 'foo')
  })
}
```

```nuxt.config.js
plugins: [
  '~/plugins/my-sentry'
]
```

タグに限らず一括でcontextを操作したいときには使えるテクニックかと思います。
https://docs.sentry.io/enriching-error-data/context/?platform=javascript
Windows Subsystem for Linux上でDockerを動かす


# Windows Subsystem for Linux上でdockerを動かす

# 前提条件
- Windows Subsystem for Linux上で既にUbuntuが動作中。
- Docker for Windowsをインストール済み。

# 必要パッケージ等準備
```
apt-get install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
```
## プロキシ設定
プロキシの設定が必要であれば設定する。
### apt-get設定
```
vi /etc/apt/apt.conf （なければ作成）
Acquire::ftp::proxy "ftp://username:password@your.proxy.address:proxy.port/";
Acquire::http::proxy "http://username:password@your.proxy.address:proxy.port/";
Acquire::https::proxy "https://username:password@your.proxy.address:proxy.port/";
```
### curl設定
```
vi ~/.curlrc
proxy-user = "(ユーザ名):(パスワード)"
proxy = "http://proxy.xxx.co.jp:(ポート)"
```

## Docker公式のGPG鍵を追加、確認
```
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
apt-key fingerprint 0EBFCD88
```

## Docker リポジトリを追加
```
add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
```

# Dockerインストール
```
apt-get update
apt-get install docker-ce
```

# Docker for Windowsと連携する
```
echo "export DOCKER_HOST='tcp://0.0.0.0:2375'" >> ~/.bashrc
source ~/.bashrc
docker version
```

## 備考
- systemd使う場合

```
apt-get install systemd
```

# Docker for Windows プロキシ設定
プロキシの設定が必要であれば設定する。
・Setting > Proxices
```USER:PASSWORD@XXXXX.com:8080
```

## 参考URL(公式サイト)
https://docs.docker.com/install/linux/docker-ce/ubuntu/
RCTAppStateのエラー解決

# はじめに
- 自分用備忘録として記載してます。
- 前案件で開発したReactNativeアプリを久々に起動しようとしたらエラーが起きて困ったので試したことを羅列してます。

出てきた画面はこちら。
<img width="535" alt="スクリーンショット 2019-10-04 14.03.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275513/f500ede6-21c8-d0e7-f81c-2a38c9d3f2f3.png">
※ iPhone11 Pro Maxを利用していますが、他のバージョンでも同様のエラーが発生。

その以前に、以下の部分は正常に通っているのを確認しています。
- yarn tsc ->正常終了
- yarn build ->正常終了
- XCodeビルド ->正常終了
- アプリ起動(スプラッシュ表示) ->正常終了
- node_module読み込み ->正常終了

## 原因：XCode11へのバージョンアップによって旧react-nativeが動かなくなった
→ なので、対応方法としては以下の２パターン。
①react-nativeのバージョンを上げる
②XCode10に戻す

# ①react-nativeのバージョンを上げる
元のバージョンは `0.57.1` でした。ということで。

### 1-1.react-nativeのバージョンを `0.59.9` に変更してみる。
参照：https://github.com/facebook/react-native/issues/25154
→ 別のエラーが山のように出てきてXCodeビルドが出来なくなったのでそっ閉じ

### 1-2.react-nativeのバージョンを最新 `0.61` に変更してみる。
→ `react-native-sound` や `amazon-cognito-identity-js` などの他モジュールで `'React/RCTBridgeModule.h' file not found` エラーが出てXCodeビルドが出来ないため戻す。

### 1-3.障害箇所だけ直してみる。
参照：https://github.com/facebook/react-native/pull/25146/files#diff-263fc157dfce55895cdc16495b55d190
XCode11対応として、 `node_modules/react-native/React/Base/RCTModuleMethod.mm` の `l.94` に1行改修が入っています。
react-native自体をバージョンアップしたくない場合はこの1行を手動追加する。
→ 無事立ち上がった！！！！

```tsx:RCTModuleMethod.mm
static BOOL RCTParseUnused(const char **input)
{
  return RCTReadString(input, "__attribute__((unused))") ||
         // ↓の1行を追加
         RCTReadString(input, "__attribute__((__unused__))") ||
         RCTReadString(input, "__unused");
}
```

# ②XCode10に戻す
参照：https://qiita.com/leo1109/items/0f4c0b343b1515bbc90d
→ 私の場合、元々使っていたバージョンは`XCode10.2.1`だったのでこれに戻せばOKの筈。
（ただ、要件としてXCode11が良かったので`1-3.障害部分だけ直してみる`で対応しました）
<img width="1011" alt="スクリーンショット 2019-10-04 14.51.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275513/8877ba8d-cdb4-8fcf-ee9a-82b3ec552a66.png">

# 終わりに
今回も先輩や各所参考にさせて頂きました...多謝！
メモ書きですが誰かの助けになれば幸いです。
[ Android Studio ] ボタンによる表示切替

Android StudioのButtonによる「表示↔非表示」切り替えについて学習していく。

##ボタンの実装

###ボタン配置
　以前書いたHello World表示サンプルをもとに進めていく。

　まずはボタンを配置する。
　プロジェクトの「app」→「res」→「layout」→「activity_main.xml」でxmlファイルを開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506451/32c12016-deb4-afc4-f25e-0e319dd31319.png)

　左下の「デザイン」or「テキスト」で「デザイン」を選択したまま、全画面表示で左真ん中あたりにある
「Common」→「Button」の「Button」を画面上でドラッグ。
　今回は表示用、非表示用の二種類作るので、２回ドラッグ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506451/fb9412c1-4618-400c-332e-afadf7ebdd66.png)


　上記の画面で、それぞれButtonを左クリックで選択し、右画面の一番上idでプログラムで使うidを決めておく。
（左下の「デザイン」を「テキスト」にしてソースコードいじって変更も可能）
 とりあえず

- Button1はbutton1（表示用）
- Button2はbutton2（非表示用）

にする。

　Buttonを右クリックして「Constrain」→「parent top（なんでもよい）」を選択。
（これしないとエラー出ます。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506451/22ec5b19-5584-74b1-660e-8c0ec8bf1dfd.png)


　これでボタン設置完了。


###プログラム
　まずクリックイベントを取得するボタンを決める。
　先ほどのidをここで使う。
　またテキストについても表示変更のため加えておく。

~~~java
        //クリックイベントを取得するボタン
        Button button1 = (Button) findViewById(R.id.button1);
        Button button2 = (Button) findViewById(R.id.button2);
        TextView text = (TextView) findViewById(R.id.text);

~~~

　後は、buttonごとにクリックイベントを取得するためのプログラムを書いて終了。
　ネットでよく出るテンプレートは古く、ラムダ式で書くのが現代のやり方、らしい…

~~~java
        //ボタンにOnClickListenerインターフェースを実装
        button1.setOnClickListener((View v)-> {
            text.setVisibility(View.VISIBLE);
        });

        button2.setOnClickListener((View v2)-> {
            text.setVisibility(View.INVISIBLE);
        });
~~~



　試してみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506451/55d14916-0a42-27e4-7312-b62f645b3d4a.png)

　成功。

##まとめ
　以下がサンプルプログラム。

~~~MainActivity.java
package com.example.applicationtest;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;


public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //クリックイベントを取得するボタン
        Button button1 = (Button) findViewById(R.id.button1);
        Button button2 = (Button) findViewById(R.id.button2);
        TextView text = (TextView) findViewById(R.id.text);

        //ボタンにOnClickListenerインターフェースを実装
        button1.setOnClickListener((View v)-> {
            text.setVisibility(View.VISIBLE);
        });

        button2.setOnClickListener((View v2)-> {
            text.setVisibility(View.INVISIBLE);
        });
    }
}

~~~

　途中エラー出まくりだったが何とか解決。
　次は画像表示切替に挑戦しようと思う。
　以上。
Docker Composeでサービス名を抽出して実行する

# 前提

```docker-compose.yaml
version: "3.3"
services:
  serviceA:
  
  taskA:

  taskB:
```

# 本題

`docker-compose ps`を使えばserviceの名称を取得できます。

```bash
$ docker-compose ps --service
serviceA
taskA
taskB
```

taskだけ実行する

```shell
$ docker-compose ps --service | grep task | xargs -I % docker-compose run %
```
mac で Android エミュレーター の hosts を変更する方法

# エミュレーターのリストを表示

<font color="red">※ Android 11 だと hosts ファイルの転送ができませんでした。</font>

```
$ ~/Library/Android/sdk/emulator/emulator -list-avds
Pixel_3a_XL_API_28_9.0_
```

# エミュレーターを書き込みモードで起動

```
$ ~/Library/Android/sdk/emulator/emulator -avd Pixel_3a_XL_API_28_9.0_ -writable-system
```

上記コマンドを実行するとエミュレーターが起動する。

既にエミュレーターが起動している場合は

```
emulator: WARNING: System image is writable
emulator: ERROR: Running multiple emulators with the same AVD is an experimental feature.
Please use -read-only flag to enable this feature.
```

こんなエラーが表示されるので終了してからコマンドを実行する。

### 注意

ここで起動するエミュレーターは **「Play Store」ではない** ものでないとダメらしい。

# root を取得

もうひとつターミナルを起動して以下実行する。

```
$ ~/Library/Android/sdk/platform-tools/adb root
restarting adbd as root
```

もし「Play Store」のエミュレーターを起動していた場合は

```
adbd cannot run as root in production builds
```

こんなエラーが出る。

# 再マウント

```
$ ~/Library/Android/sdk/platform-tools/adb remount
remount succeeded
```

# エミュレーターの hosts ファイルを取得

```
$ ~/Library/Android/sdk/platform-tools/adb pull /system/etc/hosts ~/Desktop/
/system/etc/hosts: 1 file pulled. 0.0 MB/s (79 bytes in 0.002s)
```

Android Studio の [Device File Explorer](https://developer.android.com/studio/debug/device-file-explorer?hl=ja) でエミュレーター内のファイルを確認すると
`/etc/hosts` も存在するが `/system/etc/hosts` へのリンクが貼ってあるだけ。

# hosts ファイルを編集

```
127.0.0.1       localhost
::1             ip6-localhost

10.0.2.2 変更するドメイン ← 追記
```

ローカルへ接続する場合、 `10.0.2.2` でないとダメらしい。

# hosts ファイルを転送

```
$ ~/Library/Android/sdk/platform-tools/adb push ~/Desktop/hosts /system/etc/hosts
/Users/*****/Desktop/hosts: 1 file pushed. 0.0 MB/s (79 bytes in 0.011s)
```

もし書き込みモードでエミュレーターを起動していない場合は

```
adb: error: failed to copy '/Users/*****/Desktop/hosts' to '/system/etc/hosts': remote couldn't create file: Read-only file system
```

こんなエラーが出る。

# root を解除する

```
$ ~/Library/Android/sdk/platform-tools/adb unroot
restarting adbd as non root
```

# 再起動する

```
$ ~/Library/Android/sdk/platform-tools/adb reboot
```

# 表示されるか確認する

以上で hosts が変更されたハズ。

Chrome などでちゃんと表示されるか確認する。

# 参考
* [Androidエミュレーターのhostsを書換えてローカルサーバーへ接続する](https://qiita.com/devnokiyo/items/5388169f798bd2678d64)
* [Androidのエミュレータでhostsを書き換える](https://qiita.com/musclemikiya/items/5e7832317d442f35a853)
Railsエラーメッセージのフォーマットを変更したい(先頭にモデルの属性名をつけたくない場合など)

## 発端

- Nameを入力してください。
- Emailを入力しください。
- Passwordを入力してください。

Railsでは上記のように、エラー文の先頭に必ずモデルの属性名が表示されてしまいます。
(今回は、属性名の日本語化が本題ではありません。)
しかし、**先頭にモデルの属性名をつけたくない場合**や**エラーメッセージをカスタマイズしたい場合**、このままでは不都合です。

## 解決策

```yml:config/locales/ja.yml
ja:
  errors:
    format:
      "%{message}"
```

`config/locales/ja.yml`に上記を追記してください。
デフォルトの属性名が、`"'%{attribute}' %{message}"`になっているため、
フォーマットをオーバーライドすれば良いようです。
様々、カスタマイズすることも可能ですね！

## 参考
[Rails 6 allows to override the ActiveModel::Errors#full_message format at the model level and at the attribute level]
(https://blog.bigbinary.com/2019/04/22/rails-6-allows-to-override-the-activemodel-errors-full_message-format-at-the-model-level-and-at-the-attribute-level.html)
Chart.js のスケールタイトルを回転させる方法

追記
xのpositionにright指定してたら狂いますね、そのうち直します

## きっかけ

？？？「y軸が2つあるグラフのスケールタイトルは両方とも同じ向きなんですよね」


## コード

Chart.js 自体のコードを改変します。
まず下記の部分を探します。

```js
if (scaleLabel.display) {
    // Draw the scale label
    var scaleLabelX;
    var scaleLabelY;
    var rotation = 0;
    var halfLineHeight = scaleLabelFont.lineHeight / 2;

    if (isHorizontal) {
        scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width
	scaleLabelY = position === 'bottom'
	? me.bottom - halfLineHeight - scaleLabelPadding.bottom
	: me.top + halfLineHeight + scaleLabelPadding.top;
    } else {
        var isLeft = position === 'left';
	scaleLabelX = isLeft
	? me.left + halfLineHeight + scaleLabelPadding.top
        : me.right - halfLineHeight - scaleLabelPadding.top;
	scaleLabelY = me.top + ((me.bottom - me.top) / 2);
	rotation = isLeft ? -0.5 * Math.PI : 0.5 * Math.PI;
    }


    context.save();
    context.translate(scaleLabelX, scaleLabelY);
    context.rotate(rotation);
    context.textAlign = 'center';
    context.textBaseline = 'middle';
    context.fillStyle = scaleLabelFontColor; // render in correct colour
    context.font = scaleLabelFont.string;
    context.fillText(scaleLabel.labelString, 0, 0);
    context.restore();
}
```

position = left の処理しか書いてないので，right を追加します。


```js
if (scaleLabel.display) {
    // Draw the scale label
    var scaleLabelX;
    var scaleLabelY;
    var rotation = 0;
    var halfLineHeight = scaleLabelFont.lineHeight / 2;

    if (isHorizontal) {
        scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width
	scaleLabelY = position === 'bottom'
	? me.bottom - halfLineHeight - scaleLabelPadding.bottom
	: me.top + halfLineHeight + scaleLabelPadding.top;
    } else {
        var isLeft = position === 'left';
	scaleLabelX = isLeft
	? me.left + halfLineHeight + scaleLabelPadding.top
        : me.right - halfLineHeight - scaleLabelPadding.top;
	scaleLabelY = me.top + ((me.bottom - me.top) / 2);
	rotation = isLeft ? -0.5 * Math.PI : 0.5 * Math.PI;
    }

    /*------------ ここを追加 ------------*/
    if (position === "right") {
        rotation += Math.PI;
    }
    /*----------------------------------*/

    context.save();
    context.translate(scaleLabelX, scaleLabelY);
    context.rotate(rotation);
    context.textAlign = 'center';
    context.textBaseline = 'middle';
    context.fillStyle = scaleLabelFontColor; // render in correct colour
    context.font = scaleLabelFont.string;
    context.fillText(scaleLabel.labelString, 0, 0);
    context.restore();
}
```


## 結果

![スクリーンショット 2019-10-04 15.14.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286025/3cc8a72b-97d3-5006-153f-7832c791ea5a.png)
tf-pose-estimationを使って動画の姿勢推定と軌道描画

<img width="300" alt="cmu_dance_curve5_2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480516/006a3e83-f7f1-8053-8005-b487c7775b87.gif">

#はじめに
前回の記事「https://qiita.com/fugunoko/items/299cfde96126007c6274」
では、tf-pose-estimation(https://github.com/ildoonet/tf-pose-estimation)
を使って、動画から姿勢推定と2D座標の出力を行いました。

今回は、出力した2D座標を用いて、動画(gif)上に節毎の軌道を描くようにします（結果は冒頭のgifのようになります。）

#目次
- データ準備
- 軌道gif作成
- ご参考サイト

#データ準備
前回の記事「https://qiita.com/fugunoko/items/299cfde96126007c6274」
を参考に、2D座標データリスト、frame毎の画像を出力しておきます。

#軌道gif作成
これらのデータを用いて、frame毎の画像に2D座標データリストから各節の点を上書きプロットします。nframe目には、nframe,(n-1)frame...の節をプロットしています。これらの画像を集めてgifとすることで、軌道が分かるようなgifが作成されるようにしています。

jupyter notebook環境で実行しました。

```python:graph.py
import pandas as pd
import numpy as np
import os
import codecs
import cv2
import glob
from PIL import Image

#2D座標リスト
df= pd.read_csv('cmu_dance_2ddata.csv')
#各節の軌道の色設定(0～18節)
colors = [[255,0,0],[0,255,0],[0,0,255],[255,255,0],[255,0,255]
          ,[0,255,255],[0,255,0],[0,0,255],[255,255,0],[255,0,255]
          ,[0,255,255],[0,255,0],[0,0,255],[255,255,0],[255,0,255]
          ,[0,255,255],[0,255,0],[0,0,255]]

#合計frameとframe間隔設定
frame = 135
term = 5
sizex = 1280
sizey = 720

for m in range(0,frame+term,term):
    #各frameの画像読み込み
    img = cv2.imread('brabra/cmu_dance_' + str(m) + '_data.jpg')
    #サイズ変換
    img = cv2.resize(img,(sizex,sizey))
    #そのframeまでの節を画像に上書き描画
    for i in range(0,m+5,5):
        dfa = df[(df['flame']==i)]
        try:
            max(dfa['human'])
        except:
            continue
        for j in range(1,max(dfa['human'])+1):
            dfb = dfa[(dfa['human']==j)]
            for k in range(0,19):
                dfc = dfb[(dfb['point'] == k)]
                try:
                    cv2.circle(img, (int(dfc['x']), int(dfc['y'])), 3, colors[k], -1)
                except:
                    continue
    #各frameで画像保存
    cv2.imwrite('brabra/cmu_dance_' + str(m) + '_data_curve.jpg', img)

#gif化
files = []
for i in range(0,frame+term,term):
    filepath = 'brabra/cmu_dance_' + str(i) + '_data_curve.jpg'
    files.append(filepath)

images = list(map(lambda file: Image.open(file), files))
images[0].save('C:brabra/cmu_dance_curve' + str(term) + '.gif',
               save_all=True, append_images=images[1:], interval=330, loop=0)

```

実行すれば冒頭のgifのような軌道が描画されたものが作成されます。
動作の軌道から得られるものは多いと思うのでどんどん使っていきたいです。


#ご参考サイト
- からあげさんのヒューマンシーケンサー(https://note.mu/karaage0703/n/n78ae26dca4b5)
- https://qiita.com/sugup/items/ebe1c0783f5c4db330d0
- https://qiita.com/shiooon/items/535f588bea7748e156f2
- https://qiita.com/keel/items/0d64167850566586d22a
ブログ投稿サイトを作ってみました

こんにちは。
本日は初投稿ということで、プログラミングを始めて２週間少しの初心者が０から作った作品を紹介します。
ーーーーーーーー
#ブログ投稿サイト :airplane:
###トップ画面
<img width="1440" alt="スクリーンショット 2019-10-04 14.46.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508299/9b426b4e-5562-c246-8566-480bd685f5f0.png">
<img width="1440" alt="スクリーンショット 2019-10-04 14.45.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508299/ee429b7f-6159-59b8-6efd-a147090935e3.png">

###ユーザー新規登録、ログイン画面
<img width="50%" alt="スクリーンショット 2019-10-04 19.58.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508299/2e203040-f487-ca2f-9b50-3c9e83a128fd.png"><img width="50%" alt="スクリーンショット 2019-10-04 19.59.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508299/50249432-e18d-9b31-8d2c-e311733369a1.png">

###投稿画面
<img width="1439" alt="スクリーンショット 2019-10-04 19.59.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508299/3d41dda0-9d5c-d485-b749-62cdd5bc9cec.png">

###詳細確認画面
<img width="1440" alt="スクリーンショット 2019-10-04 19.57.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508299/e93b94d5-3335-fab4-6e1e-2ee2d9cd6308.png">
（写真引用元：https://www.travel.co.jp/guide/article/24996/）



##1. 実装機能
・ユーザ登録、ログイン、ログアウト可能
・投稿はタイトル、本文、画像のみ（非ログイン時は投稿不可）
・投稿したユーザ本人による投稿の編集、削除が可能
・ログインしていなくても投稿一覧、詳細が閲覧可能
・ページネーション機能（投稿は新着順）

##2. 使用言語・ツール
・Ruby
・Haml/Sass
・JQuery
・Ruby on Rails
・Bootstrap

##3. 工夫した点
bootstrapというwebアプリケーションフレームワークを使用し、
ボタンやページネーション等を簡単に作成、装飾してみました。
フォームなどにも適用させて、もっと簡単に作成するのが理想でしたが、
公式サイトはもちろん英語だったのでなかなか上手く使えなかったのが少し残念なところです。。。
あとは**綺麗な画像を貼ることで見栄えを良くしました！笑**

##4. 苦労した点
devise gem をインストール後、userテーブルをmigrateする際にエラーが発生し、
解決に時間が掛かりました。
エラー内容は「**max key length is 767 bytes**（768バイト以上のカラムに対するインデックスキーは設定できないよ）」と言った内容。
調べてみると、MySQLの単一カラムインデックスのインデックスキーは、デフォルトで
最大 767 バイトまでとのことでした...。
マイグレーションファイルに於いて、string 型の容量にリミットをつけてあげることで解決出来ました。
ex) t.string   :reset_password_token, limit: 191

>参考文献
https://blog.e2info.co.jp/2017/04/17/mysql%E3%81%AE%E3%82%A4%E3%83%B3%E3%83%87%E3%83%83%E3%82%AF%E3%82%B9%E3%82%B5%E3%82%A4%E3%82%BA%E3%81%AB767byte%E3%81%BE%E3%81%A7%E3%81%97%E3%81%8B%E3%81%A4%E3%81%8B%E3%81%88%E3%81%AA%E3%81%84/

##5. 感想
制作時間の半分以上がエラーとの奮闘でしたが、解決した時にはこの上ない感動でした。
普段使っているウェブサイト、アプリ、何から何までこんなに苦労しているんだなと感じることができました。
「こんな機能があるといいな」「こんな風に配置したいな」と、色々とこだわりを入れたかったのですが、そこは自分の今の技術的に厳しめだったので断念。
これからも毎日勉強して、良いものを作ろうと思いました！
AWSで構築したWebサイトがiPhoneで開けないときに試すこと

AWS で EC2 + RDS + ELB などで構成したWebサイトをiPhoneで開こうとすると
なぜか「ページを開けません。サーバーが見つかりません。」と表示されて開けない問題に直面しました

端末側の問題だと思い、以下のことを実施しましたが解決せず。

* 「ホーム画面」→「設定アプリ」→「スクリーンタイム」→「コンテンツとプライバシーの制限」をオンにし、  
「コンテンツとプライバシーの制限」画面にて「コンテンツ制限」を選択し、  
「許可されたWebサイトのみ」から「無制限アクセス」を選択します
* 「ホーム画面」→「設定アプリ」→「Safari」→「履歴とWebサイトデータを消去」を選択します
* 「ホーム画面」→「設定アプリ」→「Safari」→「Safari検索候補」をオフにします
* 「ホーム画面」→「設定アプリ」→「Safari」→「コンテンツブロッカー」をオフにします
* 端末を再起動します

結果的にこちら（ https://qiita.com/ameyamashiro/items/8d4be0f11ffe12472052 ）のページに辿り着き、
ELB における HTTP/2 の設定が有効となっているのが原因のようだったので、
HTTP/2 を無効にしたら無事 iPhone からページを表示することが出来ました。

設定手順は、
EC2 → ロードバランサー へ遷移し、説明タブの下方にある「属性の編集」ボタンを押し、
HTTP/2 の「有効化」チェックボックスのチェックを外して保存すればOKです。

HTTP/2 を使うことで画像、Javascript、CSSなどのファイルを並列処理で受け取れるのでページの表示速度は上がりますが、このような落とし穴もあるので、皆様お気をつけください。