OmniAICreator/Qiita-1.07M huggingface dataset:
データベース 基礎理論学習メモ

#参照制約とは
参照制約とは、外部キーの値は被参照表の主キー（候補キー）のどれかの値かNULLでなければならないと言うもの。
参照制約の内部的な機能は、主キーの値と外部キーの値が一致しているかどうかを調べる**制約検査**と被参照表の主キーを削除または更新したとき参照制約を維持する方向に働く**参照動作**の２つに大別できる。参照動作においては、次の５種類が定義されている。

|参照動作|説明|
|:------------------:|:------------------:|:------------------:|
|RESTRICT|参照している外部キーがあれば、参照されている主キーを削除または更新はできない|
|NO ACTION|参照されている主キーを削除または更新しても、外部キーには何もしない|
|CASCADE|参照されている主キーを削除または更新した場合、外部キーを削除、更新する|
|SET NULL|参照されている主キーを削除または更新した場合、外部キーの値をNULLに設定する|
|SET DEFAULT|参照されている主キーを削除または更新した場合、外部キーの値を設定してある既定値にする|

#CONSTRAINT制約とは
CONSTRAINT制約は、制約に名前をつける際に使用する制約形式の事。

```sql:hoge
CREATE TABLE
 学生番号 CHAR(10) NOT NULL
 学生名 CHAR(10) NOT NULL
 年齢 INT NOT NULL
CONSTRAINT 主キー PRIMARY KEY
 (学生番号)
```

この際のCONSTRAINT制約は、学生番号に対して主キー制約のかかった”主キー”と言う名前の主キー制約を設定したことになる。
Docker コンテナ　一覧　起動


##コンテナ一覧表示
```bash

docker ps -a
```

```bash
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS                    PORTS                               NAMES
38397b499e30        wordpress:latest        "docker-entrypoint.s…"   9 days ago          Up 9 days                 0.0.0.0:3001->80/tcp                wptest_wordpress_1
bb452a2d6b6b        mysql:5.7               "docker-entrypoint.s…"   9 days ago          Up 9 days                 3306/tcp, 33060/tcp                 wptest_mysql_1
```

##コンテナ起動
```bash
docker start <<コンテナID>>
```
or

```bash
docker start <<コンテナNAME>>
```
picoCTF 2018 blaise's cipher - Points: 200

#問題

https://2018game.picoctf.com/problems

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/bcad23de-4f54-60c4-b64e-96f7bc353fb9.png)

#解いてみた

Blaiseさんって誰でしょう？
調べてみるとブレーズ・ド・ヴィジュネル（Blaise de Vigenere）とのこと。
ビジュネル暗号の問題っぽいですね。

それでは接続してみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/1c56d0e1-0a48-f941-1161-eb3e053e4858.png)

暗号化された文字列が出てきました。
キーが何かわかりませんが、pohzCZK{g1gt3w3_n1pn3wd_ax3s7_maj_095glcih}ってフラグっぽいですよね。

とりあえずこれをフラグと仮定します。

pohzCZK{g1gt3w3_n1pn3wd_ax3s7_maj_095glcih}
picoCTF{x1xx3x3_x1xx3xx_xx3x7_xxx_095xxxxx}

このxをうまく変換すればよさそうです。
最初のpicoCTFの部分の差分を見てみると

|暗号文|平文|差分|
|:-----|:-----|:-----|
|p|p|0文字|
|o|i|20文字|
|h|c|21文字|
|z|o|15文字|
|C|C|0文字|
|Z|T|20文字|
|K|F|21文字|

ということになります。
変換の法則が0文字20文字21文字15文字0文字・・・と繰り返されると仮定すると復号できそうです。
数字と記号はそのままにしておきます。もしかしたら数字は変換するのかもしれませんが一旦そのままにしておきます。ダメなら数字も変換する。

※本来は平文から暗号文への変換なので文字数は逆になりますが、今回は暗号文から平文に直すのであえてこうしてます。

ということで変換するとこうなります。
※マスクがてら、あえて書いてません。

|暗号文|差分|⇒|平文| 
|:-----|:-----|:-----|:-----|
|p|0文字|⇒|p|
|o|20文字|⇒|i|
|h|21文字|⇒|c|
|z|15文字|⇒|o|
|C|0文字|⇒|C|
|Z|20文字|⇒|T|
|K|21文字|⇒|F|
|{|||{|
|g|15文字|⇒||
|1|||1|
|g|0文字|⇒||
|t|20文字|⇒||
|3|||3|
|w|21文字|⇒||
|3|||3|
|_|||_|
|n|15文字|⇒||
|1|||1|
|p|0文字|⇒||
|n|20文字|⇒||
|3|||3|
|w|21文字|⇒||
|d|15文字|⇒||
|_|||_|
|a|0文字|⇒||
|x|20文字|⇒||
|3|||3|
|s|21文字|⇒||
|7|||7|
|_|||_|
|m|15文字|⇒||
|a|0文字|⇒||
|j|20文字|⇒||
|_|||_|
|0|||0|
|9|||9|
|5|||5|
|g|21文字|⇒||
|l|15文字|⇒||
|c|0文字|⇒||
|i|20文字|⇒||
|h|21文字|⇒||
|}|||}|
CentOSでにっちもさっちも依存関係をみたせない時にチェックすべきこと

依存関係がにっちもさっちもいかない。
あげくのはてにパッケージがだぶる。
CentOSだいっきらい。だから使いたくない。
でも、仕事だから仕方ない。
 --enablerepo=なんとか
を忘れてないかチェック。
remiレポジトリがうまく読み込まれてなかったのがまずかった。くそ。
numpy.vectorizeで文字列同士の計算をしたベクトルを得る

自然言語処理をやっていると類似度などの文字列同士の計算をしたベクトルを得たいときがあります。例えば文字列のリスト`['aiueo', 'aaa', 'iii']`から`'aiueo'`に似ているものを選びたいとき。
そんなときは、類似度計算関数を`numpy.vectorize`すると以下のように類似度のベクトルを得られます (ここでは類似度関数として`python-levenshtein`パッケージの`jaro_winkler`関数を使っています)

```python

>>> import numpy
>>> from Levenshtein import jaro_winkler
>>> vectorized_jaro_winkler = numpy.vectorize(jaro_winkler)
>>> print(vectorized_jaro_winkler('aiueo', ['aiueo', 'aaa', 'iii']))
[1.         0.56       0.51111111]
```

そして最もスコアが高いものを選ぶときは`numpy.argmax`を使います。

```python

>>> result = vectorized_jaro_winkler('aiueo', ['aiueo', 'aaa', 'iii'])
>>> print(numpy.argmax(result))
0
```

スコアが高い順にソートするときは`numpy.argsort`にマイナスをかけたパラメータを与えます。

```python

>>> print(numpy.argsort(-result))
[0 1 2]
```

ちなみにPythonの`str`型にあるような関数で一括で処理するときは`numpy.chararray`を使うと便利です。

```python

>>> a = numpy.array(['aiueo', 'aaa', 'iii'])
>>> print(numpy.chararray.startswith(a, 'a'))
[ True  True False]
```
Mysqlのエラー追跡:備忘録

CentosでMysqlでエラーが出たが、mysqld.logには残らなかった。
－＞mysqld_safeで流れを確認する。

```
[root@3691215 log]# service mysqld start
MySQL Daemon failed to start.
Starting mysqld:                                           [FAILED]
You have mail in /var/spool/mail/root
```

```
mysqld_safe

190225 21:56:12 mysqld_safe Logging to '/var/lib/mysql/3691215.com.err'.
190225 21:56:12 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
190225 21:56:14 mysqld_safe mysqld from pid file /var/lib/mysql/3691215.com.pid ended
```

エラーログはこんな感じで見れる
```
cat /var/lib/mysql/3691215.com.err
```

エラーを直したあとに起動してOKだったらよい。

#参考
https://tech.librastudio.co.jp/index.php/2017/07/12/post-1595/
https://serverfault.com/questions/354828/mysql-server-wont-start-no-logs
Firebaseの設定をしてみた

今回、Firebaseを使おうと思ったので、使い方をまとめてみました。
スマホアプリ開発用で使おうと思っているのですが、とりあえずは設定まで記載して、スマホアプリ作成で使えるようにするのは後に別で記載したいと思います。

### Firebaseとは
アプリケーションのバックエンドとして必要となる機能をサービスを提供する**BaaS(Backend as service)**の一種です

ほんの一例ですが、下記のような機能が使えるようになっています
(個人的には下記の機能が簡単に実現できるフレームワーク的なものかと思っています。)

・リアルタイムデータベース(Realtime Database)
・認証(Authentication)
・通知(Notifications)
・アプリのアクセス解析(Analytics)

### Firebaseの設定
[公式サイト](https://firebase.google.com)で設定を行います

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/239560/0c455a15-c697-44af-57ff-4b467b9296cf.png)
コンソールへ移動をクリックして、自分のGoogleアカウントでログインしましょう。
無料プラン(Sparkプラン)になるはずなので、有料プランにしたい場合は、プランを切り替えてください
料金体系は以下になるので、下記をご覧ください
[料金体系](https://firebase.google.com/pricing/?hl=ja)


マイページに移動したら、新しいプロジェクトを作成しましょう
プロジェクトを追加をクリックしてください
![スクリーンショット 2019-02-21 11.33.07.png](https://qiita-image-store.s3.amazonaws.com/0/239560/f55b53fc-6bc1-5379-2d39-05457d9b278f.png)

プロジェクト名とアナリティクスの地域を入力・選択します。
それ以外のチェックボックスは必要に応じて選択してください

![スクリーンショット 2019-02-21 11.33.45.png](https://qiita-image-store.s3.amazonaws.com/0/239560/284c0cee-c6ec-d55e-0b8e-0a5cc1e74636.png)
![スクリーンショット 2019-02-21 11.33.56.png](https://qiita-image-store.s3.amazonaws.com/0/239560/073103e6-9c87-434a-6285-da8e346d885d.png)

入力が完了したら、プロジェクトを作成ボタンを押下してください


Firebaseの開始画面に遷移します
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/239560/7094a22e-70af-7f2d-3d79-acdb04764632.png)


ここからiOSアプリにfirebaseを追加するのですが、長くなりそうなので、別で記載したいと思います。

###参照###
公式サイト - https://firebase.google.com
VulsRepoでunscored CVEsを含むVulsレポートを読み込もうとすると止まるので応急処置してみた事

概要
-

VulsRepoで特定のVulsレポートを読み込ませた時に止まってしまったのを取り敢えず表示できるところまでもっていったメモです。

環境は以下になります。
Vuls v0.6.3
2019年2月23日時点のVulsRepo
表示ブラウザはFirefox 65.0.1、Chrome 72.0.3626.109

状況
-

VulsRepoでレポート情報を読み込ませていると、表示できるサーバと読み込ませた時にロード表示で止まってしまうサーバがある。
ブラウザの開発ツールのコンソールには vulsrepo.js について以下メッセージが表示される。

```plaintext:Chromeの場合
Uncaught TypeError: Cannot read property 'nvd' of undefined
```

``` plaintext:Firefoxの場合
TypeError: y_val.cveContents is undefined
```

コンソールで出ていたメッセージの該当行を見ると以下の部分。

```javascript:vulsrepo.js
                    if (y_val.cveContents.nvd !== undefined) {
                        result["CweID"] = y_val.cveContents.nvd.cweIDs;
                    } else {
                        result["CweID"] = "None";
                    }
```

上記の内容から cveContents の参照に何かあるのだろうなと。

確認
-

読み込み失敗してしまうサーバレポートのjsonデータの読み込みを確認。

```javascript
console.info(y_val.cveContents.nvd);
```

上記を差し込んで見てみると、レポートの診断情報を数個読み込んだ後に途中で失敗してしまっている事が分かった。
読み込み失敗している診断情報の該当部分を確認してみると以下のような内容で「cveContents」が存在しない。（読み込み成功していたものは「cveContents」を含んでいた）

```javascript
    "CVE-2018-12384": {
      "cveID": "CVE-2018-12384",
      "confidences": [
        {
          "score": 100,
          "detectionMethod": "OvalMatch"
        }
      ],
      "affectedPackages": [
        {
          "name": "nss",
          "notFixedYet": false,
          "fixState": ""
        }
      ],
      "alertDict": {
        "ja": null,
        "en": null
      }
    },
```

vuls reportコマンドのオプションでは除外ケースがある「-ignore-unscored-cves」（Don't report the unscored CVEs）のように、CVE情報（cveContents）が含まれないケースがあって、それがエラーに影響していそうという事が分かった。

応急処置
-

「y_val.cveContents」の部分が未定義の場合空にしておけば影響出さずにパス出来そうだなとvulsrepo.jsをざっくり確認して、以下のように修正。

```javascript:vulsrepo.js(修正後)
                    if (y_val.cveContents === undefined) {
                        y_val.cveContents = "";
                    }

                    if (y_val.cveContents.nvd !== undefined) {
                        result["CweID"] = y_val.cveContents.nvd.cweIDs;
                    } else {
                        result["CweID"] = "None";
                    }
```

以上で、読み込みが止まってしまっていたサーバ情報もVulsRepoで表示できるようになった。
＊取り敢えず表示が見たいために行った応急処置なので実際利用する場合はコード確認してください
Djangoのよく使うコマンドのメモ（Mac）

<h2>MacのターミナルでDjangoを操作する時のコマンド</h2>
<p>ローカルホストでプロジェクトを起動する</p><code>python manage.py runserver</code>
<br>
<p>Models.pyを編集した時</p><code>python manage.py makemigrations</code>
<br>
<p>データーベースに適用</p><code>python manage.py migrate</code>
<br>
<p>ユーザーを登録する</p><code>python manage.py createsuperuser</code>
今さら聞けない！シングルページアプリケーションとは

## はじめに
プロジェクトメンバーにAngularを使ったアプリケーション構築について教育する必要があり、自分の持っている知識を言語化しておきたいと思ったので、技術解説記事を書いてみます。
単純にアウトプットは大事ですし、こうやって書いた記事が誰かの理解に役に立つようなことがあれば尚良しなのでやり得ですね。
今回は第1弾として「シングルページアプリケーション」について概要を解説してみます

## シングルページアプリケーションとは
Single Page Application(SPA)とはその名が示す通り、「1つのWebアプリケーションを1つのWebページで構築する」アプリケーションのことを指します。これではよくわからないと思いますので、従来のアプリケーションと何が違うのか？というところにスポットを当てて、説明しようと思います。
### 従来のアプリケーション
![prev_app.png](https://qiita-image-store.s3.amazonaws.com/0/240148/f206af6e-dea8-0511-48a2-45e6a7db00da.png)

従来のアプリケーションは画面遷移をする際、ブラウザがWebサーバーにリクエストを発行し、そのレスポンスとしてサーバーはHTMLを返却していました。このHTMLをブラウザが読み込み、画面全体を再描画することで画面遷移を実現していたわけです。違う画面に遷移するたびに違うHTMLを読み込むことになるので、1つの画面=1つのHTMLでした。

### シングルページアプリケーション
![SPA.png](https://qiita-image-store.s3.amazonaws.com/0/240148/77a34755-22c4-0891-8623-745b0488b31f.png)

一方でシングルページアプリケーションは初期表示時こそ、従来のアプリケーションと同様にサーバーからHTMLを取得しますが、以降の画面遷移は、データ(主にJSONが用いられる)をサーバーからレスポンスとして受け取り、そのデータを使ってJavaScriptでDOMを操作することで画面遷移・更新を行います。HTMLは初期表示で取得したもののみで以降の画面遷移はJavaScriptで行うため、1つのアプリケーション=1つのHTMLということになります。
これによって従来のアプリケーションと比較して、以下のようなメリットを享受することができます。

1. 画面遷移を、画面全体を再描画するのではなく、DOM操作によって必要最低限の箇所を更新することによって実現するため全体的なパフォーマンスが向上する
2. サーバーがレスポンスとして返却するものがHTMLでなくデータになったことで、フロントエンドとサーバーサイドが疎結合になる。(HTMLで表現されるような画面をどう表示するのかといった情報をサーバーサイドが知っている必要がなくなる)
3. 2.によってPC、スマートフォン、タブレットなどのデバイスによる差異はフロントエンドの実装のみで吸収できるようになり、サーバーサイドはWebAPI的な1つの実装を行えばよくなる(マルチデバイス対応が容易になる)
4. ブラウザとサーバーのやり取りがHTMLからデータ(JSON)になるこ とで通信容量を削減できる
5. 画面遷移・更新時にアニメーションを付与することができるなど、豊かな表現が可能になる

## なぜシングルページアプリケーションが台頭したのか
シングルページアプリケーションが台頭した理由は大きく以下の2つにあると考えられます。
・スマートフォンの普及
・ブラウザの処理速度の向上(≒JavaScriptの実行速度の向上)

### スマートフォンの普及
かつてWebアプリケーションで少しリッチな表現、例えば動画再生などを行おうとした場合、HTMLやJavaScriptだけでは実現することができませんでした。では、どうやって実現していたかといいますと、Rich Internet Application(RIA)と呼ばれる、いわば外部プラグインを導入して実現していたのです。代表的なもので言えばAdobe Flash(主に動画再生用途)やMicrosoft Silverlight(音声再生用途)などが挙げられます。<br>この状況を一変させたのがスマートフォン(iPhone)の登場です。RIAは消費電力が大きい上にマシンへの負荷も高く、スマートフォンには不向きだったのです。そしてRIAの衰退にとどめを指したのがスティーブ・ジョブズが2010年4月に公開した「<a href="https://en.wikipedia.org/wiki/Thoughts_on_Flash">Thoughts on Flash</a>」という文章です。この中でジョブズはFlashがAdobeによるクローズドな仕組みであると指摘し、Flashを脱却し、HTML5/css/JavaScriptによるリッチアプリケーションの構築を行うことを発信しました。<br>その後、HTML5が正式勧告がされたこともあり、Flashなどに代わる技術としてHTML5が推進されてきました。<br>そして、HTML5でFlashと同様のUI/UXを実現するための手法としてシングルページアプリケーションが生まれたのです。

### ブラウザの処理速度の向上
もう一つの大きな要因がブラウザの処理速度の向上(≒JavaScriptの実行速度の向上)です。<br>シングルページアプリケーションはJavaScriptによるDOM操作で画面遷移を実現するため、従来のWebアプリケーションに比べて、フロントエンドの担う役割が大きくなり、ブラウザにはそれを実現するための十分なJavaScriptの処理能力が要求されます。<br>かつてのJavaScriptはWebページに簡単な動きを加える程度の言語で、実行速度も遅かったのですが、2008年にGoogle Chromeが登場したことにより、この認識は覆されることになります。<br>Google Chromeに搭載されていたV8エンジンというJavaScriptの実行エンジンは非常に高速にJavaScriptを実行することができ、この後ろ盾があったこともシングルページアプリケーション普及の大きな一因と言えるでしょう。
gdriveでgoogle driveを使う

###準備
#### インストール
```
% brew install gdrive
```

#### OAuthキーの取得
- とりあえずlist

```
% gdrive list
```


- 認証URLにアクセスし、トークンを取得

---
#### ファイルをアップロードする
```
% gdrive upload  [ファイル名]
```
#### ローカルと同期する
- まず専用のディレクトリを作る必要がある。

```
% mkdir [ディレクトリ名] 
Directory 1SG41BMuI6p4r4ggOKTc_2yK3vx9T0wS8 created
```
- sync コマンドを実行し、作成したディレクトリにファイルをアップロード

```
% gdrive sync upload [ファイル] 1SG41BMuI6p4r4ggOKTc_2yK3vx9T0wS8
```
ExpoのSpeechを使って文字列を読み上げる方法

##Speech.speak()を使って再生
読み上げたい文字列をExpoが用意してくれているSpeech.speak()に引数として渡してあげるだけで
文字列を読み上げてくれる。
以下のコードはボタンを押すと「おはようございます。今日もいい天気ですね。」と読み上げ音声が流れるだけの簡単なサンプル。

```jsx:App.js
import React from 'React';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { Speech } from 'expo';

export default Class App extends React.Component {
  startSpeech = () => {
    const text = 'おはようございます。今日もいい天気ですね。'
    Speech.speak(text, {language: 'ja', rate: 1.0, pitch: 1.0})
  }
  render() {
    return (
      <View style={styles.container}>
        <TouchableOpacity style={styles.button} onPress={() => this.startSpeech()}>
          <Text style={styles.buttonItem}>Start Speech</Text>
        </TouchableOpacity>
      </View>
    );
  }
}
const styles = StyleSheet.create({
  //styleは省略
})
```
##ポイント
* expoからSpeechをインポート　→　これでSpeechが使えるようになる。
* Speech.speak()に渡す引数は２つで、１つはtext、もう１つはoptions。

textはただの文字列。読み上げさせたい文字列を渡そう。

optionsには読み上げる際の言語や読み上げ速度（rate）、ピッチ（pitch）そして他にもコールバック関数（onStartなど）をオブジェクトの形で入れる。不要な場合は省略可。

読み上げる際の言語指定は言語コードを参照。（日本語なら'jp'、英語なら'en'、スペイン語なら'es'など…）
##ちょっとハマった注意点
日本語で読み上げる時に少し困った点。

iOSで動かす場合はSiriさんの声で読み上げてくれるため日本語でも問題なかったが、Android端末の場合は日本語に対応していない場合があるみたい。

英語は読み上げてくれたのに日本語にしたらウンともスンとも言わんやんけ！と思ったらOSの方の問題かも。
##他のメソッド
他にも読み上げを一時停止するSpeech.pause()や再開するSpeech.resume()などもあるけどここでは割愛。

詳しくは公式ドキュメントを読むのがいい。このメソッドに関して言えば特に難しいことはない。
EthereumのRopstenネットワークにて、Parityでnodeの同期が進まなくなった時の対処方法

# 症状
EthereumのnodeをParityで立ててRopstenネットワークに接続してしばらく運用していたところ、いつの間にか新しいブロックが同期されなくなってしまっていた。
Parityのバージョンを最新にして再同期してみてもダメ。
Parityのログを追っていると（ログの見方はこちらを参照 https://wiki.parity.io/FAQ#what-does-paritys-command-line-output-mean )

以下ログのように

```
2018-04-30 16:10:13 Syncing #5532478 9ce2…0499 69.28 blk/s 235.7 tx/s 15 Mgas/s 0+ 17 Qed #5032470 25/25 peers 5 MiB chain 128 MiB db 2 MiB queue 3 MiB sync RPC: 0 conn, 0 req/s, 0 µs
```
※ログは例なので加工してあります。。

「Syncing #5532478」に対して、ネットワークのhighest block numberが「#5032470」
自身のnodeの持っているブロックに対してネットワークの持ってるブロックのほうが小さい状態となっていて、自身のnodeの同期が一向に進まない。
データを消して0から同期しなおしても同じ症状。


接続するnodeの同期が進んでいない状態？正しい最新のブロックを持ったnodeに接続できてないのか？と、色々とググってオプション等を確認していくと、「--reserved-peers」オプションで、接続するnodeを指定してやると良さげとのこと。
※「--bootnodes」オプションもあったが、こちらで試しても僕の環境ではうまくいかなかった。

で、どのnodeに接続すればいいんだ？と調べてると、公式にこっそり
https://github.com/ethereum/ropsten
こんなリポジトリがあって、指定されているnodeを指定してやればいいらしい。

# 対応方法
「--reserved-only」オプションで「--reserved-peers」で指定したnode以外には接続しないようにする

```
# 保存されているnodeのデータを削除
parity db kill --chain ropsten

# 接続先nodeの情報をテキストファイルに保存
echo -e "enode://6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f@52.232.243.152:30303\nenode://94c15d1b9e2fe7ce56e458b9a3b672ef11894ddedd0c6f247e0f1d3487f52b66208fb4aeb8179fce6e3a749ea93ed147c37976d67af557508d199d9594c35f09@192.81.208.223:30303" >> ropstenpeers.txt

# 接続先nodeをreserved-peersで指定してparity起動
parity --chain ropsten --reserved-peers ropstenpeers.txt --reserved-only
```

同期を最初からやり直すことになり、2nodeとしか接続しないので同期には時間がかかってしまうが、正しく同期されるようになった。
以後、parityを再起動する際には「--reserved-peers」「--reserved-only」オプションがなくとも正しく同期され続けた。

# 原因
よくわからない、、
ropstenにつないでるpublic nodeが少なくて、たまたまつなぎに行ったnodeが正しく最新化されていなかっただけなのか？とも思ったが、何度再起動してもうまくいかなかったので原因は別なのか、、、
UE4でのメモリ使用量の調査と対策



# 概要
開発が大規模になると使用メモリが膨大になり、
アセットのロード時間やゲームの起動に影響を及ぼします。
この記事では簡単にできるメモリ使用量のチェック方法を記載致します。

# 調査方法について
メモリの使用量をチェックする方法です。
ここでは下記のコンソールコマンドを使った例を紹介します。

### コンソールコマンド
**memreport -full**
で現在使用しているメモリのダンプをとることができます。
Saved/Profiling/MemReports/以下に保存されます。
拡張子が**memreport**なのですが、中身は**テキストデータなのでそのまま見ることが可能です。**
見やすくするために専用のビューワーなど作成しておくと作業しやすいです。

例：SkeletalMesh のメモリ使用量を調べたいとき
memreportをテキストエディタ等で開いて、

```text:foo.memreport
Obj List: class=SkeletalMesh -alphasort
Objects:
:
:
```
と書かれている箇所を参照してみてください。
ここに列挙されているオブジェクトはメモリに乗っているメッシュの情報です。
不要なメッシュや、破棄できていないメッシュがあれば、**無駄なメモリを使用しているということになります。**

<font color="Crimson">**注意！**</font>
エディタでは使用メモリが開放されないので、
そのまま別のレベルでコマンドを使用すると、
前のレベルのメモリ情報も出力されてしまいます。
エディタの再起動もしくは、開放する手順を準備する必要があります。

# 対策するには
メモリ使用量を減らすには（不要なオブジェクトが見つかったときは）
メモリにのってしまっている**原因を特定する**のが第一歩です。
該当のアセットをエディタ上で探し、
[**リファレンスビューワー**](http://api.unrealengine.com/JPN/Engine/Content/Browser/ReferenceViewer/)を使用してみてください。
多くの原因としては、

- 該当のアセットが意図せずリファレンスされている
- 別の箇所でも使いまわされている
- 移動/削除したときのリダイレクタの修正漏れ
- テスト用で置きっぱなしだった

といったケースが多いです。
リファレンスを外して不要なロードを行わなくしましょう。
ビューワー上でアセットの左側のノードが繋がっているものは参照（ハードリファレンス）されているものです。
（参照されている理由はBPの変数にされていたりなど、様々です）

# おまけ
### よく使うデバッグコマンド
**stat XXX**
コンソールコマンドで入力できる、stat XXX系はとても便利です。
エディタ上の Viewport Options から有効化出来ます。

例えば stat Memory はスクリーン上に使用メモリを表示することができます。
また、stat levels では、レベルのロード状況やロード時間を調べることが出来ます。
ここでは詳細は割愛しますが、参考のリンクを記載致します。

# 参考
[デバッグとメモリーの最適化](https://www.unrealengine.com/ja/blog/debugging-and-optimizing-memory)

[[UE4] コンソールコマンドの使い方＆よく使うコマンド一覧](http://historia.co.jp/archives/1342/)
Microbit:DC motor制御

Motor Driver Board for BBC microbit Kitronik 5620
この拡張ボードを使って、DCモータの制御を行います。

このHPを参考にしました。
[micro:bitでモーターを動かしてみた](https://kanpapa.com/today/2017/08/microbit-motor-driver.html)
[micro:bitでタミヤのキャタピラー車を無線制御してみた](https://kanpapa.com/today/2017/08/microbit-motor-tamiya.html)

Microbitをこのボードにさすときは、向きに注意してください。（Microbitの0端子が、P0ピン。）
DCモーター制御のピントとデジタル出力との関係


| P8   | P12  | Motor1　Function |
| ---- | ---- | ---------------- |
| 0    | 0    | 惰性             |
| 1    | 0    | 前進             |
| 0    | 1    | 後進             |
| 1    | 1    | ブレーキ         |


| P0   | P16  | Motor2　Function |
| ---- | ---- | ---------------- |
| 0    | 0    | 惰性             |
| 1    | 0    | 前進             |
| 0    | 1    | 後進             |
| 1    | 1    | ブレーキ         |      



##動作確認テスト

以下のようなプログラムを作成
![microbit-Motor_test.png](https://qiita-image-store.s3.amazonaws.com/0/165987/4ff22b56-79ac-1303-47ef-0f8b22ad2bde.png)

Aボタンを押すとMotor1が前進方向に回転、Bボタンを押すとMotor1が前進方向に回転
ABを押すと1,2ともに後進方向へ回転。
このプログラムは停止するものがないため、電源を落として止めてください。（電池ボックスの電源を切る）

![P_20190223_192710.jpg](https://qiita-image-store.s3.amazonaws.com/0/165987/05923a9b-5995-3b21-2cde-7effcb07d54a.jpeg)
タミヤ　2チャンネル リモコン・インセクト （6足歩行タイプ）にDCモーター制御を搭載しました。



##無線でコントロール

6足歩行ロボットを無線で制御するために、受信用（DCドライバー側）と送信用プログラムを作成

###送信側プログラム
![motor_sender.png](https://qiita-image-store.s3.amazonaws.com/0/165987/4abbab78-acae-b707-2642-8c78614b6263.png)

ABボタンを基本使わず、Microbitの傾きでコントロールしています。

###受信側プログラム
![motor_resiver.png](https://qiita-image-store.s3.amazonaws.com/0/165987/1644bd29-de63-3360-c219-4026bc88646d.png)

右、左、前進などの動作の関数を作ります。送信側の送信番号に合わせて関数を配置します。
Microbitは上から実行しますので、動作の関数を上に配置して、そのあとに無線で受信した時のブロックを配置します。

実際の搭載例
![P_20190224_162853.jpg](https://qiita-image-store.s3.amazonaws.com/0/165987/c6a74bd5-24af-c8f1-e00d-b1255f51a175.jpeg)

![P_20190224_163027.jpg](https://qiita-image-store.s3.amazonaws.com/0/165987/25d2251d-d40e-cf21-a581-690538e9e9d7.jpeg)
自分がコントロールしやすいように、送信側の命令を変えてみると面白いかもしれません。
seleniumで動的なページのソースコードを取得する

ブラウザに表示しているソースコードを取得するのに手間取ったのでメモ。

```
import selenium
...
source = driver.page_source
...
```

こんな人が対象
・このコードだとURLに飛びなおすため？ブラウザで表示されているソースコードを取得することができない人。
・静的なサイトならこの命令でも十分だが、動的なサイトの場合、目的としたデータを取得できない人。
・たとえばツイッター、ニコニコ動画などスクロールすると勝手に遷移するページのスクレイピングで困ってる人。

#用意
python3
selenium
webdriver（導入は各自で）

#方法
- ステップ1

```.
C:\ > "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 --user-data-dir="C:\hoge "
```
・末尾のuser-dataは必要らしいです。これがないとブラウザ起動しませんでした。

- ステップ2

```
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
chrome_driver = r'C:～\chromedriver.exe'
driver = webdriver.Chrome(chrome_driver, chrome_options=chrome_options)
print(driver.title)
print(driver.page_source)
'''---------------------
ブラウザを操作するコードを記述
---------------------'''
driver.quit()
```


#まとめ
・表示中のソースコードを取得することができる。
・pythonからsubprocessモジュールを使い　「ブラウザ起動→ブラウザ操作」をコントロールしようとしたがうまくいかなかった。
・いちいちブラウザを起動してからpythonに入るしかない？

#参考
[teratail - python selenium　chromeで現在表示しているソースの取得](https://teratail.com/questions/159416)
(*2) [teachmeselenium - how to connect selenium...](http://www.teachmeselenium.com/2018/08/11/how-to-connect-selenium-to-an-existing-browser-that-was-opened-manually/)

#(*2)
起動中のブラウザにseleniumをつなげる方法

手動でひらかれたブラウザを操作したいことがある。
-ケースとしては…
・自動操作する前に、手動操作が必要なとき。たとえばcaptcha（操作者がロボットか判断する）を操作したあとに自動化する場合
・デバッグするとき。まだ目的のページまで行くスクリプトが完成していない時に、手動で目的のページに移動して、その後に自動化スクリプトを試す場合。

Chrome DevTools Protocolを使うことでいろいろチェックしたり、デバッグすることができる。

```
chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\selenum\AutomationProfile"
```
これでchromeを起動することによってポートを開放することができる。
また、ユーザーディレクトリを新たに作ることで、既存のユーザーデータを改変しないですむ。
PATHにchromeをいれるのも忘れずに。

以下いろいろ書かれていますが、「マニュアル起動→自動実行」を対象とした方法のようです。



勝手に遷移するページのスクレイピング方法を知ってるよっていう人がいらっしゃいましたら、ぜひご教授ください。
よろしくお願いします。
FlutterのTextFieldでIMEの変換確定前にclearするとクラッシュ

日本語入力で変換の確定前に `controller.clear()` を呼び出すとクラッシュしてしまいます。

回避策は直前に`clearComposing()`を実行すること。

```dart
controller.clearComposing();
controller.clear();
```

このようにすればクラッシュは回避できます。

↓このあたりのissueと関係してそうですが、この方法が正しいのかイマイチよくわかりません。。
https://github.com/flutter/engine/pull/6989
超初心者のHTMLとCSS

#プログラミング学習を開始しました
[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしているueken0403です。
プログラミングの学習を開始してまだ四時間ですが、記事を書いてみたいと思います。
注意事項
この記事の内容は正確ではない可能性が高いです。間違いを指摘してくれたら、すぐに修正すると同時にとても喜びます。がんがん指摘してください。
それでは、以下HTMLのコードの書き方です。

###見出しのつけ方
見出しをつけるには＜ｈ＞要素を使います。
＜ｈ＞要素は、重要度順に＜ｈ１＞＜ｈ２＞＜ｈ３＞…があります。
数字が大きくなるほど重要度は低くなると判断され、文字も小さくなります。

###本文の書き方
本文を書くには、＜p＞要素を使います。
単純に＜P＞と＜/ｐ＞の間に表示したい分を入れれば良いです。

##最後に
初めてのプログラミング記事の投稿はこれぐらいにしておきます。
手抜き感が半端ないですね。
これからもっとプログラミングを勉強していって、記事を見てれた人が有益にと感じるような情報を共有できるようになりたいと思います。
UnityからChromeブラウザの立ち上げと立ち下げ

## はじめに
UnityからChromeブラウザを立ち上げ、**立ち上げたサイトだけを立ち下げたかった**ので、
備忘録として残しておきました。
（既にブラウザで開いていたサイトは表示したままにしておきたかった）
結構無理やりなので、汎用性はあまりないかもしれません。
はじめは「System.Diagnostics.Process」だけで実現しようとしましたが、
Chromeは起動させると別のプロセスIDに切り替えて起動してしまうような挙動をしていたため断念しました。

## 実行画面
- わかりにくいですが、「W」キーを押してChromeを立ち下げています。
![Chromeオンオフ](https://taroyan3rd.com/images/Qiita/ChromeOnOff/ChromeOnOff.gif "Chromeオンオフ")


## 開発環境
- Windows **10**
- Unity Ver **2018.3.2f1** Personal
- Chrome バージョン: **72.0.3626.119** 　64bit

## ポイント
- Chromeをアプリモードで立ち上げる。（例としてGoogleサイトを表示）
- 表示させたいサイトのサイト名は英語にする。（なぜか日本語だとhWndハンドルが取れなかった）

## サンプルソースの説明(ChromeOnOff.cs)
- Unityのゲーム再生時にStart関数内でChromeがアプリモードで起動
- キーボードの「W」キーを押したとき、アプリモードで起動したChromeだけ立ち下がる。

```ChromeOnOff.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Diagnostics;
using System.Runtime.InteropServices;

public class ChromeOnOff : MonoBehaviour
{
    [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
    static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

    static uint WM_CLOSE = 0x10;

    /// <summary>
    ///起動する外部プロセス
    /// </summary>
    private Process exProcess;

    // Use this for initialization
    void Start()
    {

        if (exProcess == null)
        {

            exProcess = new Process();

            exProcess.StartInfo.FileName = @"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe";  // exe名
            exProcess.StartInfo.Arguments = "--app=https://www.google.com --incognito";                      // コマンド引数生成

            //外部のプロセスを実行
            exProcess.Start();
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))    // Wキーを押した?(Yes)
        {
            WindowsCloseProc();             // ウインドウを閉じるWin32API
        }
    }

    // Chromeを閉じる処理
    private void WindowsCloseProc()
    {
        IntPtr hWnd = FindWindowByCaption(IntPtr.Zero, "Google");    // サイト名を第二引数へ入力（日本語がダメっぽい）
        bool ret = CloseWindow(hWnd);
    }

    // WIN32APIにおけるSENDメッセージ
    static bool CloseWindow(IntPtr hWnd)
    {
        SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
        return true;
    }
}

```

## おわりに
- とりあえずWIN32APIを使うことで開いたページだけ落とすことができた。
- 日本語のサイト名の場合に対応できないのが残念。（どなたかわかるかた教えてください。。。）
「Vue + Vue Router + Vuex + Laravel」を学ぶのにすごく良い記事

# はじめに

なんとなく Vue.js はわかってはいるけど、イマイチ Vuex の使い方はしっくりきてない。
Laravel でチュートリアルはこなしたけど、実践はまだ。

そんな自分が [Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう (1) イントロダクション](https://www.hypertextcandy.com/vue-laravel-tutorial-introduction/) に出会えて、かなり成長できました。

「Vue + Vue Router + Vuex + Laravel」を学ぶのにすごく良い記事だと思ったので、どこが良いと思ったかを記載します。

- とても良い記事
    - [Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう (1) イントロダクション](https://www.hypertextcandy.com/vue-laravel-tutorial-introduction/)

- 記事にならって作ったプログラム
    - https://github.com/katsuhiko/laravel-vue-photos


# 良いところ

- 少しづつ機能を追加する作り方がわかりやすい。
    - 1つのファイルを完全にして、先に進むのではなく、少しづつ機能を追加して行く感じなので、都度動作確認しながら、リズムよく作れる。
- SPA なアプリを作れる。
    - やっぱり SPA を作りたい。
- ログインつきのアプリを作れる。
    - ログイン部分は Vue.js を使わないやり方しかしてこなかったので、作り方を学ぶことができた。
- AWS S3 も使っているアプリを作れる。
    - やっぱり、いろいろなサービスを使わないと。
- CSS を用意してくれていて、キレイなアプリを作れる。
    - CSS を最初から用意してくれているから、キレイなアプリを作れる。しかも、CSS が BEM(詳しくはないけど、たぶんBEMだと思う)に従っていて、CSSもキレイ。
- エラー処理もあるアプリを作れる。
    - やっぱりエラー処理があると、ソースの量が増えるけど、これがあると実践でも役立つはず。
- テストがあるアプリを作れる。
    - サーバーサイドのテストのみだけど、テスト作ることで早めの動作確認ができて助かる。
- 1〜2日ぐらいで作れる。
    - 記事をじっくり読んでからであれば、1日でできるボリュームなのが、根性のない自分には、とても助かる（AWSの理解があるかで、差がでるかも）。


# 学んでいるときに思ったこと

記事を読んでるだけではわからないつまづきがあって、そのときにログを見たり、ソースを見直したりするのが、とても良かった。

ローカル実行環境を独自の Docker/docker-compose にしました。ほんのちょっと自分なりのアレンジをしたことで、程よいつまづきを起こすことになってちょうどよかったです。


# 今後について

せっかく、こんなキレイなアプリができたので次になにするかも考えたくなります。

- このアプリのCSSを学ぶ。せっかくキレイなCSSだし。
- クリーンアーキテクチャを適用してみる。サーバーサイドが得意分野なので。
- e2eテストを書いてみる。やっぱりテストがほしい。
- モックを使ったテストを書いてみる。DBを使わないテストを書きたい。
- 画像の配信を AWS CloudFront 経由にする。より実践を意識するため。
- AWS ECS/Fargate/Aurora で公開する。もっと AWS を使いたい。
- 権限を追加して、ユーザー管理画面を作る。RBAC を適用して業務アプリにしちゃうとか。
最小構成の Airflow を GKE に deploy する

## はじめに

- [Airflow を単体の docker container で立ち上げる](https://qiita.com/kysnm/items/feda7b8cca44bb7389ac) で作成した container image を GKE に deploy します

## 参考とする実装

- [metabase-gke](https://github.com/kysnm/metabase-gke) で GKE への deploy 実績があるのでこれを参考にする

## Kubernetes の設定の examples

- https://github.com/kubernetes/examples
- 1.10 までは kubernetes 本体と同じレポジトリにあった https://github.com/kubernetes/kubernetes/tree/v1.10.13/examples

## Deployment、Service、Ingress

- この辺の構成を理解していないと設定ファイルの書き方に迷う

### Deployment

> DeploymentはReplicaSetを生成・管理し、ReplicaSetはPodを生成・管理します。

> ReplicaSet(ReplicationControllerの後継)はPodTemplateと呼ばれるPodのテンプレートをもとに、Podを指定された数(レプリカ数)に調整・管理を行う仕組みです。

- https://qiita.com/tkusumi/items/01cd18c59b742eebdc6a
- https://v1-10.docs.kubernetes.io/docs/concepts/workloads/controllers/deployment/
- https://cloud.google.com/kubernetes-engine/docs/concepts/deployment?hl=ja

### Service

> Pod,Nodeの存在を抽象化し、Podとの通信に単一のエンドポイントを提供するのがServiceの主な役割になります。

- https://qiita.com/kouares/items/94a073baed9dffe86ea0
- https://v1-10.docs.kubernetes.io/docs/concepts/services-networking/service/
- https://cloud.google.com/kubernetes-engine/docs/concepts/service?hl=ja

## Ingress

> ingressはHTTPSレイヤーのロードバランサーであり、

> - IP管理などを個別のserviceではなくingressで管理できる
> - Googleが推奨している

- https://qiita.com/Hirata-Masato/items/8e6b4536b6f1b23c5270
- https://v1-10.docs.kubernetes.io/docs/concepts/services-networking/ingress/
- https://cloud.google.com/kubernetes-engine/docs/concepts/ingress?hl=ja

## Ingress の導入

- ServiceType は未指定の場合 ClusterIP なので、これを NodePort に変更します。Ingress 側の ServiceName と ServicePort で Service の name と port を指定します

- https://v1-10.docs.kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types

- https://qiita.com/Hirata-Masato/items/8e6b4536b6f1b23c5270#%EF%BC%91-service-deployment%E3%81%AE%E8%A8%AD%E5%AE%9A

aiflow の場合 /admin/ がルートになるので readinessProbe で health check のパスを変更しておく

- https://qiita.com/Hirata-Masato/items/8e6b4536b6f1b23c5270#%E8%BF%BD%E8%A8%98201823

## 初回の証明書取得

- Let's Encrypt 側でエンドポイントを確認できるまでは証明書が取得できないので、一旦 http で証明書を取得してから https に移行する

## Reverse Proxy (Ingress) 内での Airflow の設定

- 環境変数 `AIRFLOW__WEBSERVER__ENABLE_PROXY_FIX` に `True` を設定する

## 実装

- https://github.com/kysnm/airflow-gke

## Ingress のトラブルシューティング

- この資料がとても役立った https://github.com/gcpug/nouhau/tree/master/kubernetes-engine/poem/ingress-nouhau
go getで入れられないライブラリをGo Moduleで扱いたい

# TL;DR
Go Moduleの`replace`機能とGit Submoduleを使う

# 経緯
cgoなどの依存があり、Makefileを実行する必要があったりしてgo getでインストールするとうまく動かないライブラリはGo Moduleでそのまま扱えないことがあります。

# 対策
私が躓いたライブラリは `github.com/zubairhamed/canopus` でした。このライブラリは内部でOpenSSLを利用しており./configとmakeを実行する必要がありました。`go get`で入れようとするとopensslのヘッダファイルがないと言われてインストールできません。
`go.mod`には当初

```
require (
    ...
    github.com/zubairhamed/canopus v0.0.0-201XXXXXXXXXXX-abcdefghijkl
)
```

このようになっていました。(ちゃんとバージョニングされて入ればv1.0.0のようになります)
これに

```
replace github.com/zubairhamed/canopus => ./canopus
```

replaceをこのように加えてディレクトリのパスを指定します。こうすると`github.com/zubairhamed/canopus`以下のライブラリを利用しようとすると`./canopus`のディレクトリを利用するようになります。
あとは`./canopus`以下にライブラリをインストールします。
  
ですがそのまま管理するのは微妙なためsubmoduleで管理するのが良いと思います。

```
git submodule add https://github.com/zubairhamed/canopus.git
```

以上で完了です。
これ以降、このパッケージをビルドする際には`git clone`後、`git submodule update --init --recursive`をし、(Makefile等を用いて)submoduleのディレクトリ内でのインストール処理を済ませた後、`go build`をすればOKです。
ただし、もしこのパッケージ自体がライブラリであった場合、他のライブラリから利用する場合も同じようなことをする必要が出てきます。

### 注意
もし`replace`したライブラリがGo Moduleを非使用で`go.mod`がない場合ビルドに失敗します。応急処置としては`touch ./canopus/go.mod`をすればビルドはできます。が、あまり綺麗ではないのでもっと良いやり方があれば教えていただきたいです。

# まとめ
Go ModuleはPure Goのライブラリ等だと扱いやすいですが扱えないライブラリはGo Moduleから切り離しGitで管理するのが現状楽そうです。

まだGo Moduleは導入されて日が浅く浸透しているとまでは言えませんが今後更に知見が共有されていくと嬉しいです。
【Python】PyPIエラー対応 Invalid or non-existent authentication informationの対処法

# 発生したエラー

`twine`を使って、PythonパッケージをPyPIに登録しようとしたところ、

`HTTPError: 403 Client Error: Invalid or non-existent authentication information.`

のエラーとなる。

```
$ twine upload --repository pypi dist/*
Enter your username: hogefuga
Enter your password: 
Uploading distributions to https://upload.pypi.org/legacy/
Uploading (yourpackagename)-1.0.0-py3-none-any.whl
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 11.4k/11.4k [00:01<00:00, 9.14kB/s]
NOTE: Try --verbose to see response content.
HTTPError: 403 Client Error: Invalid or non-existent authentication information. for url: https://upload.pypi.org/legacy/
$
```

# 対処方法

usernameかpasswordが間違っているので、正しいものを入力し直してください。

```
$ twine upload --repository pypi dist/*
Enter your username: (正しいusername)
Enter your password: (正しいpassword)
Uploading distributions to https://upload.pypi.org/legacy/
Uploading (yourpackagename)-1.0.0-py3-none-any.whl
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 11.4k/11.4k [00:01<00:00, 9.14kB/s]
$
```

無事、パッケージが登録されました。

# 環境

- Python 3.6.6
- twine 1.13.0
Power shell を使おうぜ☆（＾～＾）＜その２＞

# .bat ファイルを撲滅しよう☆（*＾～＾*）

.bat （バッチ）ファイルというのは　夢のあるやつで、一番よく見かけたのは AUTOEXEC.BAT だろうか☆（＾～＾）
Windowsと呼ばれるPCより前から　こいつは有って、
ただのテキストファイルなんで　自前で作ることもできる☆（＾～＾）
.bat ファイルを実行するだけで　ファイルをコピーしたり、何百台のＰＣのファイアーウォールの設定を変えたりといった、
ルーチンワークを片付けてくれる☆（＾ｑ＾）
要は　手で設定していたのを　このテキストファイルに書いておけば、自動実行してくれるし、他のＰＣでも使える（＾ｑ＾）

どんなにパソコンを使いこなさない日本企業のPC（Windows XPとか）でも Excel と .bat は動く、というぐらい
働き者なやつで、 １つの　.bat から　いくつもの .bat を実行するような感じで、
１つの実行で　大量の　ルーチンワーク を片付けるのに　よく使った☆（＾～＾）

この .bat を撲滅するための期待の新人が **.ps1** （Power shellのファイル）で、
このファイルを　**スクリプトレット**　と呼ぶらしい☆（＾～＾）
だいぶ使い慣れてきたので　記事を書き足していきたい☆（＾～＾）

# Task Scheduler から .ps1 を実行できる

ずっと勘違いしていて　やり方が分からなかったんだが　おそらくできそうだった☆（＾～＾）
（後日談：　やはりできなかった）

[WindowsのタスクスケジューラーでPowerShellのスクリプトを実行する際には「パス」に注意](https://www.atmarkit.co.jp/ait/articles/1412/03/news125.html)

上の記事が詳しい☆（＾～＾）
その記事を読んで　できるのなら　わたしは何も説明しなくていい……☆（＾～＾）

ＰＣ再起動時に　自動的に起動するサーバー　を作ろうと思って
タスクスケジューラーで「システム起動時に実行」の設定にして　ＰＣを再起動すると、
状態は「実行中」で　いつまで経っても　終了しなかったり、そうかと思えば　３０秒　で処理が完了したりして、
バグの中でも　**いやらしいバグの上位にくるだろう「バグが出たり出なかったりする」**　でも踏んだかと思ったんだが、
８分　ぼけーっと　していたら　処理が完了した。

つまり単に　**処理が完了するまでに３０秒～８分ぐらいかかる、そんなものだ**　というものだった。
そうか。
一体後ろはどれぐらい伸びるんだろうな。

そして タスクスケジューラーの「システム起動時に実行」するスクリプトに必要な管理者権限を　わたしは持っていない気がしてきた。
だったら **成功しないでほしい**。　成功したり、成功しなかったりするので、失敗だぜ。

# .ps1 から .ps1 を実行できる

もう　できると分かれば　やりたい放題になってくる。

[【Start-Process】PowerShellで別プロセスを起動させる方法](https://cheshire-wara.com/powershell/ps-cmdlets/system-service/start-process/)

上の記事が詳しい☆（＾～＾）

例えば　nodejs とか pm2 とか使っているなら、

```Shell:start-server.ps1
Start-Process -FilePath pm2 -ArgumentList start ./bin/web-server -NoNewWindow -Wait
```

みたいな感じにする。ファイルパスを合わせるのが一手間なんで　よくパスの説明を調べて読んでおかないといけない。

# ところで cargo を呼び出せない

rust言語を使っていると、コマンドラインから

```Shell
cargo clippy
```

とか打鍵するんだが、これをアイスで実行するとエラーになってしまう。 cargo は実行ファイルではないのか。

／／　書きかけ
【Cisco IOS】ログイン時にバナーを表示してみたり

偶然見かけて自宅のCatalystに設定したら楽しいCatalystができたので、備忘録として記録。

IOSのバージョンは15です。

##banner login ^
sshで接続した時にバナーを表示します。
設定例はこんな感じ。

```
Usamin-Planet-SW(config)# banner login ^
this is Usamin-Planet-SW!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
^
```

「^」を最後につけないと終わりません。

設定後、sshで接続した時にこんな感じになります。

```
$ ssh sw
this is Usamin-Planet-SW!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Password:
```

##banner motd ^
ログイン成功時に表示されます。
設定例はこんな感じ

```
Usamin-Planet-SW(config)# banner motd ^
Welcome to Usamin-Planet Switch!!!!!!!!!!!!!!!!!!!!!!!!
^
```

「^」をお忘れなく。

設定後、ログインに成功するとこんな感じになります。

```
Password:

Welcome to Usamin-Planet Switch!!!!!!!!!!!!!!!!!!!!!!!!
```
ようこそウサミン星へ

一応複数行いけます。

```
Usamin-Planet-SW(config)#banner motd ^
Welcome to Usamin-Planet Switch!!!!!!!!!!!!!!!!!!!!!!!!
Next stop is Chiba. Door On the right side will open.
```
```
Password:
Welcome to Usamin-Planet Switch!!!!!!!!!!!!!!!!!!!!!!!!
Next stop is Chiba. Door On the right side will open.
```



##banner exec ^
こっちもログイン成功時に表示されるものですが、違いがよくわかりません。

設定例はこんな感じ。

```
Usamin-Planet-SW(config)#banner exec ^
Mimimin!!!!Mimimin!!!!uuuuuuuuuuuuuusamiiiiiiiiiiiiiin!!!!!!!!!!!!!!!!!!!
Mimimin!!!!Mimimin!!!!uuuuuuuuuuuuuusamiiiiiiiiiiiiiin!!!!!!!!!!!!!!!!!!!
Mimimin!!!!Mimimin!!!!uuuuuuuuuuuuuusamiiiiiiiiiiiiiin!!!!!!!!!!!!!!!!!!!

Usausauuuuuuuuusaaaaaaaaaaaaa!!!!!!!!!!uuuuuuuuusamiiiiiiiiiiiin!!!!!!!!!
^
```

で、sshでアクセスしてからログイン成功するまでは以下のようになります。

```
$ ssh sw

this is Usamin-Planet-SW!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Password:

Welcome to Usamin-Planet Switch!!!!!!!!!!!!!!!!!!!!!!!!
Next stop is Chiba. Door On the right side will open.


Mimimin!!!!Mimimin!!!!uuuuuuuuuuuuuusamiiiiiiiiiiiiiin!!!!!!!!!!!!!!!!!!!
Mimimin!!!!Mimimin!!!!uuuuuuuuuuuuuusamiiiiiiiiiiiiiin!!!!!!!!!!!!!!!!!!!
Mimimin!!!!Mimimin!!!!uuuuuuuuuuuuuusamiiiiiiiiiiiiiin!!!!!!!!!!!!!!!!!!!

Usausauuuuuuuuusaaaaaaaaaaaaa!!!!!!!!!!uuuuuuuuusamiiiiiiiiiiiin!!!!!!!!!

Usamin-Planet-SW>
```

ちなみにRunning Configで確認すると以下のようになります。

```
banner exec ^C
Mimimin!!!!Mimimin!!!!uuuuuuuuuuuuuusamiiiiiiiiiiiiiin!!!!!!!!!!!!!!!!!!!
Mimimin!!!!Mimimin!!!!uuuuuuuuuuuuuusamiiiiiiiiiiiiiin!!!!!!!!!!!!!!!!!!!
Mimimin!!!!Mimimin!!!!uuuuuuuuuuuuuusamiiiiiiiiiiiiiin!!!!!!!!!!!!!!!!!!!

Usausauuuuuuuuusaaaaaaaaaaaaa!!!!!!!!!!uuuuuuuuusamiiiiiiiiiiiin!!!!!!!!!

^C
banner login ^C
this is Usamin-Planet-SW!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
^C
banner motd ^C
Welcome to Usamin-Planet Switch!!!!!!!!!!!!!!!!!!!!!!!!
Next stop is Chiba. Door On the right side will open.

^C
```
「^C」となっており、このままコピペで設定するとCが入ってしまいますので、ご注意を。

面白おかしく誤ログインや誤設定を防ぎましょう。
S3+Cloudfrontでホスティングしている静的サイトに拡張子なしでもtxtファイルとしてブラウザで表示させる

一時間ほどハマってしまいました。

# やりたかったこと
S3+Cloudfrontでホスティングしている静的サイトに拡張子なしでテキストファイルを置きたかった。

# 問題
S3のファイルのメタデータの`Content-Type: text/plain`を設定してもブラウザ側でバイナリファイルと判断されダウンロードが始まってしまう。

# 結論
BOMがなかった。BOMを追加する。

まずはBOMの確認方法。

```bash
$ file hoge.txt
hoge.txt: ASCII text # BOMがないときの表示
$ file hoge.txt
hoge.txt: UTF-8 Unicode (with BOM) text # BOMがあるときの表示
```

BOMを追加。

```bash
$ nkf --overwrite --oc=UTF-8-BOM hoge.txt
hoge.txt: UTF-8 Unicode (with BOM) text
```

あとはS3にアップロードするだけです。

余談ですが間違って追加したBOMの削除は

```bash
$ nkf --overwrite --oc=UTF-8 hoge.txt
hoge.txt: ASCII text
```

でできます。

# 原因
ブラウザによるSniffingが行われて`Content-Type`を`text/plain`に設定してもバイナリファイルと判断されてしまっていた。
Sniffingをさせない方法としては

- `X-Content-Type-Options : nosniff`をHTTPヘッダに設定してSniffingさせない。
    - .htaccessでHTTPヘッダに追加。
        - S3では.htaccessは使えない。
    - S3のメタデータでHTTPヘッダに追加。
        - `X-Content-Type-Options`メタデータは提供されていない。
    - Lambda@Edgeの`Viewer Response`でHTTPヘッダに追加。
        - お金かかるしオーバヘッドになるのでやりたくない。

- Sniffingしたときにtxtファイルと判断させる。
    - BOMを追加すればよい！！！

という行程でした。
余談ですが、`X-robot-tag: noindex`をヘッダに追加したい場合はhtmlファイルでない限り、Lambda@Edgeでヘッダーを追加するしかなさそう。


.htaccessが使えなかったり不便な点もありますが、メンテ無しで料金も安いS3のホスティングは素晴らしい〜！！

# 参考
https://stackoverflow.com/questions/9660514/content-type-of-text-plain-causes-browser-to-download-of-file

# 追記
https://christina04.hatenablog.com/entry/2017/06/23/195318
macでChromeを用いて可能な限り目に優しい環境を作る



## 概要

macOS Mojaveでダークモードが追加されたことにより、mac標準のアプリやOffice、ネイティブアプリなどは綺麗にダークテーマで表示され、かなり目に優しくなったと思います。しかし、一部アプリやブラウザ上のwebコンテンツまでは対応していないため、目がチカチカしてたまりません😩

そこで、Chromeの拡張機能を用いて出来るだけ目に優しい環境を構築したいと思います。



## 拡張機能のインストール

[Dark Reader](https://darkreader.org/)という拡張機能を使います。[GitHub](https://github.com/darkreader/darkreader)にも公開されていますがインストールは自己責任でお願いします。

![スクリーンショット 2019-02-25 19.29.35.png](https://qiita-image-store.s3.amazonaws.com/0/137148/eefaeb29-4e17-00c4-32fc-bf030fd97314.png)


Firefoxでも使えるみたいです(Safariは有料です😇)

インストールするとQiitaなら以下のように表示されます！

![qiita.com_katsuya_U.png](https://qiita-image-store.s3.amazonaws.com/0/137148/59f8c547-3401-4ad5-ea15-4d7eb44a4977.png)


おお、めちゃめちゃ見やすい…！

グラフ部分は正しく表示されていないですが、数時間使用したところ、Gmailやスプレッドシート、GitHubなど日常的に使うページはかなり正確にダークテーマになっていました。

(Chromeの設定やChromeのストアなどは適応されないみたいですが。。)

## チャットツールをダークテーマでapp化する

 SlackやLINE WORKS、ChatWorkなど業務向けチャットツールはApp Storeで配布されていますが、残念ながらダークテーマがまだ実装されていません。

そこで、Chromeのショートカット機能を使ってwebページをapp化してみようと思います。(app化したwebページはDark Readerを初め拡張機能が適応されます。)

弊社では主にLINE WORKSを使っているため、LINE WORKSをapp化します。

1. 右上のメニューから その他のツール>ショートカットを作成… を選択します

![スクリーンショット 2019-02-25 19.53.51.png](https://qiita-image-store.s3.amazonaws.com/0/137148/68145310-40bf-76e0-7dfd-0746cda68ee6.png)


2. ダイアログにアプリ名を入力し、ウィンドウとして開くをチェックしてOKをクリック

![スクリーンショット 2019-02-25 19.59.06.png](https://qiita-image-store.s3.amazonaws.com/0/137148/89f3891d-87a4-5073-bffa-03c34c648e1e.png)


3. appとして開ける！

<img width="1181" alt="スクリーンショット 2019-02-25 20.08.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/137148/34e7c842-f8bc-740e-5560-e50b83ddd0e3.png">


LINE WORKS もいい感じにダークテーマが適応されてますね☺️

アイコンはLINE WORKSの場合faviconが適応されて見栄えが悪かったので、適宜差し替えるといいでしょう。

## まとめ

これで使用するアプリの9割がダークテーマになり、かなり目に優しくなりました☺️

これでコンタクトでも目に負担がかからないんでかなり嬉しいです...！
Salesforce画面へのTableau表示

# 概要
Tableauで作成したワークブックやダッシュボードをSalesforceの画面で表示することができます。
今回実施するやり方は、TableauシートのURLをVisualforceに埋め込み、そのVFをLightningレイアウトに追加するという方法です。
# 完成図
完成すると以下のようにTableauのシートがSalesforceの画面に表示されます。
以下の例では、何かしらのデータを都道府県別にバブル表示したTableauレポートをSalesforceのホーム画面に埋め込んでいます。
もちろん取引先や商談の画面に埋め込むこともできます。
![TableauHome.PNG](https://qiita-image-store.s3.amazonaws.com/0/260521/19f55941-43ea-b0f5-d877-3464b0c073b4.png)
# 手順
全体の手順は以下のような感じです。
1. Tableauでワークブックを作成
2. 作成したシートやダッシュボードの共有URLを取得
3. Visualforceページを作成して、iframeタグに共有URLをセットする
4. Lightningページに、作成したVisualforceページを埋め込む

では早速やっていきましょう。
まずはTableauにログインしてワークブックを作成します。
![tab1.PNG](https://qiita-image-store.s3.amazonaws.com/0/260521/7c4cf344-2b8b-2931-e75f-a42e65e257c5.png)
出来上がったものが以下になります。右上の共有ボタンを押して共有URLを取得しましょう。
![tab2.PNG](https://qiita-image-store.s3.amazonaws.com/0/260521/7d0590e4-4ed8-d291-d6a8-1482e8539fcd.png)
今回必要なのは「リンク」のほうです。コピーしておきます。
![tab3.PNG](https://qiita-image-store.s3.amazonaws.com/0/260521/784db33b-c4b2-ba7f-5fc4-b260f6068cce.png)
次にSalesforceにて以下のようなVisualforceを作成します。

```TEST_Tableau.page
<apex:page >
  <apex:iframe src="先ほどコピーした共有URL"/>
</apex:page>
```

あとは作成したVFページをLightningレイアウトに埋め込むだけです。
今回はホーム画面に追加します。
Lightningレイアウトの編集画面でコンポーネント一覧からVisualforceをドラッグアンドドロップして先ほど作成したページを選択します。
ここで表示する枠の高さも指定できるのでTableauレポートに合わせて指定します。
![tab4.PNG](https://qiita-image-store.s3.amazonaws.com/0/260521/cd060d99-a486-1fc0-14e7-fe2ccf5b868d.png)
ホーム画面を表示してTableauにログインすると、以下のようにTableauレポートが表示されました。
![tab5.PNG](https://qiita-image-store.s3.amazonaws.com/0/260521/e38948dd-3e08-416e-16d6-b6e6ac1637d6.png)
以上!!TableauレポートのSalesforce画面への表示手順でした。
今回は単純に表示するだけでしたが、Tableauのフィルタ条件をVisualforce側のJavascriptで設定するといったこともできます。
それについては余裕があればまた別の記事を書こうかと思います。

それでは、よいSalesforce&Tableauライフを～( ^_^)/~
Note about UNUserNotification

`UIUserNotification` is deprecated since iOS10, and we use `UNUserNotification` instead. We need to import `UserNotifications`

- Set up the delegate: usually did in `didFinishLaunchingWithOptions` in AppDelegate

```objective_c
UNUserNotificationCenter.currentNotificationCenter.delegate = self;
```
- Register the remote notification: usually did in `didFinishLaunchingWithOptions` in AppDelegate

```objective_c
UNAuthorizationOptions options = UNAuthorizationOptionAlert | UNAuthorizationOptionSound;
[UNUserNotificationCenter.currentNotificationCenter requestAuthorizationWithOptions:options
                                                                      completionHandler:^(BOOL granted, NSError * _Nullable error)
{
    if(!error){
        dispatch_async(dispatch_get_main_queue(), ^{
            [[UIApplication sharedApplication] registerForRemoteNotifications];
        });
    }
}];
```

- UNUserNotificationCenterDelegate Methods 

```objective_c
// called when a notification is delivered to a foreground app.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
    completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert);
}

// called when the user clicked the notification
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(UNNotificationPresentationOptions))completionHandler {
    NSDictionary *userInfo = response.notification.request.content.userInfo;
    // customize code here
    completionHandler(UNNotificationPresentationOptionAlert);
}

// called when a remote notification is received 
// content-available should be set to true for the delegate to be called
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    // customize code here
    completionHandler(UIBackgroundFetchResultNoData);
}
```
- How to schedule a notification

```objective_c
UNMutableNotificationContent *content = UNMutableNotificationContent.new;
content.title = @"this is a title";
content.body = @"body message";
content.userInfo = @{@"userID": @(100)};
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1
                                                                                                repeats:NO];
NSString *identifier = @"test";
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier
                                                                      content:content
                                                                      trigger:trigger];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request
                                                       withCompletionHandler:^(NSError * _Nullable error)
{
    if (error) {
        // something went wrong!!
    }
}];
```
Vue.jsのv-forでネスト(入れ子)したい

##はじめに
Vue.jsを学習している中で`v-for`をネストする方法でつまづいたので今回記事としてまとめてみました。

##基本的なv-forの使い方
dataの値が配列の場合、`v-for`を使用することでリスト形式で表示することができます。

```js:sample.js
var sample = new Vue({
	el: '#sample',
	data: {
		message: 'v-for基本',
		items: ['item1', 'item2', 'item3']
	}
})

```
```html:sample.html
<div id="sample">
	<h1>{{ message }}</h1>
	<ul>
		<li v-for="item in items">{{ item }}</li>
	</ul>
</div>
```
結果↓
<img width="150" alt="スクリーンショット 2019-02-25 15.32.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/255876/76b5dcab-9266-c017-3654-7e32870b9389.png">

##今回やりたいこと(完成形)
さっそく本題へ！
ネストのリストの完成形はこちらです。↓
<img width="253" alt="スクリーンショット 2019-02-25 15.30.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/255876/ca2f6857-2e85-e274-4980-e2e73c8baee6.png">

##v-forで入れ子（ネスト）を実装
```js:sample2.js
var sample2 = new Vue({
	el: '#sample2',
	data: {
		message: 'v-forでネスト',
		categorys:[
			{name:'哺乳類', animals:['人', 'ねこ', 'さる', 'パンダ']},
			{name:'鳥類', animals: ['ニワトリ', 'アヒル', 'カラス', 'すずめ']},
			{name:'爬虫類', animals: ['わに', 'トカゲ', 'へび', 'かめ']}
		]
	}
})
```

```html:sample2.html
<div id="sample2">
	<h1>{{ message }}</h1>

	<ul v-for='category in categorys'>
		<li>
			{{ category.name }}
			<ul>
				<li v-for="animal in category.animals">{{ animal }}</li>
			</ul>
		</li>
	</ul>
</div>
```
ネストしたリストを表示することができました〜♪

##解説
もう少し詳しく`categorys`配列の中身を見てみたいと思います。

```html:
<ul v-for='category in categorys'>
	<p>{{ category }}</p>
	<li>
		{{ category.name }}
		<ul>
			{{ category.animals }}
			<li v-for="animal in category.animals">{{ animal }}</li>
		</ul>
	</li>
</ul>
```
<img width="567" alt="スクリーンショット 2019-02-25 17.09.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/255876/e55552c9-d7c7-fc5a-755d-440bfae691f2.png">

上記の結果よりネストを実現したい場合
・`v-for="category in categorys"`で要素を取り出す。
・`{ category.key名 }`を指定することでkeyに紐づいたvalue値を1つずつ取り出す。
・`catogory.animals`は配列なのでさらに`v-for="animal in category.animals"`で1つずつvalue値を取り出す。

##まとめ
`v-for`を利用してネストで表示するのだいぶ苦戦しました。
「[解説](#解説)」でもいろいろデータを表示して試している通り実際に表示して動作を確認しながら書くと理解が深まると思います。
vagrantのCentOS にNode.jsをインストールする際にnvmを使ったバージョンアップ

ドッ●インストールで作ったVagrantでUde●yのLaravel講座を勉強しようと思い、環境構築。

Composerを入れる

```
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

```
laravel入れる

```
php composer.phar create-project --prefer-dist laravel/laravel xx(プロジェクト名)
```
プロジェクト名の場所に移動し、Gitを対応させる,

Node.jsを
https://nodejs.org/ja/download/
からダウンロードしてインストールし、npmをインストールしようとする

```
npm install
```

しかしここでエラーがでる。

```
Error: CERT_UNTRUSTED
```
一旦SSHは解除

```
npm config set strict-ssl false
```

今度はこのエラーが出た。

```
Error: No dist in undefined package
```

エラーで検索するとインストールしたnpmとnodeのバージョンが古いらしい

```
npm ERR! node -v v0.10.48
npm ERR! npm -v 1.3.6
```

キャッシュクリアなどは効果なし

```
npm cache clean --force
npm cache verify
```
以下を試すも、バージョンが上がらない。

```
 npm install -g npm
```

nvm入れたらバージョンアップできた（参考になった記事↓）
https://tako1192.hatenablog.com/entry/2016/05/07/054522
https://qiita.com/fagai/items/93402522a9024e243f4d

```
$ node -v
v11.10.0
$ npm -v
6.7.0
```
ふたたびnpm installでインストール完了!
$_POSTとか$_GETを書くのが面倒なので１文字にしてみた

# はじめに（おまじない）

WEBフレームワークなどを使用していて、OOPをしている方々には（もしかしたら、そうでない方にも）、\$\_POSTや\$\_GETをそのまま使用するのは「ありえない話」かもしれません。

たぶん現代PHPエンジニアは、\$\_POSTや\$\_GETなどのグローバルな変数に対し、httpリクエストインスタンス的なラッパーをかまして扱うのが、現代PHPなんだと思っています。

今回、私は試験的に「ありえない話」をしようとしていますので、もしかしたら、読まずにスルーしていただいたほうが、お互いに幸せかもしれません。

※上記は#include \<stdio.h\>的なおまじないです。深い意味はありません。

# $_POSTや$_GETについて

これらの変数は素のPHPでは、よく使われます。唯一の入力値でもありますので当然といえば当然です。

これらの変数を「もっと気軽に使ったほうがいいのでは？」と思っています。そのままWEBからの入力値としてラッパーをかまさずに使っているシステムをいくつか見てきましたが、とくにコーダーが非常識なことをしなければ、それがバグの要因になって困りません。困ったことがありません。その経験から、今も素のPHPを書く時は、そのまま\$\_POSTや\$\_GET扱っています。しかし、\$\_POSTや\$\_GETをいくつも書くのは骨が折れます。というか\$\_POSTや\$\_GETという文字を見るのが最近は億劫です。。。

グローバルな変数への置き換えをしても、関数を実行する度にglobalキーワードや\$GLOBALを使うのは気持ちが悪いし、それならまだ引数として必ず受け取るかメソッドから取得した方がまし。

．．．でもそうじゃない。短く書きたい。できれば１文字で。

※コード設計に関係する話にはせずに、入力の億劫さは「エディタの機能で補完せよ」という主張もあるかもしれませんが、宗教上の理由によりできません。

# 解決方法を見つけた

```php:test.php
define("p", $_POST);
define("g", $_GET);
define("f", $_FILES);
define("c", $_COOKIE);

echo p["onamae"];
```

※php7から配列も定数にできるようになった。
※定数だけど小文字なのは入力しやすいからです。
※もったいぶった言い方をしましたがネタはこれだけ。すみません。

# 良い点

- 定数なので内容が書き換えられない。

# 問題点

- requestの値を定数にするのはそもそもおかしい。

# 個人的な結論

- とても短くなったから、これでいいんじゃね。
最近使っているツール2019

https://qiita.com/mnuma/items/99a2e5a8f9867477985a

この手の記事を以前書いたので、改めてアップデートしてみました。

## aText
http://www.trankynam.com/atext/
テキスト入力支援系アプリ、忘れがちなコマンドとかのキーフレーズを登録してます。
設定したキーフレーズを他のマシンとDropboxで共有することも出来ます。

## Spectacle
https://www.spectacleapp.com/
ウィンドウサイズ調節ツール。
ショートカットキー一発ででウィンドウを自在に動かせます。
以前はSizeUpを使ってましたが無料で使えるので置き換えました。

## Kap
https://getkap.co/
スクリーンキャプチャアプリです。
デスクトップの操作をキャプチャして、さくっと動画にしてくれます。
gif、mp4、Web、APNGなどへの書き出しも可能です。


## Awesome Screenshot
Chrome拡張です。ちょっとしたキャプチャを撮って、軽く注釈入れたいときとかに便利。
https://chrome.google.com/webstore/detail/awesome-screenshot-screen/nlipoenfbbikpbjkfpfillcgkoblgpmj?hl=ja

## ImTranslator
こちらもChrome拡張の翻訳ツールです。
インラインで対訳を入れてくれるのが良さげです。

https://chrome.google.com/webstore/detail/imtranslator-translator-d/noaijdpnepcgjemiklgfkcfbkokogabh?hl=ja
![image.png](https://qiita-image-store.s3.amazonaws.com/0/7410/74e52858-cbc5-0605-6572-5f8e89d47593.png)

## Gravit

https://gravit.io
イラレの代わりに。
まだ使いこなせて無いですが、かなり高機能です。

## SqlDBM

https://app.sqldbm.com/
テーブル定義考えるときなどに。
黒くてかっこいいですが、Freeプランだと1プロジェクトのみ。


## Authy

https://authy.com/
2段階認証してるサービスなど、スマホ、Chrome、Macアプリなどマルチデバイス向けに配信されているので便利です。
データをクラウドで保持してくれるので、端末変更などが発生した場合も楽。