OmniAICreator/Qiita-1.07M huggingface dataset:
itertools.groupby ご利用上の注意

# イテレーション中でグループを参照すること

https://docs.python.org/ja/3/library/itertools.html#itertools.groupby より
> 返されるグループはそれ自体がイテレータで、 groupby() と iterable を共有しています。もととなる iterable を共有しているため、 groupby() オブジェクトの要素取り出しを先に進めると、それ以前の要素であるグループは見えなくなってしまいます。


良い例：

```python
>>> import itertools
>>> groups = []
>>> for _, g in itertools.groupby([1, 1, 2, 2, 3, 3]):
...     groups.append(list(g))
...
>>> for g in groups:
...     print(g)
...
[1, 1]
[2, 2]
[3, 3]
```

悪い例：

```python
>>> import itertools
>>> groups = []
>>> for _, g in itertools.groupby([1, 1, 2, 2, 3, 3]):
...     groups.append(g)
...
>>> for g in groups:
...     print(list(g))
...
[]
[]
[]
```

# 事前にソート済みであること

https://docs.python.org/ja/3/library/itertools.html#itertools.groupby より
> 通常、iterable は同じキー関数でソート済みである必要があります。

ソート済みでないと使えないというわけではないが、例えば以下のどちらを期待してるかによって、必要なら事前にソートしてから groupby を呼ぶ。

事前にソートしない例：

```python
>>> import itertools
>>> groups = []
>>> for _, g in itertools.groupby([1, 1, 2, 2, 3, 3, 2, 1]):
...     groups.append(list(g))
...
>>> groups
[[1, 1], [2, 2], [3, 3], [2], [1]]
```

事前にソートする例：

```python
>>> import itertools
>>> groups = []
>>> for _, g in itertools.groupby(sorted([1, 1, 2, 2, 3, 3, 2, 1])):
...     groups.append(list(g))
...
>>> groups
[[1, 1, 1], [2, 2, 2], [3, 3]]
```

# 確認環境

Python 3.7.2 で動作確認しました。
Rust Vector alphabet を簡潔に初期化 🐒

スニペットなどに
さらに良いやり方があれば教えてください:metal:

# Vector

```rust
let v = (b'a'..=b'z').map(|c| c as char)
                    .collect::<Vec<_>>();

// or

let v = (0..26).map(|x| (x + b'a') as char)
               .collect::<Vec<_>>();

// ['a', 'b', .., 'z']
```

ただしAtCoderではRustのバージョンが低く(Ver 1.15.1)(2019年4月13日 現在)([6月頃に言語アップデートがあるそうです](https://twitter.com/chokudai/status/1100429644681998336))

```Rust
b'a'..=b'z'
```

の文法は使えません

```Rust
b'a'..b'z'+1
```
を代わりに使用できます

# HashMap (0で初期化)
[AtCoder Beginner Contest 098 B問題](https://atcoder.jp/contests/abc098/tasks/abc098_b) など文字ごとの出現数を数えたいときに使えます

```Rust
let m = (b'a'..=b'z').map(|c| c as char)
                     .map(|c| (c, 0))
                     .collect::<HashMap<_, _>>();

// or

let m = (0..26).map(|x| (x + b'a') as char)
               .map(|c| (c, 0))
               .collect::<HashMap<_, _>>();


// {'a': 0, 'b': 0, .., 'z': 0}
```

[追記]
@JunSuzukiJapanさん, @vain0xさんのコメントにより一部修正しました
修正箇所は本記事下のコメントを参照ください。

[P.S]
文字列に出てくるある１文字(ここではピリオド)を数える

```Rust
 let cnt_period = s.iter().filter(|ch| **ch == '.').collect::<Vec<_>>().len();

 // or

 let cnt_period = s.iter().filter(|&c| *c == '.').count();
```

参考
[stack overflow](https://stackoverflow.com/questions/45343345/is-there-a-simple-way-to-generate-the-lowercase-and-uppercase-english-alphabet-i/45344161)
[rosettacode.org](https://rosettacode.org/wiki/Generate_lower_case_ASCII_alphabet#Rust)
ActionCableとロードバランサーを併用する時のRedisの設定

こんにちは。
Cryptogamesで働いているじゅん([@BoNingennnN](https://twitter.com/BoNingennnN))です。

最近仕事でAcitionCableを使う機会がありました。
RailsでWebsocket通信を行うものを実装するなら、ActionCableを使うのがデフォルトです。
リアルタイムのメッセージなどの機能を実装する時に使うことが多いと思います。

ActionCableは若干とっつきにくい部分もありますが、使い慣れてしまえば基本的な部分で詰まることはあまりないと思います。

ですが、Redisの設定ではかなり苦しんだので、今回はそのことを書いていきます。
(ちなみにQiitaには初めて投稿します！)

## 本番環境でActionCableを使うなら、Redisを使う必要がある。
「ActionCableを使ってみた」というような記事がいくつかあるかと思いますが、その多くではRedisを使っていません。
これは、development環境では初期設定としてRedisが使われていないからです。

しかし、公式のドキュメントにも書かれている通り、本番環境ではRedisを使うことが推奨されています。
なので、もしActionCableを使うようなWebアプリケーションを作って、実際に本番運用する予定があるのであれば、Redisを使う必要があります。


## ロードバランサーを使わない場合
ロードバランサーを使わない場合、もしくはロードバランサーを使ったとしてもサーバーが一台の場合は、比較的シンプルです。
アプリケーションののっているEC2上にRedisもインストールすればOKです。
そしてそれを起動し、config/cable.ymlの記述を変えてあげればうまく作動します。
(イメージは下の感じ。字が汚くてすみません、、)
![iOS の画像 (3).jpg](https://qiita-image-store.s3.amazonaws.com/0/311667/6fcdd829-70f4-8a32-9284-e6c5884ba49a.jpeg)



私も最初はこちらでやっていました。
しかし、ロードバランサーを立てて、その下に複数台のサーバーをぶら下げるような構成だと、このパターンではうまくいきません。
(サーバーとクライアントが1対1であればうまくいきます。ですが、リアルタイムメッセージのようにクライアント側が複数の場合はうまくいかない。)

これを解決するためには、RedisをEC2の外においてあげる必要があります。

## ロードバランサーを使う場合の設定
ここからが本題です。
ロードバランサーがない場合と同様に、EC2にRedisを立てるとうまくいきません。
２つのクライアントが異なるEC2のサーバーとWebsocket通信をし、その上でメッセージのやり取りを行おうとすると、下の図のような感じでうまくメッセージが飛びません。
![iOS の画像 (2).jpg](https://qiita-image-store.s3.amazonaws.com/0/311667/83a3d10d-e952-0311-f8c0-4a9de8c6fe09.jpeg)

これを解決するためには、RedisをEC2の外にだしてあげることが必要となります。
![iOS の画像 (2).jpg](https://qiita-image-store.s3.amazonaws.com/0/311667/e01a108a-08f9-1f24-5833-f9617cce54b3.jpeg)
(この図は、クライアントAからクライアントBにメッセージを送る時の図。)


Redis専用のEC2を立てる方法もあるかと思いますが、今回私はAWSのElastiCache Redisを使いました。
ElastiCache Redisを作成すると、プライマリエンドポイントというものが表示されます。
hogehoge.************.chache.amazonaws.com:6379
みたいなやつです。

これをconfig/cable.ymlに記述すればOKなのですが、なぜかなかなかうまくいきませんでした。
試行錯誤を繰り返した結果、最終的にどうにかうまくいったのでそれを共有します。

``` config/cable.yml
production:
  adapter: redis
  port: 6379
  url: redis://hogehoge.************.chache.amazonaws.com
```
これで設定ファイル自体はOKなはずです。
(ただし、urlについてはもちろん環境変数に入れておくべきです。)

これで本番環境でもActionCableが使える、、と言いたいところですが、もう一点気をつけないといけないことがあります。
それが作成したElastiCache Redisのセキュリティグループです。

初期設定ではRedisはPort番号6379を使います。
なので、当たり前といえば当たり前ですが、セキュリティグループのインバウンドに関しても、Port6379をあけてあげる必要があります。
アウトバウンドに関しては全てをあけて問題ないかと思います。

これでようやくちゃんと動作します！！

以上で初めてのQiitaへの投稿を終わります！
(説明が色々分かりづらくてすみません🙇‍♂️)
海外でゲーム開発会社を作って、2000万円溶かして学んだ反省点

# まえがき

どうも[英語物語](https://play.google.com/store/apps/details?id=com.frecre.englishstory)という英語学習ゲームを開発してます。[Gong](https://twitter.com/English_Story)です。

２年超の赤字期間を経てやっと、黒字化した英語物語なのですが、
懲りずに、フィリピンで[ワードコスモス](https://play.google.com/store/apps/details?id=com.frecre.wordcosmos)というゲームを作って
また大きな赤字出してしまいました。

(ちなみに、英語物語で赤字期間に書いた失敗談は[こちら](https://storys.jp/story/10269)。)

現在も、目下お金を溶かし中ですが、
先月、社員旅行中に乗っていた車が山道で横転するという事故が起こり
もう一度よく考えてみる機会を得ました。

今までの反省点をきちんと振り返り、
今後に開発に活かして行くため記事にしてみます。

ゲームやアプリ、システム開発をやりたいという人の参考になれば幸いです。
（ちなみに当たり前の事しか、書いてないです。当たり前のことって難しい。）

# 組織作りについて
（結論；**最初はプロトタイピングに必要な人員だけ雇え**）
次はフィリピンで世界向け英語学習サービスを開発だ!
と意気込んで、人事や色々な職種を雇ってから、
どんなサービスにするかを計画しだしたのですが、
圧倒的に間違いでした。
まずは、どんなサービスにするかを計画するために必要な人員だけを雇って、
サービスが決まってから、必要な人を雇うべきです。

いい人を雇うのは時間がかかるので、早く雇わなきゃとか
思ってましたが、サービスが決まる前に人を雇う弊害の方がはるかに大きいです。

金が溶けるから、焦ってくる。
サービスがリソースに引っ張られる。
業務内容がフワッとし、成功までに時間もかかるため、士気が下げる。

という弊害があります。

# ゲームの企画について
（結論；**コアゲームシステムを必要最小限で検証する**）
①のような状況で企画していると、まあドンドン豪華なアプリになっていきます。
(本人（自分）では、シンプルにしているつもりでも、)

コアとなるゲームの面白さ　を検証する以外の色々な要素が組み込まれて行き、
リリースまで時間がかかり、いざフタを開けると、あれ、このコアゲームシステム微妙？
とかいう感じになってきます。

"コアとなるゲームの面白さ"を検証するためのアプリを最短で作りましょう。
その良さが検証できてから、ビジネスモデルや継続率、収益性のための機能を考えましょう。
次僕がやるなら、
①検証するためのミニマムなアプリをいくつか企画・制作・公開する。
②マーケットの評価や分析データを検証する。
③本腰を入れて取り組むコア・ゲームシステムを決める。
④新たにアプリを企画・制作・公開します。

# ゲームの開発について
（結論；**企業文化とプロセス作りに最初からしっかり取り組む**）
企業文化とか、プロセスとか、
正直売上が上がってない状況ではあまり気にできません。
衣食足りて、礼節を知るではないですが、
売上足りて、仕組み作る。
になりがちです。
まあ、仕方ないし、やってみないと企業文化とかプロセスとか分からないんですが、
後から作るのは、とても大変だし、
きちんと作るには、時間がかかるので、
最初から取り組むのを強く勧めたい。
（一回ベンチャー企業とかに就職して失敗・成功体験があるといいかも。）
（今はしっかりスクラムやろうと研究中です。）

# 英語物語との並行開発について
（結論；**一つの事に集中できる環境を事前に作る**）
つらいです。両方が中途半端になりがちです。
英語物語のカスタマーサポート・運営・開発・ディレクション業務を行いながら、
ワードコスモスの企画・開発サポート・バックオフィス系・企業文化・プロセス作り
をする。

労働時間にすると、たいして働けていないのですが、
マルチタスクになりすぎてドンドン作業効率が落ちる悪循環に陥ります。

新しい事に着手する前に、まず英語物語の方をきちんと仕上げる。
少なくとも、僕がいなくても運営が回る体制にする。
べきでした。

# 今後
（結論；**諦めません。勝つまでは。**）
・企業文化とプロセス作りを頑張ります。
・ワードコスモスを時間を区切って完成させます。
・一度フィリピン法人を閉じて、再設立するかも。
・英語物語をしっかり仕上げます。

# 最後に
### フィリピン法人の皆
無能な社長で本当にごめんなさい。
失敗ばかりだけど、皆と出会えた事は本当に幸せだと思っているし、
すでに辞めたメンバーを含め、皆大好きです。
ワードコスモスも完成させれば、価値のアプリものになるとまだ信じています。
皆が働く価値のある会社になれるよう頑張ります。
### 英語物語ユーザの皆様
開発の遅れや、運営ミスの多発、本当に申し訳ないです。
いつも暖かく見守って頂きありがとうございます。
今後はもっとしっかりした体制作りと、開発を行います。
### 日本法人の皆様
英語物語に集中していたら、
もっと良い状況になっていたはずなのに、
未だに苦難の日々申し訳ないです。
丸投げばかりの状況にめげず、
責任感を持って対応頂き感謝感謝です。
### 家族の皆様
そばにあまりいれなくてごめんなさい。
いつも支えてくれてありがとう。


# その他記事・広告
[デザインパターンの本質（Unity用)](https://qiita.com/English_Story/items/1ea0d16763878f382c2c)
[発音記号キャラ辞典](https://www.amazon.co.jp/%E7%99%BA%E9%9F%B3%E8%A8%98%E5%8F%B7%E3%82%AD%E3%83%A3%E3%83%A9%E8%BE%9E%E5%85%B8-Dacci-%E8%8B%B1%E8%AA%9E%E7%89%A9%E8%AA%9E/dp/4046023015)
ESP8266搭載ボード(￥422)でWOL中継機を作ってみた

#外出先からWOLでPCやHDDレコーダーの電源ON
外出先からスマホでPCやHDDレコーダーの電源をONし、外出先から機器を遠隔操作できるようにしています。インターネットからWOLパケットを送信し、パケットのフォワーディングで、自宅内LANへブロードキャストすることで実現していました。
[送信機器] ---> [ルーター] ---ブロードキャスト---> [PC1], [PC2]
のような構成です。

#引越し後に問題発生
引越し先はJ:COMのCATVインターネットが無料で使え、WiFi親機付きのルーターも無料でレンタルできますが、ここで問題発生。引っ越し前と同じくWiFi親機からWOLパケットのフォワーディングを設定し、転送先をブロードキャストアドレスにしたのですが、WOLパケットが転送されません。どうやらJ:COMのWiFi親機の問題のようです。

#Wake On LANリピータ?
http://www.starstonesoft.com/WOLRepeater.htm
のような機器を使えば、問題を解決できそうです。
つまり、
  [ルーター] ---ブロードキャスト---> [PC1], [PC2]
が無理なので、ルーターから先を
  [ルーター] ---ユニキャスト---> [WOL中継機] ---ブロードキャスト---> [PC1], [PC2]
とすればよいはずです。

PC1, PC2に対して何故ブロードキャストでないといけないのかというと、ルーターやスイッチングハブはある程度時間が経過すると、電源OFFの機器のMACアドレスを忘れてしまうからです。忘れてしまうとユニキャストの場合は転送されません。ブロードキャストなら転送されるのでこれを利用しています。

WOL中継機の仕事は、特定のポート宛のUDPパケットをブロードキャストアドレス宛に転送するだけです。つまり、右から来たものを左に受け流す仕事をします。通信ライブラリ等が整備されたボードでなら機能を絞れば簡単に作れそうです。

#ESP8266搭載ボード
安いものを探したところ、これを見付けました。
https://www.amazon.co.jp/gp/product/B07K2VQ4J7/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1

最初はEthernet搭載ボードを探していたのですが、WiFi搭載のほうが安いということに気付きました。まあ性能は低いでしょうが、今回の目的には十分ですし、何と言っても激安です。￥422で1個注文したのですが、何故か2個セットが届きました(支払いは1個分だけです)。因みに、中国からの発送で、届くまでに約3週間かかりました。

#Arduino IDE
Arduino IDEで開発できますが、とにかく簡単に作れます。nodeMCU 1.0を指定し、正味わずか50行足らずでWOLリピータのようなものができました(WOL_helperと名付けました)。
以下、ソースコードです。

```C++:WOL_helper.ino
// WOL_helper
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>

// Settings
#define SSID		"SSIDをここに書く"
#define PASSWORD	"パスワードをここに書く"
#define SRC_PORT	8888    // 待受ポート番号
#define DST_PORT	9

WiFiUDP UDP;
IPAddress broadcastIP;

void setup(void)
{ 
  Serial.begin(115200);
  // Connect to WiFi
  WiFi.begin(SSID, PASSWORD);

  // while wifi not connected yet, print '.'
  // then after it connected, get out of the loop
  while (WiFi.status() != WL_CONNECTED) {
     delay(500);
     Serial.print(".");
  }
  broadcastIP = (uint32_t)WiFi.localIP() | ~(uint32_t)WiFi.subnetMask();
  UDP.begin(SRC_PORT);

  //print a new line, then print WiFi connected and the IP address
  Serial.println("\nWiFi connected");
  // Print the IP address
  Serial.print(WiFi.localIP());
  Serial.printf(":%d->", SRC_PORT);
  Serial.print(broadcastIP);
  Serial.printf(":%d\n", DST_PORT);
}

void loop()
{
  static unsigned char buf[200];
  int packetSize = UDP.parsePacket();
  if (0 < packetSize && packetSize <= sizeof(buf)) {
    int len = UDP.read(buf, packetSize);
    Serial.print(UDP.remoteIP());
    Serial.print(" /");
    for (int i = 0; i < len; i++) {
      Serial.printf(" %02X", buf[i]);
    }
    Serial.println("");
    UDP.beginPacket(broadcastIP, DST_PORT);
    UDP.write(buf, len);
    UDP.endPacket();
  } else {
    delay(1000);
  }
}
```
以上
イントラネットで地図サービスを使いたい1-概要編-

#概要
　WebGisを作ろうとして参考となるサイトが少なかったので、自分で調べたこととか顛末を備忘録としてQiitaの勉強がてら綴る。

初投稿：2019/04/09
最終更新：2019/05/18

#紙地図はあるけど…
　たびたび地図を使う機会があるのだが、大きな紙地図をまいど机に広げており、デジタル世代の自分としてはやり辛い。
　幸いなことに、一人一台、作業用のパソコンがあったので、社内向けサイトを任せれていたこともあり、GoogleMapのようなものを自作できないかと着手した。

#地図サービスって？
　さて、いざつくることにしたが、昔C++を多少齧って、htmlとcssを独学でちょっと勉強した程度の能力しかないので、とりあえずGoogle先生に聞く。
「地図サイト 自作」と調べてみると、出てくるのはAPIとかアプリとかとかやりたいこととは違うものばかり……
　なので、まずは地図サービスの正式な名称を調べたところ、
**WebGis(GeographicInformationSystem)**
というらしい。
　今度は「webGis自作」で調べてみると、有料のソフトウェアとかが出てくるなか、それっぽいものが……

#LeafletとOpenLayers
　フリーのWeb地図サービスとして、下記のものを見つけた。
・<a href="https://ja.m.wikipedia.org/wiki/Leaflet">Leaflet</a>
・<a href="https://ja.m.wikipedia.org/wiki/OpenLayers">OpenLayers</a>
　結論から言えば、イントラネットにおいて、デフォルトの地図、シンボルやポリゴンの表示はできたものの挫折した。

**挫折した原因**
・導入可能なフリーの地図画像がない。
・必要な機能を付加する技能がない。

#界隈の人を探す
　挫折してひと月、やはり導入を諦めきれず。情報収集のためTwitterで地図界隈の人が居ないか調べたところ、とある方に行きついた。
**<a href="https://twitter.com/ktgis?s=09">谷　謙二さん</a>**
・埼玉大学 人文地理学教員
・MANDARA(GISソフト)の開発・提供
・Web地図サービスの開発・提供
詳しくは<a href="http://ktgis.net">コチラ</a>

　一度挫折し、出来たらラッキーくらいの軽い気持ちで見ていると、Google、yahoo!、bingといったよく目にする地図とは異なる地図を知った。

##その名は地理院地図
百聞は一見にしかず。実際に見て欲しい。
・**<a href="https://maps.gsi.go.jp">地理院地図</a>**
その名の通り、地理院が提供している地図サービスである。
　地理院ってなんなの？というと、ざっくりいえば、国土交通省に置かれている日本国内の地図を作る公的機関で、正式名称を<a href="https://ja.m.wikipedia.org/wiki/国土地理院">国土地理院</a>という。

#なぜ地理院地図を？
　話は戻る。地理院地図を知ったわけだが、そこで、なぜ、個人が製作したWebGisで地理院地図が利用されているのかという疑問が浮かんだ。
　 というのも、挫折した一因となった地図画像は、GoogleやYahooなどの地図は使用に著作権上の問題があったからだ。
　もし、地理院地図の画像を利用できれば、技術上の問題だけなので、クリアできるのでは、と、いうわけで地理院地図の利用規約を調べてみることに……

#地図画像の利用
　さて、ここから小難しい話になる。
「**法令**」についてである。
　地図画像について「**<a href="http://www.gsi.go.jp/LAW/2930-index.html">測量法</a>**」と「**<a href="http://www.gsi.go.jp/kikakuchousei/kikakuchousei40182.html">地理院コンテンツ利用規約</a>**」に基づいた手続きを行えば、**利用できる**らしい。
　さて、地理院地図に使われている地図画像だが、正式には「**<a href="https://maps.gsi.go.jp/development/ichiran.html">地理院タイル</a>**」といい、さらに、地理院タイルは「**基本成果**」と「**基本成果以外**」にわけられる。今回、使用したいのは基本成果なので、そちらについて地理院に問い合わせた結果を書く。

**地理院に問い合わせた結果**
・「社内、サークル、同好会等」に含まれ「電子地形図をGISの背景図等に利用」は測量成果の複製に該当するため申請不要
・「国土地理院コンテンツ利用規約」が適用され、これに従った出典を明示のうえ使用
・独自情報の追加は可能
　むしろ国土地理院の測量成果は独自情報を付加して利用することを想定

※場合によって、申請が必要なので、利用する場合、問い合わせることを強く推奨する。

#政府のオープンソース施策
　上記の地理院タイルの利用手続きを調べていた最中、政府がオープンソース施策というものを進めており、なんと、<a href="https://github.com/gsi-cyberjapan/gsimaps">地理院地図のソースコード</a>がGithubで公開されていた。
　leafletベースで作成されているようで、今後はこれを使ってイントラネットにWebGisを導入していく。

#WebGisをつくる
素材が揃ったので、オープンソースをもとに導入していくが、詳細についてはまた、<a href="https://qiita.com/notmushroomnot/items/2e7cb89ad623ca6edf9f">別に記事</a>をつくる。
H2 database Engineにおけるテストデータの準備等

■Autowiredされる側のクラスに設定するには？
@Componentを追加し、このクラスをDIコンテナに登録してくれと印をつける必要がある。


■Spring Bootではクラスパス直下にSQLファイルを配置することで自動的に読み込む。
「src/main/resoures」
DDL : schema.sql
DML : data.sql

■InMemoryとFileの違いって何

どちらもメモリ上にDBを作成し、JDBCを通してデータにアクセスする点は同じ。
ファイルの場合はアプリケーション起動時にデータベースに相当するファイルを作成する。(永続化する。)
インメモリの場合はファイルを作成せず、アプリケーション終了と同時にデータは破棄される。(永続化しない。)

【ファイル】
jdbc:h2:./testXX
jdbc:h2:file:./testXX

【インメモリ】
jdbc:h2:mem:testXX

■組み込みにおけるJDBC接続指定子
http://h2database.com/html/features.html#database_url

■毎回schema.sqlを実行した場合、すでにあるテーブルを作成しようとするが
定義済みのため例外が発生する。
それを回避するには
「CREATE TABLE」ではなく「CREATE TABLE IF NOT EXISTS」を用いる。

[例外メッセージ] 
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: テーブル "CUSTOMER" はすでに存在します



■単体テストを実施するにあたっての使い分け
ファイルの場合、単体テスト実施前後で状態が変わってしまうため、
テストの再現性が保てない。

インメモリの場合、毎回１からスキーマ、データを作成するため、
再現性は保てるが、規模が大きいと時間がかかる。

インメモリかつテーブルを絞り込む方法もあるそうなのでよかったら調べること。

■互換モード
H2では各サードパーティ製のDB固有の仕様を再現することができる。
(例. Oracle : jdbc:h2:{接続子};MODE=Oracle)
  ⇒ 空白文字列はNullとして扱われる。
  
本番で使用するDBをあらかじめ設定することで
H2 -> 本番DBへ変更した際の変化により発生する問題を事前に防ぐことができる。
gulpを使ってphpunitを自動化したときにハマったこと

# 概要
vim使いながらもphpの開発を効率化したい！
コード修正してphpunitを動かすのが、ダルいなぁーと思って、gulpを使って自動化してみました。

# 要件
開発しながら、動的に何回でもテストが実行される環境を作りたい。

# 今回躓いた点
なぜか一度phpunitが実行されると、2回目以降phpunitが実行されない。
gulp-plumberを使ったりする記事は見かけて試したりはしてみたのですが、
うまくいかず。。。
きっともっと良い解決策があるかもなのですが、同じような問題で躓いた方がいたらと思い、
投稿させていただきます。

# 環境
```
php -version
PHP 7.1.23 (cli) (built: Nov  7 2018 18:20:35) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies

node --version
v11.12.0
```

## 準備
### 必要なmodule入れる
```
npm i --save gulp gulp-notify gulp-phpunit
```

## gulpfile.jsを書く
```
'use strict';
var gulp = require('gulp');
var notify = require('gulp-notify');
var phpunit = require('gulp-phpunit');

gulp.task("test",function(){
    gulp.src('tests/*.php')
        .pipe(phpunit('vendor/bin/phpunit'))
        .on('error', notify.onError({
            title: "Gulp PHP Unit",
            message: "Error(s) occurred during testing..."
        }))
        .pipe(notify({
            title: "Gulp PHP Unit",
            message: 'Successfully ran test!'
        }));
});

gulp.task('watch',function(){
    gulp.watch(['src/**/*.php', 'tests/**/*.php'], gulp.task('test'));
});
```

## 実行
```
gulp watch
```

## 結果
画質荒くてすみません。。。(テストコードを書き換えたときにphpunitが動くことを確認しています)
![gulp-once.gif](https://qiita-image-store.s3.amazonaws.com/0/57545/f5d4496e-c3a6-94b3-87ce-eaed7298b988.gif)

## 問題点
**一回テスト実行するとそこで止まってしまう。。。**
これだと、やりたいこととは違うんだ。。。
やりたいのは、開発しながら、何回でもphpunitを実行してくれる感じ。


# 解決策
**chokidarを使う**
です。

## chokidarのinstall
```
npm i --save chokidar
```

## gulpfile.jsの修正
```
'use strict';
var gulp = require('gulp');
var chokidar = require('chokidar');
var notify = require('gulp-notify');
var phpunit = require('gulp-phpunit');

var watcher = chokidar.watch(['src/**/*.php', 'tests/*.php']);

watcher.on('change', function(){
    gulp.src('tests/*.php')
        .pipe(phpunit('vendor/bin/phpunit'))
        .on('error', notify.onError({
            title: "Gulp PHP Unit",
            message: "Error(s) occurred during testing..."
        }))
        .pipe(notify({
            title: "Gulp PHP Unit",
            message: 'Successfully ran test!'
        }));
});
```

## 実行
```
node gulpfile.js
```

## 結果
2回目以降の修正でもちゃんとphpunitが実行されるようになった！
![gulp-chokidar.gif](https://qiita-image-store.s3.amazonaws.com/0/57545/b6415e88-5798-3608-1123-d470ae2a01a7.gif)


# github
下記のリポジトリにソースを載せています。
[phpunit-gulp](https://github.com/sk8metal/phpunit-gulp)

phpのコードとテストコードは、sampleとして下記のコードを使っています。
[phpunit](https://phpunit.de/getting-started/phpunit-7.html)

# 参考資料
[phperだってgulp使おうぜ！](http://blog.comnect.jp.net/blog/115)
[gulp](https://gulpjs.com/)
[chokidar](https://github.com/paulmillr/chokidar)
RISC-V ISA モジュールについて

# ベースISA

* RV32I (RISC-V 基本32ビット整数ISA)
* RV32E (RISC-V 組込み向け縮小レジスタISA)
* RV64I (RISC-V 64ビットアドレス命令ISA)
* RV128I

# 標準拡張機能

* M (乗算・除算標準拡張機能)
* A (アトミック命令標準拡張機能)
* F (単精度浮動小数点数標準拡張機能)
* D (倍精度浮動小数点数標準拡張機能)
* Q (4倍精度浮動小数点数標準拡張機能)
* L (10進浮動小数点数標準拡張機能)
* C (圧縮命令標準拡張機能)
* B (ビット操作標準拡張機能)
* J (動的翻訳言語サポート標準拡張機能)
* T (トランザクションメモリサポート標準拡張機能)
* P (パック形式SIMD命令標準拡張機能)
* V (ベクトル演算標準拡張機能)
* N (ユーザーレベル割込標準拡張機能)

# 特権アーキテクチャ

* マシンレベルISA
* 特権レベルISA

# 特権モジュール

* H (ハイパーバイザ特権モジュール)

# たくさんISAとモジュールがありますが...

初学者は基本の RV32I を押さえましょう。
MateriApps LIVE!ことはじめ

# MateriApps LIVE!
物質科学シミュレーションのポータルサイト[MateriApps](https://ma.issp.u-tokyo.ac.jp/)に掲載されているいくつかのアプリや関連するアプリがプリインストールされた環境。
[MateriApps LIVE!](https://cmsi.github.io/MateriAppsLive/)
関連しそうなライブラリ群も入っているので、アプリを自分でビルドするときも障害が少ない。
例えばVirtualBox仮想ハードディスクイメージ(OVA)をダウンロードすると、VirtualBox上でこうした環境を準備できる。

ここでは、MateriApps LIVE!を使った計算というよりは、そこに至るまでの環境まわりの一般的な話をまとめる。
そもそも、FAQについて、公式の[FAQ · cmsi/MateriAppsLive Wiki · GitHub](https://github.com/cmsi/MateriAppsLive/wiki/FAQ)を見ておいた方が良いかも。

## アカウントの情報
最初のログイン、画面がロックされて解除するときに必要。
ユーザー名：user
パスワード：live
[Using MateriApps LIVE! on VirtualBox · cmsi/MateriAppsLive Wiki · GitHub](https://github.com/cmsi/MateriAppsLive/wiki/Using-MateriApps-LIVE!-on-VirtualBox)

# トラブルシューティング
## 日本語のキーボードがうまいこと認識されていない
自分の環境(MateriApps LIVE1 2.2, VirtualBox 5.2.26, Windows Surface Pro 日本語キーボード)では、接続してある日本語キーボードが英語キーボードとして認識されていた。

MateriApps LIVE!のOSはDebianなので、このOSでのキーボードの変更方法を調べればよい。
例えば、[Debianで利用するキーボードの種類を変更する - memo.xight.org](https://memo.xight.org/2013-05-12-1)が参考になる。
変更を反映させるにはrebootが必要だった。

それと、MatriAppsLiveのWikiに情報がある：[FAQ · cmsi/MateriAppsLive Wiki · GitHub](https://github.com/cmsi/MateriAppsLive/wiki/FAQ#keyboard)

## 高解像度ディスプレイで表示が細かすぎる
MateriApps LIVE!の話ではなくて、多分一般にVirtualBoxを使った時のゲストOSの表示がデフォルト設定では画面の解像度をそのまま参照していることが理由。
自分の環境(VirtualBox 5.2.26, Windows Surface Pro)では、2736x1824のディスプレイを200%に拡大して使用している。

terminalやブラウザの表示を個別に大きくしても見えるようにはなるが、メニューは大きくならないし、そうして表示倍率を指定できるアプリがすべてではないので、根本的に解決したほうが良い。
ゲストOSをシャットダウンしている状況で、設定の項目からディスプレイを選び、表示倍率を変更する。
多分Windowsで使っている倍率と同じものでよいはず。
自分の環境では200%で、ちょうどいい感じになった。
参考にしたさいと: [その他　Windows上のVirtualBoxで解像度とマルチモニタの設定の仕方](https://www.oborodukiyo.info/etc/2016/ETC-MultiMonitorOnVirtualBox)
raspbian(rpi0w)にpostfixを入れて、gmail経由でメール送信する

# 自宅サーバからアラートメールを出したいので、gmailを送信サーバとして利用し、外部（プロバイダ）宛にメールを出す。

[gmailで送信](http://obel.hatenablog.jp/entry/20131217/1387243447)
[gmailで安全性の低いアプリを許可する](https://support.google.com/accounts/answer/6010255)

## install
```
sudo apt-get install postfix
sudo apt-get install mailutils
sudo apt-get install sasl2-bin libsasl2-modules
```
## saslauthd
> vi /etc/default/saslauthd

```
START=yes
```


## configuration-postfix
> vi /etc/postfix/main.cf 

```
myhostname = xxxx.yourdomaim     # アラートを出すサーバ
mydomain = yourdomain
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = $myhostname, xxxx, localhost.localdomain, localhost.$mydomain    # このあて先には、ローカルメールとして出す
mynetworks = 127.0.0.0/8 192.168.0.0/24  # NWアドレスは適宜変更
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = ipv4
# default_transport = error
# relay_transport = error
home_mailbox = Maildir/  # ローカルメールの配信先ディレクトリ

relayhost = [smtp.gmail.com]:587  # gmail経由で送信、送信サーバ
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = $myhostname
smtpd_relay_restrictions =
 permit_mynetworks
 permit_sasl_authenticated
 defer_unauth_destination

smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_sasl_tls_security_options = noanonymous
smtp_sasl_mechanism_filter = plain
#tls setting
smtp_use_tls = yes
```

> vi /etc/postfix/master.cf

```
smtp       inet  n       -       y       -       -       smtpd
#smtp      inet  n       -       y       -       1       postscreen
#smtpd     pass  -       -       y       -       -       smtpd
#dnsblog   unix  -       -       y       -       0       dnsblog
#tlsproxy  unix  -       -       y       -       0       tlsproxy
submission inet n       -       y       -       -       smtpd  # コメント削除
#  -o syslog_name=postfix/submission
#  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes  # コメントを削除
```

> vi ~/.profile

```
export MAIL=$HOME/Maildir
```

## sasl_passwd

> vi  /etc/postfix/sasl_passwd

GmailのIDとパスワードを設定

```
[smtp.gmail.com]:587 yyyy@gmail.com:yyyyyyyyyy
```
設定を更新したら、DBも更新

```
postmap hash:/etc/postfix/sasl_passwd
```
## aliases

> vi /etc/aliases

```
alias:  yyy@gmail.com
```

設定を更新したら、DBも更新

```
newaliases 
```

## postfix mail command
### 送信
```
## alias指定でメール
echo “test mail” | mail alias
 hogehoge
 foo foo
.
EOT(Ctrl+d)

## アドレス指定でメール
echo “test mail” | mail yyyy@gmail.com
 hogehoge
 foo foo
.
EOT(Ctrl+d)
```

### 受信
> vi /etc/skel/.bash_profile

```
export MAIL=$HOME/Maildir
```

### mail client
```
 $ mail
 > nn       nnのメールを読む
 > d nn     nnのメールを削除
 > d *      ワイルドカード
```

## queue操作
| want to do | command |
| --- | --- |
| キューの確認 | postqueue -p |
| | mailq |
| キュー削除 | postsuper -d キューID |
| | postsuper -d ALL |
| 強制配信 | postfix flush |
Excel VBAコース第1回内容

全12回 Excel VBAコースの第1回の内容です。

#マクロボタンの作成
・ボタン作成の仕方
・メッセージボックス(MsgBox)
#セルの値の取得・入力
・CellsとRange
#四則演算
・＋ － × ÷
・割り算の際、整数部分のみ出すのは「¥」、余りのみ出すのは「Mod」

#文字列連結
・文字列を連結する場合は「&」でつなげる

#デバッグ
・エラーが出るとデバッグモード(エラーになっている場所を探すモード)になる
・中断するには上のメニューの「□」を押す
UISegmentedControlの色をStoryBoardから変更する

##環境
swift4
xcode10.1

##やること
UISegmentedControlの背景色をStoryBoardから変更してみる。
<img width="160" alt="スクリーンショット 2019-04-09 0.43.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/394812/8cae229c-32a1-4d62-3195-d5a1e97ceabe.png">
こんなもの作る場合ですね。

##流れ
1.UISegmentedControlを継承したクラスの作成
2.作成したクラスにIBInspectableに背景色を設定するプロパティを設定
3.StoryBoardでUISegmentedControlを作成し、1のクラスを設定
4.2のプロパティにカラーを設定

###1.UISegmentedControlを継承したクラスの作成

こちらのリンクを参考にクラスを作成します。
https://qiita.com/son_s/items/7ca2acf690d10f9fd1b7

```swift:DesignableSegment.swift
@IBDesignable
class DesignableSegment: UISegmentedControl {
}
```

###2.作成したクラスにIBInspectableに背景色を設定するプロパティを設定
UISegmentedControlにIBInspectableを設定し、
その中でカラーを変更します。
先程のコードにIBInspectableを追加します。

```swift:DesignableSegment.swift
@IBDesignable
class DesignableSegment: UISegmentedControl {
    @IBInspectable internal var segmentColor: UIColor? {
        didSet {
            self.tintColor = segmentColor
            self.backgroundColor = UIColor.white
            self.layer.cornerRadius = 4
        }
    }
}
```

###3.StoryBoardでUISegmentedControlを作成し、1のクラスを設定
<img width="255" alt="スクリーンショット 2019-04-09 0.35.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/394812/8c0e6d8d-c0b7-06b8-9f20-794fcbebe7f4.png">

###4.2のプロパティにカラーを設定
<img width="260" alt="スクリーンショット 2019-04-09 0.35.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/394812/8c2f913b-ef8d-a7c6-f389-5995310ed697.png">

これで実行すればSegmentedControlの色を変更できます。

##おまけ
ユースケースとして、StoryBoardからだけでなく、ソースコードからもカラーを変更したくなるかもしれません。
そんな時はviewDidLoadあたりでsegmentColorに直接カラーをぶち込んで下さい。
そんなの当たり前だよと突っ込まれそうですが。。。


```swift:omake.swift
override func viewDidLoad() {
        super.viewDidLoad()
        segmentV.segmentColor = .red
    }
```
クラス・インスタンス・プロパティの理解覚書

<br>
##理解・確認のための覚書
PHPのオブジェクト・クラス・インスタンスの考え方を整理したので記します。
何度も確認して刷り込む用です。


```php:

class Menu {
    public $name;
    public $price;
}

$soup = new Menu();
```

上記のように新しいインスタンスが生成されたときのインスタンスの中身（イメージ補助）

```php:

$soup = Menu {
    public $name;
    public $price;
}
//インスタンスはクラス（設計図）をトレースして作られる
```
プロパティに値を代入したりするときは、`インスタンスを代入した変数->値を代入したいプロパティ名 = 代入するもの`でセットできる。

```php

//プロパティ '$name'に'SOUP'を代入

$soup->name = 'SOUP';
//$soupに入れられたMenuインスタンスの中のプロパティ$nameにアクセスして'SOUP'をセット
```
Macでcommandキーとoptionキーを入れ替える

#[commandキーとoptionキーの入れ替え方]
Macでemacsを使いたかったので、commandキーとoptionキーの入れ替えをした。
##karabinerを使用する
1.[karabiner](https://pqrs.org/osx/karabiner/)をインストール
2.以下の設定をする
<img width="1112" alt="スクリーンショット 2019-04-09 0.30.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/391196/fb3ee7e8-53bf-2c0f-8732-bae1e184de97.png">

※ターミナルでのみ変更したいときは以下の参考記事のやり方が良いと思います。

##参考記事
[MacでEmacsを使うときにCommandキーとOptionキーを入れ替える](https://qiita.com/usobuku/items/39342e2a4137dde894b4)

[Karabiner-Elementsで、MacのTerminalでoptionとcommandを入れ替え・自由にキーバインド変更をする例]
(https://qiita.com/peutes/items/4e20b48185b24bf06a8f)

##emacsのみで入れ替えようとしたが
以下の設定を試してみたが、反映されず、結局karabinerで設定・・・。
通常のコピペとか少しやりずらい。

```
(setq ns-command-modifier (quote meta))                                                                                             
(setq ns-alternate-modifier (quote meta))                                                                                           
(setq mac-command-modifier 'meta)                                                                                                   
(setq mac-option-modifier 'alt)      
```
RISC-V(リスク・ファイブ)について学ぶ意義

# はじめに

RISC-V(リスク・ファイブ) というインストラクション・セット・アーキテクチャ(ISA)は，知る人ぞ知るという感じで，最近急速に注目を集めています。え，聞いたことないですか？ そうですか。。。

ISA といえばx86とかARMとかが有名で，これらがデファクトスタンダード(事実上の標準)みたいな感じになっている中で，なぜ RISC-V なんていう，聞いたこともないようなISA について，わざわざこれから学ぶ必要があるんでしょう？

実は，私，RISC-Vの噂を聞きつけて，[RISC-V原典](https://amzn.to/2KfK5Ox)を読んで，軽く感動を覚えたんですよね！ この記事では私がなぜ RISC-V に対して感動を覚えたのかについて紹介することで，RISC-Vについて学ぶ意義について語ってみたいと思います。

# 感動理由その1: なぜこのように設計したのか，理由や意図が明示されているから

[RISC-V原典](https://amzn.to/2KfK5Ox)を読んでいくと，設計の概要から詳細まで1つ1つていねいに「なぜこのように設計したのか」理由や意図が明快に説明されていることにまず感動を覚えます。

それもそのはずです。[「RISC-V原典 (原書: RISC-V Reader)」](https://amzn.to/2KfK5Ox) の著者は，David Patterson と Andrew Waterman です。David Patterson という名前を聞いてピンときた人がいるかもしれませんが，CPUの仕組みについて学ぶ名著中の名著，いわゆる[「パタヘネ本」こと「コンピュータの構成と設計 (原書: Computer Organization and Design)」](https://amzn.to/2UoPdVd)の著者の1人なのです。

ちなみに「パタヘネ本」の由来は，Patterson & Hennesy の略ですね。ちなみに同じ著者で順番が逆になっている[「ヘネパタ本」こと「コンピュータアーキテクチャ定量的アプローチ(原書: Computer Architecture: Quantitative Approach)」という書籍もあります。こちらも名著中の名著です。

なお，RISC-V の研究開発を主導しているのは，Krste Asanović です。[RISC-V原典](https://amzn.to/2KfK5Ox)の帯にデカデカと「チューリング賞受賞パターソン教授 RISC研究40年の総決算 待望の邦訳！」とか書かれているので，つい私も Patterson 先生が RISC-V の生みの親かと誤解したのですが，実際には異なります。Patterson 先生もそのような誤解を受けていることを承知の上で RISC-V の広告塔の役割を担っているようです。

# 感動理由その2: ISAがシンプルなので

RISC-VはとてもシンプルなISAです。[RISC-V原典](https://amzn.to/2KfK5Ox)によると，RISC-V の ISA マニュアルと比べて，ARM-32は11倍以上，x86-32に至っては28倍以上もの語数があるそうです。ちなみに x86-64 はさらに巨大です。

全ての拡張機能を含む RISC-V ISA の要約は，なんとたったの2ページに収まります！[RISC-V原典](https://amzn.to/2KfK5Ox)の冒頭に「RISC-Vリファレンスカード」として表裏2ページに要約が掲載されています。

ISAがシンプルだと，プロセッサのサイズが小さくなり，性能も向上させやすくなります。また命令も追加しやすいです。

# 感動理由その3: なんとオープンソース！太っ腹！

x86 アーキテクチャは基本的に Intel のもので，勝手に使うことができません。AMD は Intel とクロスライセンスを締結することで利用権を得ています。

ARM も同様に Arm ホールディングスのもので，勝手に使うことができません。

しかし，RISC-V の ISA はオープンソースで，しかもBSDライセンスというゆるいライセンスで公開されています。RISC-V の実装も同様にオープンソースとして公開されているものがあります。ISAがBSDライセンスなので，商用ライセンスにしてもOKで，実際商用ライセンスの RISC-V 実装も多く存在します。

公開されている ISA やオープンソース実装をもとに，教育や研究を自由に行うことができ，それをもとにビジネスをすることも自由です。

RISC-V の仕様は RISC-V Foundation のもとで，科学的・民主的なプロセスを経て策定されます。これも理想的です。独自仕様を定義するための仕様も策定されています。

* [RISC-Vの仕様についてはこちら](https://riscv.org/specifications/)
* [RISC-Vの実装についてはこちら](https://riscv.org/risc-v-cores/)

# 感動理由その4: ツールが充実しているから

RISC-Vは，オープンソースであるという利点を備えているため，数多くの優れたオープンソースソフトウェアが RISC-V に対応しているので，とてもツールが充実しています。

* [RISC-Vのツール群についてはこちら](https://riscv.org/software-status/)

# おわりに

命令を追加しやすく，オープンソースかつツールが充実しているということは，独自の改造を施したCPUを提案し，それに対応した機械語コードを生成するプログラミング言語処理系を開発することも可能だということです。これは熱いですね！

こういう理由で，RISC-Vは教育にも研究にも向いています。RISC-Vに対応した，コンピュータアーキテクチャの書籍も充実しています(洋書ですけど)。

* [Computer Organization and Design RISC-V Edition: The Hardware Software Interface](https://amzn.to/2G7qUSW): パタヘネ本の最新刊の RISC-V 版です。
* [Computer Architecture, Sixth Edition: A Quantitative Approach](https://amzn.to/2Uoc978): ヘネパタ本の最新刊で RISC-V についても言及されています。
Google App Engine へのカスタムドメイン設定(Google Domains)

# 前提
・Google Domains でドメインを取得済
・Google App EngineでWebサービス等を公開中

# 設定方法
## GCPプロジェクト
### App Engine > 設定 > カスタムドメイン > カスタムドメインを追加
![スクリーンショット 2019-04-09 0.04.06.png](https://qiita-image-store.s3.amazonaws.com/0/32691/c9511cb8-d01a-04dd-c26b-71538e79a7c9.png)

### 使用するドメインを選択する
　使用したいドメインを選択して「続行」を押下。
　すでにGoogle Domainsでドメイン取得済であれば、選択できるようになっているはず。

### ドメインを【ProjectName】に指定する
　サブドメインを入れる場合は、追加してから「マッピングを保存」を押下。

### DNSレコード更新してセキュリティを有効化する
![スクリーンショット 2019-04-09 0.04.32.png](https://qiita-image-store.s3.amazonaws.com/0/32691/8c45d7c2-405c-5fd0-3bea-a35f207c1edc.png)
　DNSレコードが表示されたら、「完了」を押下。
　以下のように表示されていればOK
![スクリーンショット 2019-04-09 0.05.44.png](https://qiita-image-store.s3.amazonaws.com/0/32691/a84514bc-e66f-b511-ee8d-fb7481f6e10c.png)


## Google Domains
### Google Domains にアクセス
https://domains.google.com/m/registrar/

### 上で設定したマイドメインの「管理」を選択
![スクリーンショット 2019-04-09 0.09.16.png](https://qiita-image-store.s3.amazonaws.com/0/32691/83506e40-a6d4-847f-f35b-1cab9b72ca34.png)

### サイドメニューからDNSを選択し、下部のカスタムリソースレコードを設定
 設定する項目は上記のApp Engineの設定で表示されたレコードの内容。
 以下のように設定。時間が経てばアクセスできるようになるはず。
![スクリーンショット 2019-04-09 0.10.02.png](https://qiita-image-store.s3.amazonaws.com/0/32691/70dc2d50-5447-6983-833e-55ff28cc9e05.png)

リソースレコードの設定方法は、Googleが丁寧に書いてくれている。
https://support.google.com/domains/answer/3290350?hl=ja

以上
【GAE】PHP7を拡張してカスタムランタイムをデプロイする


## 前提

 - GAE PHP72 runtimeで動いているLaravelアプリケーションが存在する

[ffmpeg](https://ffmpeg.org/) を利用して動画から静止画を作成し、
[Cloud Vision API](https://cloud.google.com/vision/docs/libraries?hl=ja#client-libraries-install-php)で解析を行うための環境を作ろうと思います。

## ランタイムの拡張

プロジェクトのディレクトリで下記のコマンドを実行してベースとなるapp.yaml, Dockerfileを作成します
`gcloud beta app gen-config --custom`

ベースを元に設定を追加します
### app.yaml

```yaml
runtime: custom
env: flex

runtime_config:
  document_root: public

# Ensure we skip ".env", which is only for local development
skip_files:
  - .env

env_variables:
  # Put production environment variables here.
  APP_LOG: errorlog
  WHITELIST_FUNCTIONS: proc_open,proc_close

automatic_scaling:     # add
  min_num_instances: 1 # add
  max_num_instances: 1 # add
```

### Dockerfile

```
# Dockerfile extending the generic PHP image with application files for a
# single application.
FROM gcr.io/google-appengine/php:latest

## FFMpeg Dependency
RUN apt-get update -qq && apt-get -y install \
  autoconf \
  automake \
  build-essential \
  cmake \
  git-core \
  libass-dev \
  libfreetype6-dev \
  libsdl2-dev \
  libtool \
  libva-dev \
  libvdpau-dev \
  libvorbis-dev \
  libxcb1-dev \
  libxcb-shm0-dev \
  libxcb-xfixes0-dev \
  pkg-config \
  texinfo \
  wget \
  zlib1g-dev

RUN apt-get update -y && apt-get install -y \
        vim \
        unzip \
        zip \
        zlib1g-dev \
        ffmpeg

# The Docker image will configure the document root according to this
# environment variable.
ENV DOCUMENT_ROOT /app/public
```

基本的にffmpegなどのミドルウェアをインストールしたい場合には
PHP用のベースイメージを元に拡張してあげれば環境を作ることができます

```
FROM gcr.io/google-appengine/php:latest
```

ローカル環境として立ち上げる場合にはコンテナの8080portが開いているので
好きなホストのportと繋ぐといいと思います
$_POST['foo']とfilter_input(INPUT_POST, 'foo')の違い

今更ながら知ったので書く。

```php:sample.php
$foo1 = $_POST['foo'] ?? null;
$foo2 = filter_input(INPUT_POST, 'foo');
```
の違いがわかってませんでした。

```haml
<from action="sample.php" method="post">
  <input type="hidden" name="foo" value="foo">
  <input type="submit">
</form>
```
上記をsubmitすると

```php:sample.php
<?php
$foo1 = $_POST['foo'] ?? null;
$foo2 = filter_input(INPUT_POST, 'foo');

var_dump($foo1);
// string(3) "foo"
var_dump($foo2);
// string(3) "foo"
```
どちらも結果は同じ

```php:sample.php
<?php
$_POST['foo'] = 'bar';    // $_POSTの値を書き換える
$foo1 = $_POST['foo'] ?? null;
$foo2 = filter_input(INPUT_POST, 'foo');

var_dump($foo1);
// string(3) "bar"
var_dump($foo2);
// string(3) "foo"
```

\$\_POSTの値を直接書き換えると結果が変わった。
filter_input()はHTTPボディから参照しているっぽい。
$_POST書き換えるなよって話しですが、（書き換えたことあります。ごめんなさい。）

#気になったこと
https://www.php.net/manual/ja/function.filter-input.php
>返り値 
成功した場合は要求された変数の値、フィルタリングに失敗した場合に FALSE、 あるいは変数 variable_name が設定されていない場合に NULL を返します。フラグ FILTER_NULL_ON_FAILURE が指定されている場合は、変数が設定されていなければ FALSE、 フィルタリングに失敗したら NULL を返します。

返り値のfalseってなに。
変数が設定されてない場合はnullじゃないの。

```html
<input type="hidden" name="foo[]" value="hoge">
<input type="hidden" name="foo[]" value="fuga">
```

```php:sample.php
<?php
$foo1 = $_POST['foo'] ?? null;
$foo2 = filter_input(INPUT_POST, 'foo');

var_dump($foo1);
// array(2) { [0]=> string(4) "hoge" [1]=> string(4) "fuga" }
var_dump($foo2);
// bool(false)
```
配列を渡すとfalseが帰ってくる。

#配列の受け取り
```php:sample.php
<?php
$foo2 = filter_input(INPUT_POST, 'foo', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
var_dump($foo2);    // array(2) { [0]=> string(4) "hoge" [1]=> string(4) "fuga" }
```

第４引数にFILTER_REQUIRE_ARRAYを指定すると配列を受け取れる。

#オプションとかで色々指定できるっぽい
```html
<input type="hidden" name="foo" value="30">
```

```php:sample.php
<?php
$foo1 = $_POST['foo'] ?? null;
$foo2 = filter_input(INPUT_POST, 'foo', FILTER_VALIDATE_INT, [
            "options" => [
                "max_range" => 20,
                "min_range" => 10
            ]
        ]);

var_dump($foo1);   // string(2) "30"
var_dump($foo2);   // bool(false)
```
この場合もfalseが帰ってくる。
Embulk × Digdag on Docker

```dockerfile:Dockerfile
FROM centos:latest

WORKDIR /embulk_digdag

# java
RUN yum update -y && yum install -y \
      java-1.8.9-openjdk \
      java-1.8.0-openjdk-devel \
      vim

ENV TD_API_KEY='td_api_key' \
    AWS_ACCESS_KEY_ID='aws_access_key' \
    AWS_SECRET_ACCESS_KEY='aws_secret_access_key'

# treasure data toolbelt
RUN curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent2.sh | sed -e "s/sudo//g" | /bin/bash && \
    td apikey:set $TD_API_KEY

# embulk
RUN curl --create-dirs -o ~/.embulk/bin/embulk -L "https://dl.embulk.org/embulk-latest.jar" &&\
    chmod +x ~/.embulk/bin/embulk && \
    echo 'export PATH="$HOME/.embulk/bin:$PATH"' >> ~/.bashrc && \
    source ~/.bashrc && \
    embulk gem install embulk-input-mysql embulk-output-td embulk-input-s3 embulk-filter-column embulk-filter-add_time

# digdag
RUN curl -o ~/bin/digdag --create-dirs -L "https://dl.digdag.io/digdag-latest" && \
    chmod +x ~/bin/digdag && \
    echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc && \
    source ~/.bashrc && \
    mkdir -p ~/.config/digdag; touch ~/.config/digdag/config && \
    echo "client.http.endpoint = https://digdag.サーバー名.com" >> ~/.config/digdag/config

# digdag path
ENV PATH /root/bin:${PATH}

# aws cli
RUN set -xv && \
    curl -s "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py" && \
    python get-pip.py && \
    pip install awscli --ignore-installed six && \
    curl -s -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | sh && \
    source ~/.nvm/nvm.sh && \
    nvm install v6.10.3 && \
    npm install -g jsonlint && \
    npm install -g jq

RUN digdag secrets --local --set td.apikey=${TD_API_KEY} && \
    digdag secrets --local --set aws.access_key_id=${AWS_ACCESS_KEY_ID} && \
    digdag secrets --local --set aws.secret_access_key=${AWS_SECRET_ACCESS_KEY}

```

```:docker-compose.yml
version: '3'
services:
  app:
    build: .
    volumes:
      - .:/embulk_digdag
    tty: true
    environment:
      TZ: Asia/Tokyo
```

```
# docker-compose up -d
docker exec -it コンテナID /bin/bash
# embulk --version
embulk 0.9.17
# digdag --version
0.9.35
# aws --version
aws-cli/1.16.140 Python/2.7.5 Linux/4.9.125-linuxkit botocore/1.12.130
```
【GAE】PHP7ランタイムでBasic認証を設定する


## 環境

 - GAE PHP72 runtime
 - Laravel 5.8.7

## インストール

基本的にREADMEの内容を設定するだけでBasic認証が有効になります。

[l5-very-basic-auth](https://github.com/olssonm/l5-very-basic-auth)

`composer require olssonm/l5-very-basic-auth:5.*`


## 設定

設定ファイルを作成する

```bash
$ php artisan vendor:publish --provider="Olssonm\VeryBasicAuth\VeryBasicAuthServiceProvider"
Copied File [/vendor/olssonm/l5-very-basic-auth/src/config.php] To [/config/very_basic_auth.php]
Publishing complete.
```

ユーザとパスワードを設定する
`config/very_basic_auth.php`

user, passwordのキーがそれぞれユーザとパスワードに紐づいているので
設定したい値に変更します。
今回は全環境でBasic認証を適用していますが
特定の環境のみ認証必須にしたければenvsキーを変更することで対応が可能です。

```php
<?php

    /**
     * Configuration for the "HTTP Very Basic Auth"-middleware
     */
    return [
        // Username
        'user'              => 'admin',

        // Password
        'password'          => 'aGnXaX9k',

        // Environments where the middleware is active. Use "*" to protect all envs
        'envs'              => [
            '*'
        ],

        // Message to display if the user "opts out"/clicks "cancel"
        'error_message'     => 'You have to supply your credentials to access this resource.',

        // Message to display in the auth dialiog in some browsers (mainly Internet Explorer).
        // Realm is also used to define a "space" that should share credentials.
        'realm'             => 'Basic Auth',

        // If you prefer to use a view with your error message you can uncomment "error_view".
        // This will superseed your default response message
        // 'error_view'        => 'very_basic_auth::default'
    ];
```

環境を指定する場合

```php
    'envs' => [
        'production',
        'development',
        'local'
    ],
```

`routes/web.php` にBasic認証の適用範囲を設定する

```php
// 複数のルーティングを認証かける場合
Route::group(['middleware' => 'auth.very_basic'], function() {
    Route::get('/', ['as' => 'start', 'uses' => 'StartController@index']);
    Route::get('/page', ['as' => 'page', 'uses' => 'StartController@page']);
});

// 特定のルーティングのみかける場合
Route::get('/', [
    'as' => 'start',
    'uses' => 'StartController@index',
    'middleware' => 'auth.very_basic'
]);
```

これでDBの設定等もなしでBasic認証が有効になります
デプロイして確認してみましょう

```
gcloud app deploy
```
[Atom] tablrプラグインでCSVビューが開かない場合の対処法

## 前提条件

- Macを利用しています

## 対処法

Atomを開いて`Settings > Install`から`tablr`をインストールすると
以下のメッセージが出てエラーになりました。（`Commant + ,`で開ける）

```
Cannot read property 'includeInfo' of undefined
```

対処法として、apmコマンドで以下を行ったら解決しました。
1. インストールした`tablr`をアンインストール
2. 修正版をgithubからインストールをする

```
> apm uninstall tablr
> apm install https://github.com/mfripp/atom-tablr.git
```

ちなみにapmコマントド使えるようにするには、

上部メニューの`Atom > Install Shell Commands`でapmコマンドが使えるようになりました。
React 学習メモ_20190408

最近Reactの勉強を始めたので、Note takingがてら学んだことをoutputしていきます(　･∀･)ﾉ
トンチンカンなことも書いてるのでご容赦下さい＼(^O^)／
Webエンジニアの諸先輩方からアドバイス頂けたら泣いて喜びます(  ；∀；)


# 現在勉強しているところ

[React公式チュートリアル]( https://ja.reactjs.org/tutorial/tutorial.html#why-immutability-is-important )の
見出し: `イミュータビリティは何故重要なのか`


# React.jsとは

コンポーネント(部品)単位でWebアプリを作れちゃう
超イケてるJavaScriptフレームワークだ٩( 'ω' )و 


# JSXとは

JavaScriptとHTMLが合体したような、Reactを記述するための言語だ。

    class Hoge extends React.Component{
      render(){
        return(
          <div>
            <h1>Hello World!</h1>
          </div>
        );
      }
    }



こんなかんじでJavaScriptの中にHTMLを融合させたような書き方をする。
ベテランのWebプログラマーにとってはキモいらしい(´・ω・`)
私にはどの部品がどんな見栄え、機能を担当するかがわかりやすい書き方だと感じた( ˘ω˘ )


# コンポーネントとは

Reactアプリを構成する一個一個の部品。
JSX中で`<Hogehoge />` と書かれているもの。という認識で良いのだろうか？(´・ω・`)


# stateとは

ユーザーの動きに合わせて変わる部分のこと。状態(state)を保持する部分。
stateはprivateである(そのオブジェクト内部からしかアクセス出来ない = 外からいじれない)

this.setStateメソッドが実行されると、コンポーネントが受け取ったstateをマージした上で、再レンダリング(ブラウザに表示する)する。

stateを保持するのははより下のコンポーネント(子コンポーネント)にさせる
(何か処理をする必要があるときは、子が親に状態を渡して処理してもらうとよいらしい)

内部データを書き換えるときは、直接そのデータにアクセスするのではなく
コピーを作成してからそいつをいじるようにすると、履歴を保持することができて便利


# propsとは

~~渡すものである~~ ←ちがう
コンポーネントが持っている属性のこと？
HTMLタグの属性と何かしらの関係があるのだろうか(・ω・)

```jsx

    <Hoge 
      props1 = 'foo'
      props2 = 'baa'
    />
````

上記コードの`props1` ,`props2` がpropsだ。



# 参考文献
http://better-than-i-was-yesterday.com/react-tutorial-japanese/

https://ja.reactjs.org/tutorial/tutorial.html
とにかくDockerイメージのサイズを小さくしたい

　docker build でイメージを作成したら、予想を超えびっくりする程大きくなってしまいました。
　運用に耐えられない程大きいのですが、この後コンテナを使ったテストなどが控えており、イメージのダイエットは平行して研究することとして、とりあえず出来るだけサイズダウンをして展開する必要に迫られたので、その際にとった方法を残しておきます。

### イメージのサイズダウン
　イメージのサイズダウンを行うために、意識しないといけない事はたくさんあるようですが、概ね下記３つくらいを意識しておけばそこそこ効果が出そうです。

- 複数のRUNコマンドを１行にまとめるなど、Dockerfileを頑張る。
- マルチステージビルドでビルド時しか使わない資材をイメージに持ち込まない。
- イメージのレイヤを統合して、肥大化したところをダイエットする。

この中で、Dockerfileを変更せずとも行える「イメージのレイヤを統合」することにしました。

### イメージのレイヤを統合する
　イメージのレイヤを統合したい場合は、`docker build`に`--squash`オプションをつけることで行われます。
ただし、これを行うとレイヤ構造であることのメリットが失われるので、コンテナの用途などを考えて採用するかを検討するのが良いと思います。
　このオプションは、実験的に実装されたオプションらしく、使用するにはDockerデーモン起動時のパラメータでスイッチしないと使えません。

#### 1. Dockerデーモンを`--experimental`オプション付きで起動する
という事で、スイッチの方法です。
`/lib/system/docker.service`の`ExecStart` の末尾に` -s overlay --experimental `を付与して、Dockerデーモンを起動すればOKです。

#### 2. `docker build` を `--squash`オプション付きで実施する
あとは、ビルド時のオプションを指定すればOKです。

```bash
docker build --squash=true
```

### 参考
https://docs.docker.com/engine/reference/commandline/build/#options
firestoreでaddせずにdocumentのunique idを使用する方法[備忘録]

「Get a DocumentReference for the document within the collection at the specified path. If no path is specified, an automatically-generated unique ID will be used for the returned DocumentReference.」とのことで、下記のようにdocに引数渡さなければ良い

```js
db.collection('hoge').doc().id
```

上記を用いれば下記のようにbatchで自動生成された共通のユニークidを使用して書き込める

```js
const db = firebase.firestore()
const batch = db.batch()
const hogeId = db.collection('hoge').doc().id
batch.set(db.collection('hoge').doc(hogeId), values)
batch.set(
  db
    .collection('fuga')
    .doc('piyopiyo')
    .collection('hoge')
    .doc(hogeId),
  values)
```
cv::Vec型変数を変換するときに少ない記述量で書く方法 その２

#tl;dr
カスタムで高速な画像処理を実装したいときは、C++とOpenCV(cv::Mat)を使って実装したいはず。cv::Matの画素はVec型だけど、[前回、この型の変換処理をラムダ式を使って簡潔に書ける小ネタ的な関数を紹介](https://qiita.com/luftfararen/items/1d5a0b88028c5258efc1)した。今回は、その関数とMat::forEachを使ってMatの画素値すべてを変換するやりかた。forEachは、並列化してくれるので、高速な画素値の変換コードを簡潔に書ける。ちなみに、最高速な変換コードを書きたいなら、それなりのやり方があるので、今回は簡潔に書くことに重点を置いています。ターゲットはC++17。Visual Studio 2017 15.9.11で動作確認。


# 本題
細かい説明よりも、まずコードから。conv関数の解説は、[前回](https://qiita.com/luftfararen/items/1d5a0b88028c5258efc1)を参照のこと。

```c++:サンプルコード1
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;

template <class VECD, class FUNC, class VEC>
VECD conv(const VEC& s, FUNC func) 
{
	constexpr int ch = VEC::channels < VECD::channels ? VEC::channels : VECD::channels;
	VECD ret;
	for (int i = 0; i < ch; i++) {
		ret[i] = func(s[i]);
	}
	return ret;
}

template <class VEC, class FUNC>
VEC conv(const VEC& s, FUNC func)
{
	constexpr int ch = VEC::channels;
	VEC ret;
	for (int i = 0; i < ch; i++) {
		ret[i] = func(s[i]);
	}
	return ret;
}

//今回初登場
template <class VECD, class FUNC, class VEC>
void conv(const VEC& s, VECD& d,FUNC func)
{
	constexpr int ch = VEC::channels < VECD::channels ? VEC::channels : VECD::channels;
	for (int i = 0; i < ch; i++) {
		func(s[i], d[i]);
	}
}

//使い方
int main()
{
	Mat src = imread("c:\\temp\\picture.jpg");
	Mat dst(src.size(),CV_8UC3);

	src.forEach<Vec3b>([&dst](const auto& pix, const int* pos) {
		dst.at<Vec3b>(pos[0],pos[1]) = conv(pix, [](const auto& v) {
			return v / 2;
		});
	});

	imshow("dark image", dst);
	waitKey();

	return 0;
}

```

# 解説
解説するほどのものでもないが、Mat::forEach\<T>のラムダ式の第一引数は、T型の画素値を渡す。サンプルコード1の例で言えば、TはVec3b。今回は、const auto&として、pix変数(Vec3b型)で受けた。pix変数(Vec3b型)をconv関数に渡してやると、conv関数のラムダ式の第一引数に、b,g,r値をそれぞれ渡しながら、ラムダ式が呼び出される。 例のように値を半分にしてreturnしてあげると、conv関数の戻り値はそれぞれの要素が半分になったVec3b型を返してくれる。これを参照でキャプチャしたdstの画素に代入してあげれば、全画素分処理できる。ちなみにサンプルコード2のように、Mat_\<T>::forEachを使ってもよい。Mat3bは、Mat_\<Vec3b>のtypedef。自分は、Vec3bを書くことが不要なサンプルコード2の書き方のほうが好き。
型変換を伴う場合、サンプルコード3と4の書き方があるが、どちらを選ぶかは、好みの問題かもしれない。

```c++:サンプルコード2
int main()
{
	Mat3b src = imread("c:\\temp\\picture.jpg");
	Mat3b dst(src.size());

	src.forEach([&dst](const auto& pix, const int* pos) {
		dst(pos[0],pos[1]) = conv(pix, [](const auto& v) {
			return v / 2;
		});
	});

	imshow("dark image", dst);
	waitKey();

	return 0;
}
```

```c++:サンプルコード3
int main()
{
	Mat3b src = imread("c:\\temp\\picture.jpg");
	Mat3f dst(src.size());

	src.forEach([&dst](const auto& pix, const int* pos) {
		dst(pos[0],pos[1]) = conv<Vec3f>(pix, [](const auto& v) {
			return v * 0.5f;
		});
	});

	return 0;
}
```

# 
```c++:サンプルコード4
int main()
{
	Mat3b src = imread("c:\\temp\\picture.jpg");
	Mat3f dst(src.size());

	src.forEach([&dst](const auto& pix, const int* pos) {
		conv(pix, dst(pos[0], pos[1]), [](const auto& s, auto& d) {
			d =  s * 0.5f;
		});
	});

	return 0;
}
```

# 補足
なお、ソースは無保証でソースを使用したことによって発生した損害に対して、責任を負いません。
Unityで枠付きの日本語テキストを描画する方法

## Unityで枠付きの日本語テキストを描画する方法
これは結構調べました。すると、Text Mesh Proというものがあるらしいので、それについて調べていると、次のような記事がありました。
[Unity TextMeshPro 日本語表示＋アウトライン](https://qiita.com/satotin/items/2856a4d2b5eea8c8a5be)

この記事の通りにしたらできました。

自分で方法を記事にしようかと思いましたが、この記事が素晴らしいのでご紹介だけしようと思います。
## 終わりに
私は現在、Web3のサービスの開発をしています。詳しくはこちらの記事をご覧下さい。
        [無料でイーサリアムが当たる、Web3時代の寄付サイトを作った話](https://note.com/kenroda/n/n814347fbdcd7)
Django2.2で開発サーバー起動時にSQLite3のエラーが出た場合の対応

Amazon Linux release 2 (Karoo)

```
# Python3のインストール
sudo yum install python3
cd
python3 -m venv ~/myvenv/

# 仮想環境に切り替え
source ~/myvenv/bin/activate
# Djangoインストール
pip install Django

# Djangoのチュートリアルをやろうとしてプロジェクト作成
$ django-admin startproject mysite

# 開発用サーバー起動
$ python manage.py runserver

# 大量に出るので一部だけ
# SQLite3は3.8.3、または、3.8.3以降のバージョンにしてくださいエラー
packages/django/db/backends/sqlite3/base.py", line 63, in check_sqlite_version
    raise ImproperlyConfigured('SQLite 3.8.3 or later is required (found %s).' % Database.sqlite_version)
django.core.exceptions.ImproperlyConfigured: SQLite 3.8.3 or later is required (found 3.7.17).

# SQLite3を最新化する
# ソースを取得 (ホームディレクトリで実行してます)
$ cd

# バージョンは「https://www.sqlite.org/download.html」で確認して、
# 新しいバージョンのファイル名を指定してください (2019/12/06追記)
# 例) SQLite 3.31.1の場合

$ wget https://www.sqlite.org/2020/sqlite-autoconf-3310100.tar.gz
$ tar xvfz sqlite-autoconf-3310100.tar.gz

# ビルドしてインストール
$ cd sqlite-autoconf-3310100
$ ./configure --prefix=/usr/local
$ make
$ sudo make install
$ sudo find /usr/ -name sqlite3

# コマンド結果
# /usr/lib64/python2.7/sqlite3と/usr/lib64/python3.7/sqlite3はディレクトリ
/usr/bin/sqlite3
/usr/lib64/python2.7/sqlite3
/usr/lib64/python3.7/sqlite3
/usr/local/bin/sqlite3

# 不要なファイル、ディレクトリ削除
$ cd 
$ rm sqlite-autoconf-3310100.tar.gz
$ rm -rf ./sqlite-autoconf-3310100

# バージョン確認
$ /usr/local/bin/sqlite3 --version

3.31.1 2020-01-27 19:55:54 3bfa9cc97da10598521b342961df8f5f68c7388fa117345eeb516eaa837bb4d6

$ /usr/bin/sqlite3 --version

3.7.17 2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668

$ sqlite3 --version

3.31.1 2020-01-27 19:55:54 3bfa9cc97da10598521b342961df8f5f68c7388fa117345eeb516eaa837bb4d6

$ sudo mv /usr/bin/sqlite3 /usr/bin/sqlite3_old
$ sudo ln -s /usr/local/bin/sqlite3 /usr/bin/sqlite3

# 共有ライブラリへパスを通す
# vi ~/.bashrcで設定を追加(すぐに反映する場合 source ~/.bashrc)しないとターミナルを起動するたびに実行することになります
$ export LD_LIBRARY_PATH="/usr/local/lib"

# PythonのSQLite3バージョン確認
$ python
Python 3.7.4 (default, Dec 13 2019, 01:02:18) 
[GCC 7.3.1 20180712 (Red Hat 7.3.1-6)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlite3
>>> sqlite3.sqlite_version
'3.31.1'
>>> exit()

# 開発用サーバー起動
$ cd
$ cd mysite
$ python manage.py runserver
```

**参考URL**
[Using SQLite3 with Django 2.2 and Python 3.6.7 on Centos7](https://stackoverflow.com/questions/55485858/using-sqlite3-with-django-2-2-and-python-3-6-7-on-centos7)
[Upgrade Python's sqlite3 on Debian](https://stackoverflow.com/questions/49820873/upgrade-pythons-sqlite3-on-debian?noredirect=1&lq=1)
[How do I upgrade the SQLite version used by Python's SQLite3 module on Mac?](https://stackoverflow.com/questions/26345972/how-do-i-upgrade-the-sqlite-version-used-by-pythons-sqlite3-module-on-mac?noredirect=1&lq=1)
中卒が説明する。　プログラミングとは？

# プログラミングって何？？
## 中卒の私が専門用語を可能な限り専門用語を省いて説明してきます。

## プログラミングとは？
プログラムを作る事をプログラミングという。
プログラムとは？コンピュータへの指示を書く事。

ではプログラムとは何かを少し説明していきます。
コンピュータが理解できるような言葉でするべき仕事の手順や内容が書いてある指示書みたいなものです。

その指示書をコードというもので書いていくのがプログラミングと言います。

プログラミングによりコンピュータが理解できるように指示を出して
人の作業効率を飛躍的にアップさせたり、情報収集を簡単にできるようにしています。