OmniAICreator/Qiita-1.07M huggingface dataset:
ngrokを使ってdjangoアプリを限定公開する

# 目的
djangoアプリを限定的かつ手軽に公開するため、
ngrokを使ってローカルで起動しているdjangoアプリを外部から利用する。

# ngrokとは

ngrokとは、localhostで動いているサーバーを、LANの外からアクセスできるようにできるツールです。
詳細は→[ngrokの使い方（windows, mac）](https://qiita.com/Esfahan/items/74e71edfe17d9935d47e)

## ngrokの起動

ngrokを↓からダウンロードし、任意の場所で解凍する。
[ngrok](https://ngrok.co)

ngrok.exeを起動する
![ngrok.exe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150628/ce839f94-2256-a638-e499-076edef92ed0.png)

### ngrokの設定

djangoをデフォルトで起動した場合、ポート番号は8000となる。

```
System check identified no issues (0 silenced).
April 22, 2020 - 17:50:03
Django version 3.0.3, using settings 'project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
```

アプリのURL`http://127.0.0.1:8000/`をngrokで処理するため
ngrokのターミナル上で、`ngrok http 8000`を入力して実行する。
ngrok.exeに引数を渡して実行するのも〇
`ngrok.exe http 8000`
![ngrok.exe2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150628/468705e0-37cd-6ade-53b1-a33fcf3b956e.png)

Forwardingに表示されてる`xxxxx.ngrok.io/アプリ名`で外部アクセスができる。
アプリ名はapps.pyで定義したアプリケーション名。

### djangoの設定

djnago側ではngrokからのアクセスを許可する必要があり、`ALLOWED_HOSTS`に`'.ngrok.io'`を追記する。
**.ngrok**の前の文字列は起動の度にランダム生成されるため、起動時に影響しないようngrokからのアクセスのみを許可する。

```settings.py
ALLOWED_HOSTS = ['.ngrok.io']
```

ALLOWED_HOSTSの対応をしなかった場合には下記のエラーが発生する。

```
DisallowedHost at /app/
Invalid HTTP_HOST header: 'xxxxx.ngrok.io'. You may need to add 'xxxxx.ngrok.io' to ALLOWED_HOSTS.

Request Method:	GET
Request URL:	http://xxxxx.ngrok.io/app/
Django Version:	3.0.3
Exception Type:	DisallowedHost
Exception Value:	
Invalid HTTP_HOST header: 'xxxxx.ngrok.io'. You may need to add 'xxxxx.ngrok.io' to ALLOWED_HOSTS.
・
・
・

```
【python】DataReaderで経済データを取得する

[twitter](https://twitter.com/ichiharahiroshi/status/1252573799104442368)で下記チャートを紹介しました。
![VIX_SP500rtn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341224/1aaf66a2-53d1-cd4b-ecaf-f900ae157325.png)
このチャートは、
>横軸はVIX（恐怖指数）、縦軸はその後100日（約半年）騰落率。VIXの水準とその後の騰落率には正の相関がありランダムウォークではない。今のVIXが40程度なので、過去ケースから見ると半年後のリターンがマイナスになることはなさそう（投資は自己責任！）

ということを意味しています。

このチャートは、Pythonの`pandas_datareader`を使ってセントルイス連銀ウェブサイトからVIX（恐怖指数）とS&P500株価指数を取得して作りました。

ここにそのコードを保存しておきます。


まずライブラリの読み込み。

```python:
import pandas as pd
import numpy as np
import pandas_datareader.data as web

import datetime
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
```

#1.DataReaderでデータを取得

```python:
#取得するデータの開始日と最終日を指定
start = datetime.datetime(2010, 1, 1)
end = datetime.datetime(2020, 5, 1)


#S&P500のデータを取得
# 'SP500'がS&P500のティッカーシンボル。
# 'fred'が、データソースとしてセントルイス連銀を指定する。
#あとは開始日と最終日。
eq = web.DataReader('SP500', 'fred', start, end)

#VIXのデータを取得
# 'VIXCLS'がVIXのティッカーシンボル。
vix = web.DataReader('VIXCLS','fred', start, end)

#取得したデータを１つのデータフレームにまとめる
df = pd.DataFrame(index = eq.index)
df['Equity'] = eq
df['VIX'] = vix
df.dropna(inplace = True)
```

セントルイス連銀からは様々な経済・金融データを取得できます。
[セントルイス連銀ウェブサイト](https://fred.stlouisfed.org/)各データのURLの、一番最後がシンボルティッカーです。

例：VIXの場合は下記アドレスの最後、`VIXCLS`となります。
[https://fred.stlouisfed.org/series/VIXCLS](https://fred.stlouisfed.org/series/VIXCLS)

#2. グラフを作成

```python:
#グラフを作る関数
def chart(days):
    dfd = df.copy()
    dfd['Return'] = (dfd['Equity'].shift(-days) /  dfd['Equity'] -1)
    dfd.dropna(inplace = True)
    plt.figure(figsize = (8,4))
    plt.scatter(x = dfd['VIX'], y = dfd['Return'], alpha = 0.6, c = dfd['VIX'])
    plt.xlabel('VIX')
    plt.ylabel(str(days)+' days Return')
    plt.title('VIX and S&P500 '+str(days)+' days Returns (USD base)')
    plt.savefig('VIX_SP500rtn',bbox_inches="tight")

#何日間のリターンを計算するかを指定して関数実行
chart(100)
```

↓このグラフが作られます。

![VIX_SP500rtn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341224/6a0f2961-52d4-e5de-3eb5-3c68d3d65418.png)

`plt.scatter(x = dfd['VIX'], y = dfd['Return'], alpha = 0.6, c = dfd['VIX'])`
↑このコードの`c = dfd['VIX']`によって、VIXの値に応じてグラフ内の点の色を変えて、グラデーション効果を出しています。

# おまけ1：VIXチャート

```python:
df['VIX'].plot(title = 'VIX', figsize = (8,4))
```

![VIX.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341224/ce93b987-35e3-256a-e57a-391a5e644188.png)
# おまけ2：SP500チャート

```python:
df['Equity'].plot(title = 'S&P500', figsize = (8,4))
```

![VIX.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341224/f6036b8f-68bb-c5c3-eb60-285673d26fc0.png)
 
# おわりに
DataReaderでは、セントルイス連銀の経済データだけでなく、株価や為替など、様々なデータを取得することができます。詳しくは[DataReaderのドキュメント](https://pandas-datareader.readthedocs.io/en/latest/)をご参照ください。
macOS Catalina (10.15.3)におけるVagrant設定

macOS Catalina (10.15.3)におけるvagrant設定自分用メモ

各種アプリケーションのインストール

* VirtualBoxのインストール
https://www.virtualbox.org/

* vagrantのインストール公式サイトのDownloadsから
https://www.vagrantup.com/

※今回はrails-dev-boxを使う
希望のディレクトリ直下で以下を実行


```
$ git clone https://github.com/rails/rails-dev-box.git
$ cd rails-dev-box 
```

vagrantの実行

```
$ vagrant up
```

以下エラーが出る場合がある↓

```
Vagrant was unable to mount VirtualBox shared folders. This is usually
because the filesystem "vboxsf" is not available.
```

<img width="570" alt="スクリーンショット 2020-04-22 17.37.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110060/538ad164-27e8-8f4a-c493-9b52dd8a0af1.png">


解決には追加でパッケージを導入すれば良い↓

```
$ vagrant plugin install vagrant-vbguest
```

最後に立ち上げは以下の要領行います。

```
$ vagrant up
$ vagrant ssh
```
<img width="629" alt="スクリーンショット 2020-04-22 18.07.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110060/c14ef451-7727-3561-5f65-26b518e3622a.png">

以上で環境構築完了です。
waves ESP32 0.96“ OLED モジュール ESP-WROOM-32 ESP-32 CPU Lolin でRC522

ディスプレイにVSPIが使われているようで、RC522を使うには、HSPIを使う必要があるとか


あるいは、一般的にSPIで
　SDA→15
　SCK→14
　MOSI→13
　MISO→12
　RST→16
につないだとき、のSPIの設定と読み替えてもいいと思われる（確証なし)

```
SPI.begin();
```

などとなっている箇所を

```
SPI.begin(14, 12, 13, 15);
```
にするだけ。

#参考
https://trac.switch-science.com/wiki/esp32_tips
http://wakwak-koba.hatenadiary.jp/entry/20180504/p1
【Swift】Result型を使ってみた

Swift5.0以降でResult型が正式採用されました🎉
この前Loaderを新規で書く機会があって、Result型使えるじゃん！　と思って使ってみました。

# Result型とは
- success/failureの２パターンだけもつEnum
- エラー処理をswitch文を使ってシンプルに書ける
- 実際の定義は下記

```swift
public enum Result<Success, Failure: Error> {
    case success(Success)
    case failure(Failure)
}
```

- ジェネリクス型なので、Success/Failureの型は開発者が指定してやる必要がある
- Swift5以前だと、オリジナルでこの手のResult型っぽいEnumを自分で書いていたりライブラリ入れたりしていたと思うので、それはもはや要らない

# 使い方
たとえばLoaderのDelegateメソッドで、Result型を返す仕様にするとしたら、下記みたいに書きます。

```swift:DataLoaderDelegate
protocol DataLoaderDelegate: AnyObject {
    func dataLoader(didReceive result: Result<Data, DataLoaderError>)
}
```

```swift:DataLoaderError
enum DataLoaderError: Error {
    case timeout
    case jsonParseFailed
}
```

この例だと、successのときはData型を返し、failureのときはDataLoaderErrorというカスタムErrorクラスを返します。

# ViewController側の受け取り方
さて渡されたResultクラスをどう受け取ればいいかというと、下記みたいな感じで書けます。

```swift:DataLoaderDelegate
// MARK: DataLoaderDelegate
extension ViewController: DataLoaderDelegate {
    func dataLoader(didReceive result: Result<Data, DataLoaderError>) {
        switch result {
        case .success(let data):
            self.data = data
        case .failure(let error):
            print("DataLoaderError:" + error.localizedDescription)
        }
    }
}
```

Enumの連想値（Associated Value）をパターンマッチで取り出すのがポイントですね。
この取り出し方、実は今まで知らなかったんですけど、めちゃくちゃ便利ですね。
型情報も失われないのも嬉しい。

# 使いどころ
Result型自体は失敗する可能性のある非同期処理だけでなく、
try〜catch構文で書いていたようなエラー処理の代替手段にもなります。

[Swift 5 のResultに備える](https://qiita.com/koher/items/7e92414082476fb87b76)

↑の記事とかをチラッと読んだ感じだと、非同期処理はResult使うことでコードが読みやすくなる典型例みたいです。
Swiftチーム内でもResultをいつ使うべきか、明確なコンセンサスがないみたいですが、
**通常のエラー処理でResultを使うのは非推奨**なのは確かなようです。

そうなると現状使いどころってAPI叩くときの非同期処理ぐらいしかユースケースないよな、って思いました。
【ReactNative】react-native-mapsのMarkerのonPressイベントでMapのonPressイベントが発火してしまう

# 概要
先日[【ReactNative】react-native-mapsを導入する](https://qiita.com/nekoniki/items/61bfa4245c88a5ca0408)という記事を書いて、`react-native-maps`を導入しました。
そこでちょっとハマった事象があるので紹介します。

簡単に言うと、`Map`コンポーネントに`onPress`で地図を押下した際のイベントを指定した上で、`Map`上に`Marker`を配置し、こちらにも`onPress`を指定している場合に、`Marker`をタップして`onPress`を発火させると`Map`の`onPress`も同時に発火してしまうというものです。

```tsx:TestMap.tsx
import React from 'react';
import { Alert } from 'react-native'
import MapView, { Region, Marker, LatLng } from 'react-native-maps';

render(){

    // 初期表示位置
    const initialRegion : Region = {
        latitude : 35.689521,
        longitude : 139.691704,
        latitudeDelta : 0.0460,
        longitudeDelta : 0.0260,
    }

    // マーカーの表示位置
    const coordinate : LatLng = {
        latitude : 35.689421,
        longitude :139.691604
    }
    <MapView initialRegion={initialRegion} onPress={()=> { Alert.alert("マップを押したよ") }} >
        <Marker coordinate={coordinate} onPress={()=>{ Alert.alert("マーカーを押したよ") }} />
    </MapView>
}
```

# バージョン情報
```
"react-native": "0.61.5",
"react-native-maps": "^0.26.1",
"native-base": "^2.13.8",
```

# 対処法
`Marker`の`onPress`に`MapEvent`型の引数を指定して`stopPropagation()`を実行します。
これにより`Marker`→`Map`へのイベントの伝播が止まります。

```jsx
<Marker coordinate={coordinate} onPress={(e : MapEvent) => {
            // マップにonPressイベントが伝播するのを止める 
            e.stopPropagation();
            Alert.alert("マーカーを押したよ")
        }} />
```

# おわりに
`react-native-maps`を使っていて、***マップをタップしてマーカーを置き***、***マーカーをタップした時に何かをする***というのはよくあるパターンだと思います。
一度対応を覚えればなんてことない内容なのですが、備忘として残しておきます。
【Nuxt.js】導入に必要なサーバ要件について

# サーバで動かすには何が必要なの？

まずはローカル環境でいろいろ試すとは思いますが、
実際にプロダクトとしてサーバにローンチするにあたり、結局のところ
**動作させるにはどんな環境が必要なのか？**という軸でざっくり説明したいと思います。
なので、Nuxt.jsそのものがどんなものなのか、はここでは割愛させていただきます。

### そもそも何故こんな記事を書こうと思ったのか

自身はPHPを中心としたバックエンドよりの仕事が多かったため、
Vue.jsやNuxt.jsの台頭によるフロントエンドの隆盛を横目で流し見していました。
さすがにこりゃいかん、と、思い始めたのも2018年あたりという…
で、細々と勉強をしている中で、文法作法はさて置き、いまいち分からなくなるのが
**開発とローンチ(サーバ)での動作環境**についてでした。
詰まるところ、ローカルではNode.jsやらnpmやらwebpackやらVueCLIやら
あれもこれもインストールして大盛り上がりな状態で開発していくんですが
**ローンチするサーバには結局、どんな要件があれば動くの？**ってところが非常に分かりにくかったんですね。
その切り口でシンプルに解説している投稿もなく
(もしかしたら昨今のフロントエンドエンジニアは、肌感で当たり前になっていることなのかもしれないが…)
ここは**自身に言い聞かせる**意味でも、あえて記事にしておこうと思った次第です。

## モード別に見るとこんな感じ
Nuxt.jsには、モードによりデプロイ結果が変わってくるという仕様があります。

| Universal(ユニバーサル)|Single Page App(シングルページアプリケーション)|Generate(静的ファイル生成)|
|:------------------------------------------|:------------------|:---------------------|
| ssr(サーバーサイドレタリング) | SPAってやつ　　　　　　 |        生のhtmlを書き出し        |
| UIレンダリング全体を担う | ミドルウェアとして組み込む, プログラムの一部として使う| vueファイルからhtmlに生成してしまう |
| 静的ホスティング不可  |  静的ホスティング可(buildしたdist一式アップすれば動く) 　　　　|      静的ホスティング可(buildしたdist一式アップすれば動く)       |
| サーバにNode.jsいる  |  サーバにNode.js不要 　　　　|      サーバにNode.js不要      |
| phpと同じように、サーバ側でレンダリングしてhtmlを作成してからレスポンス返す  |  フロントにてjsでhtmlをレンダリングするので、初回が遅い。あと、jsでhtml生成なので、SEO的に弱い|      ただのhtmlサイト。ある意味では最強の状態     |
| SEO OK   |              SEO△　個別のメタやOG× |        SEO OK        |
| いろいろコスト高い     |         コスト低い　 |         コスト低い         |
| サクサク        |       初回重い |       普通       |
| 中～大規模サイト     |           LP,小～中規模 |      ALL       |
※デフォルトはユニバーサルモード

なんというか、つまり
サーバ側でNode.jsさんがごにょごにょしてページを作ってからフロントに返し、フロントはただそれを表示するだけか**(SSR)**、
とりあえず最初にサーバから材料まるっとフロントに渡して、フロントのjsさんが頑張ってごにょごにょして都度ページをレンダリングして表示させるか**(SPA)**、
はたまた、なんてことない生のhtmlを用意するか**(静的サイト)**、
という**三つのやり口**があるんです。

余談ですが、静的htmlのジェネレートもできるんだ、ってちょっと驚きでした。
これ、**MT(MovableType)みたいな使い方もできる**んだ…って。

あと、SPAのところで一つ補足
ダイナミックレンダリングって技術があるようで、
ボットのクロール用にはhtmlを読ませて、ブラウザからの人のアクセス時にはjs生成ページを見せるみたいな
使い分けを行うことでSEOを補完するやり方もあるようです。
しかし、SSR移行までの一時しのぎ、的な位置づけのようで、
定着させる必須技術というわけではないですね。

こう考えると、はっきりしてくるんですが、
ユニバーサル、つまり**SSRするときは、当たり前ですがサーバ要件にnode必須**ということですね。
で、SPAとなるとサーバ側でレンダリグする必要はないので、サーバにnodeは不要、ローカルの開発環境にだけあればよいですし、
Generateでも同じことですね。

## 結局のところ
Node.jsがいるんです。ただそれは、**ローカルの開発環境には必須**ということであり
SSRモードで利用しないのであれば、サーバにNode.jsは不要です。
という、ものすごく単純で当たり前のことに行き着くのでした。

Nuxt.jsをプロジェクトに導入する場合は、
必ず**サーバ要件でNode.jsが使えるかどうか確認**してからにしましょう。
**SSRでいくぜ！なんて息巻いて**みても、後でやっぱりできませんでした…なんてことがないようにね！
Udonノードを用いたanimator　Part1

みなさんこんにちは。2020年4月にVRchatが更新されUdonが追加されました。
皆さんUdon楽しんでいますか？
animatorに関する検証が日本語で書かれていなかったので私なりに検証したものを解説していきます。なお私自身C#を触ったことはないので、ノードにて不安定な値の渡し方などあったら申し訳ない。
では、はじめて行きましょう。
# 目標
Bool型変数を用いたanimationの駆動に関する理解

#おしながき
- 作成した機構(ギミック)の説明
- Udonノードでのanimationのプログラム(メイン)

## はじめに
今回animatorの解説はU#ではなく、Udonノードで行います。
理由は僕自身がこれまでVRCTriggerを用いたギミックしか
作成したことがなかったため。
(~~私がC#を触ったことがないためではありません~~)

○開発環境
- Unity 2018.4.20f1
- VRCSDK3の最新版（2020年4月22日現在、VRCSDK3-UDON-2020.04.17.11.43）

##サンプルのギミック
今回は「Animator_bool_stu」という機構をもとに解説していきます。
この機構は赤いボタン(Button)に触れると、キューブ(moving_cube)が180度回転するものです。※ローカルで動作します

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621662/47ca4489-fe23-de5d-94fa-c0f69e202c57.png)

なおanimatorはキューブ(moving_cube)に設定。
Bool型変数名はV、animatorの遷移図は以下のように設定しています。
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621662/7bbf43d9-0361-8ccf-c858-12bd17ff6c2b.png)

Vがtrueでrotate(idleの状態から180度回転した状態)に遷移、falseでidle(初期状態)に戻ります。
各animationには状態のみが保持され、動くanimationは遷移時間で表現しています。

##Udonノードの作成
赤いボタン(Button)にanimationが駆動できるように設定します。
ButtonオブジェクトにUdonBehaviour(script)コンポーネントを追加し
udonを追加します。
![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621662/671096e3-e695-e389-2e4b-bd441f47df2c.png)

設定したUdonは以下2つから構成されています。(同一面)

- animatorの取得部
![キャプチャ4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621662/cc261d1a-7d6e-be00-e47d-49320e1a0431.png)
 
- animatorの駆動部
![キャプチャ5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621662/9d62cf40-11de-c373-1f6a-fec5e6c59e98.png)

## Udonノードの解説
○animator取得部

ここでは、ゲーム開始時に「game object find」でhierarchyからanimatorの設定されたオブジェクトを探し出し、「game object get componet」でオブジェクトからAnimatorコンポーネントを取得し、Udon内で宣言したanimator名(anim_tmp)に格納するとなっています。
「start」はおそらくゲームがスタートしたらというメソッドです。

| 名称       | 詳細 |    
|:-----------------|:------------------:|
| Start             |              ゲーム開始時に呼び出される | 
| Update           |            毎フレームごとに呼び出される | 

私が調べた限りでは毎フレームごとに呼び出すのは負荷があるので、毎フレームごとに呼び出す必要ない場合はStartメソッドを利用したほうが良いようです。

なお、Animatorコンポーネントがボタン(トリガ)の親階層や子階層にある場合は,
図(この場合は親階層)のように簡潔にanimatorを取得できます。
(~~同階層の取得はゲームオブジェクトを見つけて取得する方法以外にもあると思いますが~~)
![キャプチャ6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621662/4fbf5948-8468-df2c-6f65-60bfba4f77d8.png)

○animator駆動部

ここでは、マウスでボタンが触られたら、bool型変数Vを取得し、boolにセット(trueをfalse、falseをtrue)にするノードとなっています。「Op Unavy Negation」はプログラムで言うところの、A=Aに相当するものです。
なおトリガは「on mouse down」(unity上で実行したときのクリック)となっていますが、VRchat上で使うときのトリガは以下URLに乗っています。
https://ask.vrchat.com/t/vrc-triggers-udon/196

基本的に、この部分の大まかな構造はfloat型、int型でのanimationでも大体同じです。
(int型とfloat型はUdonノードを用いたanimator　Part2以降で解説します)

## 実行結果
![ダウンロード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621662/f32a4ec2-07a6-03d9-a55d-e0e01a2f94af.gif)

## まとめ
- animationを使うには、animatorを取得する記述が必要がある
- 現時点(2020/4/22)ではanimationはローカルでしか動かない
- Udonを用いてanimatorを起動するには、VRCTriggerよりも明確な命令が必要

## 最後に
　私自身、初めてQiitaで解説を書いたので正直わかりずらい部分があったり、未熟な部分があると思います。
とりあえず、私含むC#やったことない勢は、各ノードは使って慣れていくしかないように思えます。またudonのノードで用いた関数やメソッドの理解にはUnityのC#の解説記事が役に立ちました。(~~C#学べ~~)

次回はfloat型とint型のanimationを起動するUdonを書いていきたいと思います。
Wacom Cintiq ProをMacで使うと「ペン先の位置調整」が表示されない

MacでCintiqProを繋ぐと、
毎回ペン先がずれて、しかもペン先の位置調整が出ない・・・という問題が起きていました。
デバイスドライバを入れ直しても、まったく改善しません。

これを改善するには
アクティビティモニタのある「WacomTabletDriver」を強制終了して再起動させるしかありません。
ただ、液タブを起動するたびに、
アクティビティモニタ開き、タスク選んで、強制終了して、ペン先位置調整して・・・なんてやってられない！

なのでAutomatorを使います。

Automatorの新規ファイルで「ワークフロー」を選び、
「AppleScriptを実行」を追加しましょう。
追加したら、ソースコードを以下に置き換えます。

```
kill_aProc("WacomTabletDriver") of me
on kill_aProc(aProcName)
	tell application "System Events"
		set procList to every process whose name contains aProcName
		if procList is not equal to {} then
			set aProc to contents of first item of procList
			tell aProc
				set anID to unix id
			end tell
			do shell script "kill -9 " & (anID as string)
		end if
	end tell
end kill_aProc
```


<img width="928" alt="WacomTabletDriver Automator" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410880/de7a4c6a-fd2c-1e1d-e5a0-37eb7ef7fbac.png">


保存する時に「アプリケーション」として保存します。
その後、Dockに登録すると、1クリックでタスクキルできます。

<img width="248" alt="WacomTabletDriver TaskKill" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410880/06af145e-db1d-1f46-6a18-49bf79c7411b.png">

アプリケーションを実行すると、
グレーアウトしている「位置調整」ボタンが押せるようになります。
アプリを再起動すると、その時点でペン先のズレが基本的に解決しますが、
モニターの解像度をMac側の認識で間違えていると、ペン先はズレます。。。
そのときは「ディスプレイ」の解像度設定を見直しましょう。

<img width="667" alt="スクリーンショット 2020-04-22 17.20.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410880/cdd51153-49b5-3a97-fd26-a6837036a696.png">
Synology NAS(DSM)でマウントした暗号化フォルダを自動的にアンマウントする

# はじめに
Synology NAS(DSM)でマウントした暗号化フォルダを自動的にアンマウントする方法です。

# 検証環境
- 型番：DS218j
- DSMバージョン：DSM 6.2.1-23824 Update 6

# ずばり
コントロールパネル -> タスクスケジューラー
作成 -> 予約タスク -> ユーザー指定のスクリプト
タスク設定の「ユーザー指定のスクリプト」に

`synoshare --enc_unmount <共有フォルダ名>`

を指定する。

アンマウントすると全共有フォルダが一旦アンマウントされるので、自分はパソコンを操作しない深夜帯の時間に実行するよう指定してます。

# 備考
マウントされてないフォルダに対して上記コマンドを実行しても問題ないことを確認してます。
初心者がVagrantでローカル環境にLAMP環境構築してみた（マウント編）

[初心者がVagrantでローカル環境にLAMP環境構築してみた](https://qiita.com/tonkatu_tanaka/items/e88c212d328977d778f3)の続編。
ホストOSとゲストOSのフォルダ共有化で手こずったのでメモ

# 前提
すでにVagrantでLAMP環境構築したけどローカルにあるファイルたちをVagrant環境で使いたい。
Vagrant環境（ゲストOS）にローカル環境（ホストOS）のフォルダ（ディレクトリ）をマウント（共有化）し、
開発をすすめたい。

下記エラーが出て手こずった思い出。。。

```
Vagrant was unable to mount VirtualBox shared folders. This is usually
because the filesystem "vboxsf" is not available. This filesystem is
made available via the VirtualBox Guest Additions and kernel module.
Please verify that these guest additions are properly installed in the
guest. This is not a bug in Vagrant and is usually caused by a faulty
Vagrant box. For context, the command attempted was:
```

---

# ローカル環境
マシン：mac os 10.15.4
知識：Linuxを少しいじったことがあるくらい

# 構築環境


| LAMP | version |
| --- | --- |
| centOS | 7 |
|APACHE|2.4|
|PHP|7.3|
|MYSQL|8.0|


---

# 手順

## 1，プラグインのインストール

ローカル環境（ホストOS）からコマンド実行

- Vagrant環境（ゲストOS）にログインしている場合はログアウト

```
exit
# もしくは control + d
```

- プラグインインストールして実行

```
vagrant plugin install vagrant-vbguest
vagrant vbguest
```

### 2，Vagrantfileの編集
Vagrantfile の下記行のコメントアウトを外し、内容を適宜自分の環境に置き換える。
参照：[初心者がVagrantでローカル環境にLAMP環境構築してみた](https://qiita.com/tonkatu_tanaka/items/e88c212d328977d778f3)

```
config.vm.synced_folder "xxxxxxxxxxx", "/var/www/html", mount_options: ['dmode=777','fmode=777']
# config.vm.synced_folder "ホストOSの共有したいディレクトリパス", "ゲストOSの設置場所", mount_options: ['dmode=777','fmode=777']
```
xxxxxxxxxxx（ホストOSの共有したいディレクトリパス）Vagrantfileが置いてあるディレクトリからの相対パス。

### 3，Vagrantの再起動

```
vagrant reload
```

---

参考：vagrant up 時の共有フォルダのマウントエラー解消方法
https://qiita.com/takutoki/items/33cf1230e032931f9adc
【自分用メモ】WSLでMinillaを使うことになったのでインストールメモ

　昔作ったCPANモジュールにバグレポートをいただいたので、5～6年ぶりにCPANにモジュールをアップすることになりました。
　んが！ずっとPerlを書いていなかったので、手元にPerl開発環境が入っていなかった。しかも、セットアップ方法を忘れていました。

　インストールでいろいろハマったので、自分のメモ用にインストールメモを残しておきます。


今回整える環境
=============

　修正するモジュールが [Minilla](https://metacpan.org/pod/Minilla) を使って作られていた[^1]ので、現在メインで使っているWSL1のUbuntuの上にMinillaをインストールします。

[^1]: ちなみに、Minilla v0.8.0 で生成されておりました。何年前だ？

　次のものはすでに入っているものとします：

- Windows 10 Pro
- WSL1
- Ubuntu 18.04
- perl 5.30


aptでビルドツールをインストールする
================================

CPANモジュールのビルドに必要になるコマンド類をインストールします。aptで次のものをインストールしましょう:

```shell-session
sudo apt install build-essential patch
```


cpanmをインストールする
=====================

　なにはともあれ cpanm をいれます：

```shell-session
curl -L https://cpanmin.us | perl - App::cpanminus
```


Minillaをインストールする
=======================

　上で入れた cpanm でを使って Minilla をインストールします:

```shell-session
cpanm Minilla
```

　が、ここでいきなりビルドにつまづきます。build.logを見ると、ヘッダファイルがないとか言われています：

```
Building and testing Module-Build-Tiny-0.039
cp lib/Module/Build/Tiny.pm blib/lib/Module/Build/Tiny.pm
t/00-compile.t .......... ok
t/release-pod-syntax.t .. skipped: these tests are for release candidate testing
In file included from lib/Simple.xs:3:0:
/home/ubuntu/.plenv/versions/5.30.0/lib/perl5/5.30.0/x86_64-linux/CORE/perl.h:732:13: fatal error: xlocale.h: No such f
 #   include <xlocale.h>
             ^~~~~~~~~~~
compilation terminated.
```

　`xlocale.h` がないとか言われても知らんがな・・・と思ってGoogle先生に聞くと、なんでもしばらく前にglibcから消えたヘッダファイルなんだとか。
　[workaroundはシンボリックリンクを張ることらしい](https://github.com/carla-simulator/carla/issues/503)ので、おとなしく従います:

```shell-session
sudo ln -s /usr/include/locale.h /usr/include/xlocale.h
```

　これで Minilla のインストールが成功します:

```shell-session
cpanm Minilla
```


Minillaのoptionalモジュールのインストール
=======================================

　`minil release` を実行しようとすると、Version::Next が必要だと言われるのでインストールします:

```shell-session
cpanm Version::Next
```

　さらに、CPAN::Uploader も必要と言われるのでインストールします:

```shell-session
cpanm CPAN::Uploader
```

　が、ここで問題が。
　CPAN::Uploader は HTTPS で通信するのでビルドに OpenSSL が必要です:

```
SSLeay.xs:163:10: fatal error: openssl/err.h: No such file or directory
 #include <openssl/err.h>
          ^~~~~~~~~~~~~~~
compilation terminated.
```

　さらに、Zlib も必要でした:

```
LD_RUN_PATH="/usr/lib/x86_64-linux-gnu:/lib/x86_64-linux-gnu" cc  -shared -O2 -L/usr -L/usr/lib -L/usr/local/lib -fstac
   -L/usr -L/usr/lib -lssl -lcrypto -lz   \

/usr/bin/ld: cannot find -lz
collect2: error: ld returned 1 exit status
Makefile:493: recipe for target 'blib/arch/auto/Net/SSLeay/SSLeay.so' failed
```

　というわけで、再び apt に戻って依存ライブラリをインストールしましょう:

```shell-session
sudo apt install libssl1.0-dev zlib1g-dev
```

　Ubuntuではこの2つをインストールすれば良さそうです。
　これで CPAN::Uploader がビルドできます:

```shell-session
cpanm CPAN::Uploader
```

　これで無事に `minil release` ができるようになりました。

　めでたし、めでたし。
Python：クラス変数とインスタンス変数

クラス変数とは、そのクラス共通の変数で、
インスタンス変数とは、そのインスタンスだけで使う変数です。
初学者覚書です。

例

```
class enemy:
    # クラス変数
    # インスタンスオブジェクト間で共有する変数
    ENEMY_MAX = 100  # 敵の数最大値
    CHARACTER = 'Ｏ' # 敵の表示キャラクタ

    def __init__(self,x,y):
    # インスタンス変数
    # インスタンスオブジェクト間で共有しない変数
　       self.alive = True # 敵生きているフラグ
  　     self.x = x        # 敵x座標
    　   self.y = y        # 敵y座標
```
確実にクラス変数にアクセスするには、クラス内、外からでも、「クラス.変数名」とします。
「ビルドツール」についてざっくりまとめ

どーも、ふぎとです。
今回は「ビルドツール」について、ほぼ自分用の
アウトプットです。
なんか間違ってたら教えてください。
ほないきます。

#そもそも「ビルド」とは

ある環境でプログラムを実行できるように、
アプリケーションやライブラリを組み立てる
こと。ソースコードの解析、コンパイル、ラ
イブラリへのリンクなどを経て実行ファイル
を作成する
    
#ビルドの方法

##手動ビルド
人の手で１つ１つ処理する

##ビルド処理のスクリプト化
処理をスクリプトに起こして固定化
（Javaでいうとmainメソッドにビルド
処理をつらつらと書く感じ？）

##ビルドツールの使用
ビルドを構成するタスク（ソースコード
解析、コンパイルなど）を個別に定義し
実行するツールを使う
    
#代表的なビルドツール

##Ant 
・Apacheというところが開発、公開して
いるJavaプログラムのビルドツール。
Eclipseに標準で組み込まれている。
            
・ビルドファイル（ビルドに関する設
定を記述するファイル）は"build.xml"
という名前で存在する。XML形式なので
可読性は低い

・システムが大きくなるとビルドファイ
ルが肥大化してしまう
        
##Maven
・Antに代わるものとして作られた、Ja
vaプログラムのビルドツール

・POM（Project Of Model）の考え
方に基づく

・ビルドファイルは"pom.xml"

・プラグインによる拡張（フレームワーク
の導入など）ができるが、ビルドファイルは
XML形式なのでやっぱり読みにくい

##Gradle
・AntやMavenのコンセプトをもとに開発
されたビルドツール
           
・Java開発のデファクトスタンダードに
なりつつある（らしい）
            
・ビルドファイルは"build.gradle"。
GroovyというJavaに近いプログラミン
グ言語で記述されるのでXML形式より読
みやすい

・ただしシンタックスシュガー（略記）
も多いので学習コストが低いという訳
ではない

本日はここまで。ではまた。
Simotion - SIMOSIMシミュレーターを使う


#SIMOSIMとは？
SIMOSIMはUserをSimotion Runtimeシステムをテストするシミュレーターです。このソフトはSimotion Scout・Scout TIA同時に走るおことできますが、
一回は一個のSIMOSIMしか走りません。

#注意
- SINAMICS Integrated とIOはシミュレーションできません。(モジュールアラームもありません)
- 一個”キレイ”なVMでやったほうがよいだと思います。自分のHostが色々なものがインストールしてて、何回起動したらエラーになり、プロジェクトダウンロードさえもできません。
- モーションコントローラーのバージョンがV5.1以上じゃないと使いません。

#ソフトバージョン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/1207c205-b4bd-ba3c-37e7-467308ce6168.png)


#流れ
私使ってるのはScout TIAでなので、まずいまのプロジェクトの開いて、モーションコントローラーのところ右クリックし、”Change Devices”をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/c178e24b-3a1e-179a-403a-190486ad296a.png)

先も言いましたが、SIMOSIMを使うにはV5.1以上じゃないとだめです。
ここでモーションコントローラーのバージョンをV5.1にあげます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/c18de304-f11e-dae1-e5be-b9df40119c37.png)

そのあと一回Ctrl+Bでハードウェア構成をコンパイルします。
次はProject>Open SIMOTION configurationをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/543470b0-60fe-ed17-d01e-5f28ef2495ae.png)

Scoutが立ち上げて、次はモーションコントローラーを選んで右クリックし>Save and recompole allでプロジェクト全体をコンパイルします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/22e4f8ab-16d1-8887-e05d-c0b974bfe945.png)

余談ですが、もしSIMOSIMが使えるのであればこのICONがクリックすることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/598fa14b-b504-23cc-4a99-d89ed31cbdf1.png)

同じく、モーションコントローラーを選んで右クリックし、”Start SIMOSIM”がクリックできるようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/b49f6a65-ba93-3376-becb-20a1bdea3b68.png)

ごの画面が出てきます。
1. いま使ってるDriverの設定を使いますか？と。
2. PG/PCはパソコンとSimosimの間を繋ぐのインタフェースを設定する。
3. Access Pointというのは、D4xxなどたくさんのPortがあり、どこのPortを使ってアクセスするか。
4. まぁ、Yesです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/c059eadb-f830-b137-c57f-dd6ff043b8b6.png)

PG/PCを”Siemens SIMOSIM Virtual XXXXXX”を選んでください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/128e7979-e298-f5b1-0907-deea5fd582d8.png)

Access Pointのところ>Device Address>X127を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/78c589e5-e903-518c-0181-9e24299d29f0.png)

最後”YES”を押したら、SIMOSIMが立ち上がります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/708417a7-93d7-2316-0900-9031477314bf.png)

このICONをクリックしアクセスできるデバイスを探します。(いわゆるこのシミュレーター)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/cffcadfc-127b-6b31-6861-f6bd48fb9a8a.png)

最後はOnlineして、プロジェクトダウンロード。終わりです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/84478fbd-64b7-2f14-3d7d-6d720bf97d1b.png)

#参考LINK
[SIMOSIM Software request](https://support.industry.siemens.com/tf//WW/en/posts/simosim-software-request/196544?page=0&pageSize=10)
[Access to TCP/IP failed.](https://support.industry.siemens.com/tf/WW/en/posts/access-to-tcp-ip-failed/176800?page=0&pageSize=10)

いつもこの方に助けられていますー。ありがとうございます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/83fa46f9-ff7e-9bd4-9cc4-bdab24c7034f.png)

はいーお疲れ様ですー。
Pythonで毎日AtCoder #44

### はじめに
[前回](https://qiita.com/taxfree_python/items/a34bee69f7c5fa0ea11a)
Boot campの問題を5問解きます

### #44
[ABC056-C](https://atcoder.jp/contests/abc056/tasks/arc070_a)

**考えたこと**
iまでの非負整数の和は$\frac{1}{2}n(n+1)$となり}}ます。この和が$X$になるのは$\frac{1}{2}n(n+1)=X$のときで、$n$について解くと、$n=\frac{-1\pm{\sqrt{8X+1}}}{2}$となります。この式の解にceil記号を付けると$\lceil \frac{-1\pm{\sqrt{8X+1}}}{2} \rceil$となります。これが答えになります。

```python
import math
x = int(input())

f = (-1+math.sqrt(8*x+1)) / 2
print(math.ceil(f))
```

[ABC066-C](https://atcoder.jp/contests/abc066/tasks/arc077_a)

**考えたこと**
操作のたびにreverseしてると死ぬので、反転しているかをboolで管理します。データの左右にしかアクセスしないのでdequeを使います。あとは、操作を実装するだけ

```python
from collections import deque
n = int(input())
a = list(input().split())

b = deque([])
r = False
for i in range(n):
    if r:
        b.appendleft(a[i])
    else:
        b.append(a[i])
    r = not r

if r:
    b = reversed(b)
ans = ' '.join(b)
print(ans)
```
[類題](https://atcoder.jp/contests/abc158/tasks/abc158_d)

[ARC069-C](https://atcoder.jp/contests/arc069/tasks/arc069_a)

**考えたこと**
まずはcをsに合成せずにいくつのsccを作成できるかを考えます。cをsに合成せずに作れるsccは$min(N,M//2)$となります。
次は合成した場合を考えます。合成すると2個のcが1個のsになるので、cからsを作ろうとすると4個のcが必要になります。あとは実装するだけです。

```python
n, m = map(int,input().split())

if m - 2 * n >= 0: #合成せずにsccが作れるかどうか
    ans = n + (m-2*n)//4
    print(ans)
else:
    print(m//2)
```

[ABC130-C](https://atcoder.jp/contests/abc130/tasks/abc130_c)

**考えたこと**
分割する点が中心にあるなら分割方法は無数に存在します。また、分割したときの大きくない方の面積は全体の半分です。

```python
w, h, x, y = map(int,input().split())

s = w * h / 2
if 2*x == w and 2*y == h:
    print(s,1)
else:
    print(s,0)
```

[ARC081-C](https://atcoder.jp/contests/arc081/tasks/arc081_a)

**考えたこと**
$A_i$の要素についてcountするとおそらくTLEするので、別の方法でカウントしていきます。sortして値の区切りでカウントしていく方法で実装します。一番長い辺が4本以上あればそれ辺で作れる正方形が最大になります。そうでなければ、二本ある一番目の辺と二本ある二番目の辺の長方形になります。

```python
n = int(input())
a = list(map(int,input().split()))

a.sort(reverse=True)
c = 0
v = []
for i in range(n-1):
    if a[i] != a[i+1]:
        c += 1
        if c >= 2: #辺が二本以上のときのみappend
            v.append([a[i],c])
        c = 0
    else:
        c += 1
if a.count(a[-1]) >=2:
    v.append([a[-1],a.count(a[-1])])
if len(v) == 0: #vが空なら四角形は作れない
    print(0)
elif v[0][1] >= 4: #正方形になる
    print(v[0][0]**2)
elif len(v) >= 2: # 長方形
    print(v[0][0]*v[1][0])
```

### まとめ
これくらいなら解ける。ではまた、
Google Apps Script(GAS)個人的ヘルプ集

Google Apps Script(GAS)によるスクリプト作成・実行に関する個人的なヘルプ的メモ。
随時、編集していく予定。

#スクリプト編集用のエディタ画面を開く
スプレッドシートのメニューに「ツール」があるので、そこから「スクリプト エディタ」をクリックする。
![gasmemo0-d1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409430/d01c7146-6a79-cb0c-2f5b-5450908ff966.jpeg)

#初めてスクリプトを実行するときの手順
作成したスクリプトを実行するときは、最初だけ、ツールバーの右向き三角アイコンをクリックした後、以下の手順が必要（次からは不要）

1. 「Authorization required」ダイアログが表示されるので、「許可を確認」をクリックする。
2. 「アカウントの選択」ウィンドウで、作成したスクリプトが紐づいているスプレッドシートのオーナー（所有者）のアカウントを選択する。
3. （作成したスクリプト名）がスプレッドシートへのアクセスをリクエストしているとの確認ウィンドウが表示されるので、「許可」をクリックする。
4. **（ここから先は、Gmailのアカウントでログインしている場合のみ必要）** 「このアプリは確認されていません」ウィンドウが表示されるので、「詳細」をクリックする。
5. 4.で「詳細」をクリックすると、ウィンドウ下部に「メッセージダイアログ（安全ではないページ）に移動」リンクが表示されるので、それをクリックするとスクリプトが実行される。

#変数を定義する「let」などES2015(ES6)以降の記述で保存時にエラーが出るとき

![gasmemo1d.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409430/848e45d3-07c3-507f-32b3-0a8947a17608.jpeg)

記述ミス等がないようであれば、環境がV8ランタイムに対応してないので、メニューに「実行」があるので、そこから「Chrome V8 を搭載した新しい Apps Script ランタイムを有効にする」をクリックしてから改めて保存する。

![gasmemo2-d1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409430/ae8586ec-73e8-9ed0-4c07-ad29c12e7557.jpeg)

※「console.log」を記述してあるのに、スクリプト実行後にメニューの「表示」から「ログ」でログが表示されないときも、環境がV8ランタイム対応になっているか確認してみる。

[参考にさせていただいたページ]
【初心者向けGAS】スクリプト実行時の「承認」でびっくりしないために
https://tonari-it.com/gas-script-approval/

[GAS] V8ランタイムを有効にし最新のECMAScriptを動かす
https://blog.katsubemakito.net/gas/enable-v8
AWS トレーニングメモ part2

#クラウド導入に対する懸念
クラウドとはIT利用の新しい形。
クラウドを利用するのは当たり前になりつつある。


懸念
・オンプレミスの方が安全。
・コストが高い。
　　↓
都市伝説

真実
・様々な認証を得ているので、オンプレミスと同等あるいはそれより上である。
・TCOの観点で見ると大幅に削減できる

###マネージドサービス
物理的な環境準備から設計までを包括的に行うサービス。
顧客が行うのは、データの登録から。
なのでサービスに集中できるようになる

#AWSにおけるセキュリティとコンプライアンス
クラウドセキュリティはAWSの最優先事項

###AWSの考え方
・責任共有モデル


###AWS WAF
ウェブアプリケーションファイアウォール
一般的なウェブエクスプロイトからウェブアプリケーションを守る
ハードウェアのセキュリティ対策


###AWS Shield
マネージド型のDDoS保護
⇨マネージド型の分散サービス妨害に対するサービス
　AWSで実行しているアプリケーションを保護する
　スタンダード機能は、自動で追加されている。

#Well Architected Frameworkの紹介

クラウドアーキテクトがアプリケーション向けに実装可能な、安全で高いパフォーマンス、障害耐性を備え、効率的なインフラストラクチャを構築するのをサポートする目的で開発された。
・クラウド設計・運用のベストプラクティス
・ベストプラクティスが記載されたホワイトペーパー
・レビューをお手伝いする（AWSのSA or 認定をうけたパートナーも可能になる）


#サーバレスプラットフレームワークの機能
サーバレス＝サーバにおいて何も考えることないこと

サーバーを意識することなく、効率的な開発ができる。
サービスの組み合わせで実現。

AWSLambda
⇨サーバレスでコードの実行ができる




#AWSへの移行

個別プロジェクト
↓
ハイブリッド化
↓
大規模移行
↓
クラウド最適化

####DB
RDSを先に検討して、適当でない場合はEC2

#####Amazon Aurora
クラウドに合わせたデータベース。
ポスグレよりも高性能




#DXに向けたAWS活用
クラウドで新しいチャレンジを可能に。
例
AIサービスなど






#AWSトレーニングと認定、学習関連リソースの紹介

・クラウドサービス活用資料集
　⇨Black Beltセミナー
・技術ドキュメント
・ホワイトペーパー



#単語
###レイテンシ
待ち時間、反応時間のこと
【Android】FragmentでBackボタンを押した際のイベントを簡単に制御する

# 概要
- とあるアプリを作成しているときにバックボタンを無効化する処理を入れたかったので、その備忘録
- ActivityだったらOnBackPressedをオーバーライドするだけでOKだが、fragmentではそうもいかない

```MyActivity.java
@Override
    public void onBackPressed() {
      // バックボタンが押された際の処理を入れる
    }
```
- Interface経由で値を渡すこともできるけど、IDとかタグの指定をするのも面倒。。。
- もっと簡単な方法を探っていたところ、OnBackPressedDispatcherを使えばFragment内だけで実装可能のようです
（最初からドキュメント見てれば一番早かった。。。）
- https://developer.android.com/guide/navigation/navigation-custom-back

# 方法

```MyFragment.java
public class MyFragment extends Fragment {
    private OnBackPressedCallback mBackButtonCallback;

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {

        mBackButtonCallback = new OnBackPressedCallback(true) {
            @Override 
            public void handleOnBackPressed() {
                // バックボタンが押された際の処理を入れる
            }
        };
        requireActivity().getOnBackPressedDispatcher().addCallback(this, mBackButtonCallback);
    }

    @Override
    public void onDestroy(){
        mBackButtonCallback.remove();
        super.onDestroy();
    }
}
```

# 備考
- 非常に楽なんですが、これを実装する際はonDestroyなどでremove()して明示的にコールバックを解放しないと、他のFragmentなどでも処理が実行されてしまいます。
- 勝手に解放してくれるわけではないので、その点だけ注意が必要かと思います。
GraphQLチュートリアル

締め切りのある開発者向けの実際の[GraphQL](http://hasura.io/graphql/)チュートリアル！

フロントエンドおよびバックエンド開発者向けのハンズオンチュートリアルを使用して、GraphQLの基本から本番環境に対応したコンセプトに移行します。

このウェブサイトにアクセス-http://hasura.io/learn/
Flutter の Text 、赤文字に黄色のアンダーラインってなんなの？

Flutter の `Text` ウィジェットについてのお話です。

例えばサンプルプログラム。

```dart
/// 全体的にコメントも省略
// 省略
body: Center(
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
      Text(
        'You have pushed the button this many times:',
      ),
      Text(
        '$_counter',
        style: Theme.of(context).textTheme.display1,
      ),
    ],
  ),
),
// 省略
```

こんな感じに実装されていて、 `Text` ウィジェットは二箇所で利用されています。
![sample_app.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135956/24021c57-22b0-2034-749a-452c7a644cdd.png)
サンプルアプリを起動したときの表示はこうです。



## Text に手を加えてみる

いざアプリ開発に取り掛かると、サンプルアプリのようにシンプルではなく様々な装飾を行います。

今回は二箇所の `Text` をドラッグできるようにしてみましょう。

```dart
/// 全体的にコメントも省略
// 省略
body: Center(
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
      Draggable(
        child: Text(
          'You have pushed the button this many times:',
        ),
        feedback: Text(
          'You have pushed the button this many times:',
        ),
      ),
      Draggable(
        child: Text(
          '$_counter',
          style: Theme.of(context).textTheme.display1,
        ),
        feedback: Text(
          '$_counter',
          style: Theme.of(context).textTheme.display1,
        ),
      ),
    ],
  ),
),
// 省略
```

[Draggable](https://api.flutter.dev/flutter/widgets/Draggable-class.html) を使ってそれぞれをドラッグ可能な `Text` にしてみました。

じゃあ動作を確認してみます。
![draggable1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135956/c1bfd425-69e0-2952-d962-0962f9e90bb1.gif)
いいですね！

もう一方のほうの `Text` も確認してみます。
![draggable2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135956/02ca9a72-82af-feaf-2ffb-5d19e3baa1a2.gif)
**ふぁあああああああ！？**

なんだこのビビッドにもほどがあるテーマは……。



## 何が起こったのか？

<font color="Red">実はこの派手なテーマは、 `DefaultTextStyle` クラスのデフォルト値のようです。</font>

シンプルに `Text` を利用している際はきれいに表示されていても、ダイアログなどを始め、他のウィジェットでラップした場合などにこのテーマで表示されてしまうことが **稀によくあります** 。



## 解決方法

### テーマをちゃんと設定してやる

カウンター（ 0 と表示されている `Text` ）側のテーマが崩れていないのを見てもわかるように、自ら `Text` にテーマを指定してやることでこの現象を防ぐことが可能です。

その場合、フォントサイズやカラーの他に `decoration: TextDecoration.none` を指定して <font color="#ffd900">黄色の二重下線</font> を消すのを忘れないようにしましょう。



### アプリケーションのテーマでラップしてやる

これは知らなかったのですが、 `MaterialApp` の場合、 `Material` ウィジェットで `Text` をラップしてやると、このテーマが変わってしまう現象を防ぐことができるようです。

```dart
Material(
  child: Text(
    'You have pushed the button this many times:',
  ),
),
```

こんな感じでラップしてやれば OK です！
![draggable3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135956/bff10814-caaa-3948-867c-e7a75892d4a4.gif)
**バッチリですね！**



## まとめ

`Text` がいきなり <font color="Red">赤字</font> に <font color="#ffd900">黄色のアンダーライン</font> で表示されると焦りますよね :sweat_smile:
（ぼくは焦りましたｗ）

`Text` にテーマを指定する方法は知っていたのですが、もともと指定していなかったところに追加するのは違和感を感じていましたので、 `Material` でラップする方法を知れてよかったです。

日本語の情報も少なめだったので、困っている人の手助けになれば幸いです :yum:



## 参考にしたサイト

:link:[Yellow lines under Text Widgets in Flutter? | stackoverflow](https://stackoverflow.com/questions/47114639/yellow-lines-under-text-widgets-in-flutter)
Github Desktopの使い方

# 背景
自分の備忘録として記載してます。

# 手順

1.左上の「Current Repository」→「Add」→「Add Existing Repository」でアプリを選択。
　「Add Repository」をクリック。
※クリック出来ない場合は、ターミナルで、git initする。
 
2.全ファイルを選択しコミットする。

3.「Publish Branch」でプッシュする。
　※モーダルが表示されるため入力し、リモートリポジトリを作成する。
 
4.「Current Branch」→「New Branch」→トピックブランチ作成。
　※ブランチが切り替えされているか確認
 
5.ターミナルで、git commit --allow-empty -m 'create pull request'　で空のコミットをする。
　※ブランチ作成後はコミットをしていないため。

6.「Publish Branch」でプッシュする。

7.「Create Pull Request」をクリックする。

8.ブラウザが起動してプルリクエスト作成画面になるので入力する。

9.[WIP]を外してURL確認後、レビュー依頼。

10.修正等完了し、LGTMを貰ったら「Marge Pull Request」をクリックしてマージする。

11.マージ完了後、「Delete branch」でブランチを削除する。

12.ブランチを切り替えし、「Fetch origin」→「Pull origin」でプルする。
【Elasticsearch】ScrollAPIを使ってみた

#Elasticsearchに格納されているデータ取得
10000件以上データが格納されているタイプに対して全件取得をしたかったが、
単純なsearchによるデータ取得ではできなかったので、別の方法を試してみた。

###TL;DR
「Search API」によるデータ取得件数にはいくつか制限がある為、
「Scroll API」を利用して全件取得する方法をメモとして残しておく。

###バージョン
Elasticsearch 5.4

##「Search API」の制限
Search APIによるデータ検索には検索数における制限がある

###「Search API」の検索

- 無条件検索する

```
curl -sS -XGET 'loclahost:9200/[インデックス名]/[タイプ名]/_search?pretty'
```

**制限①：デフォルトの10件までしか取得できない**


- クエリを利用して、fromとsizeを指定すうことで10件以上のデータを取得する

```
curl -sS -XGET 'localhost:9200/[インデックス名]/[タイプ名]/_search?pretty' -d
'{
  "query": {
    "match_all": {}
  },
  "from": 0,
  "size": 999
}'
```
**制限②：from + sizeが10000件を超えるとエラーとなってしまう**

```
Result window is too large, from + size must be less than or equal to: [10000] but was [12000]. See the scroll api for a more efficient way to r
equest large data sets. This limit can be set by changing the [index.max_result_window] index level setting.
```
[index.max_result_window]に設定されている値以上は取得できないよう。
（デフォルトで10000が設定されている）
エラー内容に書かれているようにscroll apiを調べて利用してみる。

##「Scroll API」による検索

Scroll APIを利用すると、実行時点でのスナップショットを保存し、取得しきれなかった分を辿っていくことができる。
レスポンスとして検索結果と「scroll_id」が返却される。
返却された「scroll_id」を元に、リクエストを繰り返し投げることで全データを取得することが可能。

###初回リクエスト
必要な設定値

- スナップショットの保存期限
- size
- query

スナップショットの保存期限を「1m」（1分）とし、match_allで9000件取得するクエリを投げる。

```
curl -sS -XGET 'localhost:9200/[インデックス名]/[タイプ名]/_search?pretty&scroll=1m' -d 
'{
  "size": 9000,
  "query": {
    "match_all": {}
  }
}'
```

※sizeには10000件（[index.max_result_window]に設定されている値）以上は設定できない

レスポンス例

```
{
  "_scroll_id": "XXXXXXXXX・・・XXX",
  "took": 274,
  "timed_out": false,
  "terminated_early": true,
  "_shards": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "hits": {
    "total": 23514,
    "max_score": 1,
    "hits": [
      {
        "_index": "index_name",
        "_type": "type_name",
        "_id": "〇〇〇",
        "_score": 1,
        "_source": {
          "name": "mug",
          "group": "sample"
        }
      },
      {
        "_index": "index_name",
        "_type": "type_name",
        "_id": "△△△",
        "_score": 1,
        "_source": {
          "name": "cup",
          "group": "sample"
        }
      }
...........
...........
......
    ]
  }
}
```

###2回目以降のリクエスト

初回リクエストで返ってきた「scroll_id」を元に作成
スナップショットを元にリクエストを投げるため、初回に設定したクエリやサイズを元に実行される。
エントリポイントは /_search/scroll

```
curl -sS -XGET 'localhost:9200/_search/scroll?pretty' -d 
'{
  "scroll": "1m",
  "scroll_id": "XXXXXXXXX・・・XXX"
}'
```

scroll_idは初回以降変わらないため、データ件数を超えるまで投げ続けることでデータを全件取得できる
データ件数を超えた場合は検索結果がレスポンスに返ってこないため、
プログラムとしてそこを判定してループ処理を実施することも可能。

###スナップショットの廃棄

設定したスナップショットの保存期限を超えると自動で削除される仕様だが、
明示的に作成したスナップショットを削除することが推奨されている。

```
curl -XDELETE 'localhost:9200/_search/scroll?pretty' -d
'{
  "scroll_id": "XXXXXXXXX・・・XXX"
}'
```

##まとめ
確実に全件取得できることは理解したが、
プログラムで実行する場合、データ件数を超えたかどうかの判定の箇所はもう少し考える必要がある。
コロナ情報でグラフ作成してみた　　

##Pythonでグラフ作成
※python初心者



ここから最新のコロナ情報が取れます。
[https://github.com/CSSEGISandData/COVID-19/blob/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv]




jupiter notebook を使って　グラフを作成してみます。

⑴　pandas 🐼　
⑵　欠損値の有無
⑶　色々な項目
⑷　日付をきれいにする
⑸　グラフ作成

　


※わからなかったこと※
・行と列を逆にしたかったのでエクセルでやった
・X軸を日付にするのがわからないのでエクセルで数値にした
頑張ってやってみました！





⑴

```
import pandas as pd
df= pd.read_csv("corona.csv",encoding="UTF-8")
df.head()
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625097/68cb23a3-b8b3-2a4c-ae7d-851fc9655f40.png)





⑵

```
df.isnull().sum()
df.head()
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625097/794c0203-45b9-699a-4b97-8631c26a0b7d.png)





⑶

```
df.describe()
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625097/8b4897d8-a9f2-030b-401f-02330c55fe03.png)






⑷

```
flg_is_serial=df["day1"].astype("str").str.isdigit()
flg_is_serial.sum()
fromSerial=pd.to_timedelta(df.loc[flg_is_serial,"day1"].astype("float"),unit="D") + pd.to_datetime("1900/01/01")
fromSerial
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625097/800770a8-f53b-5988-c9c7-b2f881355ed7.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625097/7475bcc9-8abf-85e4-587a-2042b5806fb5.png)




```
df["day1"]=pd.concat([fromSerial])
df
```



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625097/c576ffcf-85d6-2707-5fe3-9ba8e0814903.png)







⑸

```
import matplotlib.pyplot as plt
%matplotlib inline

data_col = df.columns


plt.figure(1)
plt.plot(df[data_col[1]],df[data_col[2]],marker="o")


plt.xlabel(df[data_col[1]].name)
plt.ylabel(df[data_col[2]].name)
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625097/defdce78-3f62-f4ff-7fb3-18530d56e3ff.png)
[Rails]  params, require, permit  (ActiveModel::ForbiddenAttributesError の対処)

##params, require, permit
悪意のあるデータが送られてくる場合があるのでデータの検証を行うことができる

例: post(title, body)を受け取ると想定
require, permitを使わず下記のように書くとセキュリティ上好ましくない

```ruby
def create
  @post = Post.new(params[:post])
end
```

そのためRailsから危ないと怒られる
(ActiveModel::ForbiddenAttributesError のエラーが表示される)
安全にするためにrequire, permitを使おう

###Strong Parameterを使おう
送られてくるのはtitle, bodyと明示

```ruby
def create
  @post = Post.new(params.require(:post).permit(:title, :body))
end
```

ただこの書き方はあまり推奨されていないので下記のように書きましょう

```ruby
def create
  @post = Post.new(post_params)
end

private
  def post_params
    params.require(:post).permit(:title, :body)
  end
```
WP-CLIで 「wp post list --post_author」がで出せない時の対処法

日本語で情報なかったのでメモとして書いておきます

# 投稿者を指定して記事を取得する
##NG
```shell
wp post list --post_author=1
```
##OK
WP_Queryにならって下記がOK

```shell
wp post list --author=1
```

##使用例
```shell
# 状態=公開、投稿タイプ=投稿、ライターID=10,11
wp post list --fields=ID,post_title,post_status,post_author --post_status=publish  --post_type=post --author=1,2,3
```
QNAPをAnsibleのターゲットにする

うちのサーバ QNAP TS-231P の設定を ansible で管理したいなぁと思っていたんだけど、なかなか一筋縄ではいかなかった。

ようやくやれるようになったので、メモしておく。

# 準備
QNAPコントロールパネルなんて使いたくないからansibleをやりたいのだが、残念ながら最低限次のことだけはコントロールパネルでやらなくてはならない。

コントロールパネルが出るまでの設定、ハードディスクやボリュームの設定は適宜やるとして、QNAPコントロールパネルが開けるようになってから以下のことをする。

## ネットワークとサービス / SSH接続
SSH接続を許可。SFTPも有効にする。ポートは一応22じゃなくて別のに変えておく。

## Python3
AppCenter で Python3 をインストール。

Python3 は `/share/CACHEDEV1_DATA/.qpkg/Python3` に入る。(本当は `/sbin/getcfg Python3 Install_Path -f /etc/config/qpkg.conf` でとってくるんだろうけど)
この中の `src/bin` にある。

しかしなぜかパーミッションが0666なので、sshで入って `chmod +x /share/CACHEDEV1_DATA/.qpkg/Python3/src/bin/*` で実行できるようにしておく。

# ansible の準備
以下の設定を加える。hostsでもhost_varsでもgroup_varsでもどこでもいいのだが、「QNAP関連の設定」ということでgroup_varsに書く。ポート番号とかIPアドレスとかはhostsの方に書く。

```group_vars/server.yml
ansible_python_interpreter: /share/CACHEDEV1_DATA/.qpkg/Python3/src/bin/python3
ansible_ssh_user: admin
```

これで一応 ansible が通るようになった。

---
注) いろいろ試した後の振り返りメモなので、もしかしたらこれだけではうまくいかないかもしれない。
pip install error"Can't connect to HTTPS URL because the SSL module is not available.

#environment
- Macos Catalina 10.15.1
- python 3.6.8
- pip 20.0.2

#error
~~~
$ pip install jupyter
WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.",)': /simple/jupyter/
WARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.",)': /simple/jupyter/
WARNING: Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.",)': /simple/jupyter/
WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.",)': /simple/jupyter/
WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError("Can't connect to HTTPS URL because the SSL module is not available.",)': /simple/jupyter/
Could not fetch URL https://pypi.org/simple/jupyter/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/jupyter/ (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available.",)) - skipping
ERROR: Could not find a version that satisfies the requirement jupyter (from versions: none)
ERROR: No matching distribution found for jupyter
WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/pip/ (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available.",)) - skipping
~~~

#check the openssl
[please follow this blog](https://qiita.com/halo57/items/e7511f3befbcb9fedd6a)

#If openssl is ok , maybe the python is broken.You can make a backup of this python and reinstall it.
~~~linux
$ pip freeze > requirements.txt
$ pyenv uninstall 3.6.8
$ pyenv install 3.6.8
$ pyenv virtualenv 3.6.8 env_3.6.8
$ pyenv local env_3.6.8
(env_3.6.8) xxxxxx:~ user$ $ pip install -r requirements.txt
~~~
[you can see this site about python virtual environment](https://qiita.com/drafts/4b4c6f431338ce697d11/edit)
stdin is not a ttyとなった時の対応方法


- 環境
    - Windows 10 Pro 64bit バージョン1909
    - GitBash(mintty 3.1.0)

# 事象 : GitBashで`winpty`と`mysql`コマンドをリダイレクトして使ったら怒られた

```bash
$ winpty mysql -u ponsuke -p -D sampledb -P 3306 < input.ddl
stdin is not a tty
```

# 原因 : (多分)対話モードにできないから
TTYというのは対話で入力したりできるようにしてくれるものらしい・・・
[TTY（テレタイプ端末）とは - IT用語辞典 e-Words](http://e-words.jp/w/TTY.html)

で、いくつかのコマンドでは`winpty`をくっつけないと対話モードにできない・・・からMySQLにログインするときに使っていた。
[Git for WindowsでPythonがうまく動かない場合の対処法 - Qiita](https://qiita.com/icoxfog417/items/33e6b1f3dd9358923e21)

が、「ログインするのにパスワード入力を対話でする」「リダイレクトでファイルの内容を実行する」が一気にきて「意味ぷーーー」になったのかもしれない(多分そんなことじゃないけど)。
[MySQL Git Bash winpty mysqldump stdout is not a tty and stdin is not a tty - Stack Overflow](https://stackoverflow.com/questions/40680812/mysql-git-bash-winpty-mysqldump-stdout-is-not-a-tty-and-stdin-is-not-a-tty)

どなたか、正しい原因を教えてください。

## 対応 : ログインしてからファイルの内容を実行する

```bash
# 1. ログインする
$ winpty mysql -u ponsuke -p -D sampledb -P 3306
Enter password: *******
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 16
Server version: 8.0.19 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

# 2. ファイルの内容を実行する
mysql> source input.ddl
Query OK, 0 rows affected (0.00 sec)
...省略...
```

## やってないけどほかの対応方法
- GitBashを使わないでコマンドプロンプトとかを使う
- bash自体をwinptyする : [Git Bashのttyで怒られないように - Qiita](https://qiita.com/amanoese/items/7b237e8703c3b4c7f001)