OmniAICreator/Qiita-1.07M huggingface dataset:
白黒写真の彩色プログラムを使用してみた(2019年対応版)

この度NPO法人 まちづくりエージェント SIDE BEACH CITY.で、パソコン・スマートフォンの活用方法を紹介するパフォーマンスをすることになりました。

[6/15開催のいそご地域活動フォーラムにて、PC活用パフォーマンスを開催 \| まちづくりエージェント SIDE BEACH CITY\.](https://sbc.yokohama/internet/20180615-isogo-pc-performance)

まあそれはそれとして、この場で以前紹介されていた、白黒写真を彩色するプログラムを見せることになり、オープンソースなので実際にビルドし、実行してみることに。

大まかには以下の記事にあがっていますので、環境が揃っている人は特に問題はないかと。

* [白黒写真に着彩する人工知能を使い、実際の色見と推測による色見を比較してみた \- Qiita](https://qiita.com/y_hokkey/items/d1a12b7d155b9ed2a623)

ただし、わたしはWindowsのPCしか持っていないため、とりあえずDockerを使って実行環境を構築しました。また、2019年現在は上記プログラムのままでは動作しない部分があるため、それも含めてメモ。

# 手順

だいたい上記の通りですが、ひとつだけ。

[ubuntu 14\.04 でのapt\-add\-repositoryのインストール \- Qiita](https://qiita.com/Hiroshi_Obata/items/8fa13972f7922ad3252f)に書いてあるとおり、「python-software-properties」というパッケージは2019年5月24日現在のUbuntuの環境には存在しないため、「software-properties-common」に変更する必要があります。

また、DockerhubでインストールできるUbuntu環境にはwgetなどの基本的なコマンドが入っていないため、apt-getでちゃんとインストールしておきます。

## で。

で、つくってみたDockerfileがこちら。

* [side\-beach\-city/isogofesta\_2019\_siggraph\_tool: いそご地域活動フォーラム2019で使用する早大研究結果の実行環境](https://github.com/side-beach-city/isogofesta_2019_siggraph_tool)


`d_build.sh`でコンテナイメージをビルドし、`d_run.sh`でコンテナを実行、bashに入れます。

README.mdにも書いているとおり、事前に

* 仮想マシンに8GBくらいの容量を割り当てておくこと
* /dockerというディレクトリを共有フォルダとして作成しておくこと

ということが必要になります。

では結果はどうなるかというと、とりあえず[Webサービス版](http://iizuka.cs.tsukuba.ac.jp/projects/colorization/web/)と同じなようです。ImageNet Modelというものもあるようなので、そちらを使うとまた違うのかもしれません。

色鮮やかになるかどうかは、「とりあえず写真による」という感じです。すごく鮮明に彩色される写真もあれば、全体的に茶色っぽくなるだけという写真もあるという感じ。また、最近になってモノクロレンズで撮影したり、別のアプリで白黒化した写真は、おおよそ元の画像に近くなるという印象がありました。

## そのほか

そのほかDockerfile作成に当たって気をつけた点

### `RUN`コマンドの扱いについて

Dockerfileでは、ファイルを修正したあと再イメージのビルドを行うと、「修正したより下の行だけ」再構築されます。

torchのビルドなどはなるべく`RUN`コマンドを1行ごとに分けておくと、ビルドイメージの作成に失敗したときの手戻りが少なく安心です(よくあるサンプルのように別のshファイルで処理したり、複数コマンドを&&で繋いだりすると、コマンドが失敗したときに一からやり直しになる)。

### Dockerfileのビルドと実行について

Dockerfileのビルド(docker build)と実行(docker run)については、何度も実行することになるためシェルスクリプトに分けておくと日々の修正が苦痛になりません。

また、うっかりコマンドラインで設定するべきパラメータを忘れたり、結びつけるべきディレクトリを指定し忘れたりすることも防げるので、忘れずシェルスクリプトにしておくとよいでしょう(今回はあまりやり直しをせずにすみましたが)。

# 参考

* [白黒写真に着彩する人工知能を使い、実際の色見と推測による色見を比較してみた \- Qiita](https://qiita.com/y_hokkey/items/d1a12b7d155b9ed2a623)
* [ubuntu 14\.04 でのapt\-add\-repositoryのインストール \- Qiita](https://qiita.com/Hiroshi_Obata/items/8fa13972f7922ad3252f)
* [satoshiiizuka/siggraph2016\_colorization: Code for the paper 'Let there be Color\!: Joint End\-to\-end Learning of Global and Local Image Priors for Automatic Image Colorization with Simultaneous Classification'\.](https://github.com/satoshiiizuka/siggraph2016_colorization)

siggraph2016_colorizationのREADME.mdを読む限り、メモリは4GB以上あればよいみたいですね。
LINE WORKS の Bot に送信したトークを Excel に保存する

LINE WORKS の トーク Bot API と Microsoft FLOW で作るトーク Bot が受信したトークを Excel に記録してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/adbdac76-4131-0b30-ea20-bfff466fd176.png)


##Excel
テーブルを作成した Excel ブックを OneDrive または OneDrive for Business に保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/a656a589-4be5-e3f6-7c41-b0615e304b53.png)

##Microsoft Flow の準備

フローのトリガーとして [HTTP 要求の受信時] を用います。これにより、ユーザーから送信されたメッセージを解析し、受信者への転送メッセージの処理を行います。

[要求本文の JSON スキーマ] を [サンプルのペイロードを使用してスキーマを生成する] を利用して作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/0a88a8de-2d3f-ccb2-a9e0-e6623df248d1.png)


サンプルの JSON ペイロードは LINE WORKS の Developers サイトの "メッセージ受信 - Callback 形式 (message)" の記事中の Request Example として掲載された以下を用います。

https://developers.worksmobile.com/jp/document/100500901?lang=ja

```
{
  "type": "message",
  "source": {
    "accountId": "admin@example.com",
    "roomId": "12345"
  },
  "createdTime": 1470902041851,
  "content": {
    "type": "text",
    "text": "hello"
  }
}
```

Microsoft Flow がサンプル ペイロードを解析してスキーマを生成してくれます。スバラシイ!!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/3534239b-0692-6904-5686-1cb4bd7225f8.png)

[method] は "POST" を指定します。

なお、Flow の保存時に、この Http 要求の受信用の URL が生成され、これを LINE WORKS の Developer Console で Callback URL として利用します。

次に、"Excel Online" の "表に行を追加" をアクションとして指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/ec2ac620-0f26-f4ed-fe41-9a514fc9b5e9.png)

##LINE WORKS Developer Console の準備

LINE WORKS でトークボット API を利用するため、LINE WORKS の Developer Console で、以下の作業を行います。

###Bot 登録
Bot メニューで [登録] ボタンをクリックし、以下の項目を入力し、保存をクリック
- Bot名 -> 任意の名前
- 「説明」-> 任意の説明文
- Callback URL -> Microsoft Flow の Http 受信時の要求で生成された URL
- 複数人のトークルームに招待可 -> off
- 管理者 -> 任意のメンバーを指定

##LINE WORKS 管理画面での作業
LINE WORKS の管理画面の [サービス]-[Bot] メニューで当該 Bot を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/88b61306-a9d3-d7a1-192d-df77d9b985fe.png)

##動作確認
LINE WORKS でメッセージ受付 Bot にメッセージを送ると、Excel Online のシートにログが記録されることを確認します。
【Python】世界地図・その右と下にグラフを描く

論文用の画像を作るためのテンプレートのメモ．
真ん中：世界地図，右と下：緯度・経度ごとの陸地面積．

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270660/18ed3762-6074-d325-baf1-21b50951132e.png)

若干枠線がズレるのはなぜ？

``` Python:map_right_bottom.py
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
from   mpl_toolkits.basemap import Basemap

north, south, dlat = 90.0, -60.0, 30.0
east , west , dlon = 180.0, -180.0, 60.0

def gen_axes(figWidth=10.0, rightWidth=4.0, bottomHeight=2.5):
    '''
    center|right
    ------
    bottom
    '''
    centerWidth  = figWidth - rightWidth
    centerHeight = centerWidth * (north - south) / (east - west)
    figHeight    = centerHeight + bottomHeight
    fig = plt.figure(figsize=(figWidth, figHeight))
    gs = GridSpec(2, 2,
                  width_ratios=(centerWidth,rightWidth), height_ratios=(centerHeight,bottomHeight),
                  wspace=0.0, hspace=0.0)
    return [plt.subplot(gs[0,0]), plt.subplot(gs[0,1]), plt.subplot(gs[1,0])] # center, right, bottom

def center_map(ax):
    m = Basemap(llcrnrlon=west, llcrnrlat=south, urcrnrlon=east, urcrnrlat=north, ax=ax)
    m.drawcoastlines(linewidth=.4)
    m.fillcontinents(color='0.7')
    m.drawparallels(np.arange(south+dlat,north,dlat), labels=[1,0,0,0])
    m.drawmeridians(np.arange(west +dlon,east ,dlon), labels=[0,0,1,0])
    return

def right_plot(ax, data):
    ax.plot(data, np.arange(len(data))[::-1])
    left, right = ax.get_xlim()
    left        = 0
    ax.set_xlim(left=left, right=right)
    ax.hlines(y=range(120, 720, 120), xmin=left, xmax=right, linestyles=':', linewidth=1.0)
    ax.set_ylim(0, len(data))
    ax.tick_params(left=False, right=False)
    ax.tick_params(labelleft=False, labelright=False)
    return

def bottom_plot(ax, data):
    ax.plot(data)
    ax.set_xlim(0, len(data))
    bottom, top = ax.get_ylim()
    bottom      = 0
    ax.set_ylim(top=top, bottom=bottom)
    ax.vlines(x=range(240, 1440, 240), ymin=bottom, ymax=top, linestyles=':', linewidth=1.0)
    ax.tick_params(top=False, bottom=False)
    ax.tick_params(labeltop=False, labelbottom=False)
    ax.set_facecolor((0.0, 0.0, 0.0, 0.0))


def main(*args):
    landMap = # グリッドごとの陸地面積マップ
    landMap = np.ma.masked_less_equal(landMap, 0.0)
    landLat = landMap.sum(axis=1)
    landLon = landMap.sum(axis=0)

    axs = gen_axes()

    center_map (axs[0])
    right_plot (axs[1], landLat)
    bottom_plot(axs[2], landLon)

    plt.show()

```
結局Pythonのフレームワークは何を使えば良いの？ [Flask vs Django]2019

#はじめに

機械学習やら色々な新しい事を実践的に試すべく
エロサイトを開発中。[モトダチ](http://motodachi.me/)
開発実践用にオープンしているので広告は入っておりませんのでお気軽にどうぞ。
色々工夫したアプリケーションの作りになっているのでレスポンスは速いはず。

自分への忘備録も含めてFlaskの知識をまとめてみたいと思います。

#Flaskについて
最近はPythonが人気沸騰中だと思います。
Pythonの中でWEBフレームワークといえばDjangoとFlaskの2トップだと思います。
ほとんどの人がPythonでウェブアプリを構築する場合その2つのどちらかを選択するのかな、と。

#Flask VS Django問題
Pythonアプリを作りたいけどDjangoとFlaskのどっちが良いの？という疑問はよく起こります。
僕も最初は迷いました。
まぁ極端なことを言えば作りたいものに合わせて選択してね？ってことだと思うんだけどそれは酷ってもんですよね。
そこに回答はないんですよ。
・どのようなPythonアプリを作りたいか
・どのような規模のアプリケーションになるか
・どのような人がコーディングをするか

この記事では迷ってるんだよねって人への一助になればと思います。

#Flaskについて
まずはじめにFlaskの特徴を。

Flaskはマイクロフレームワークで軽量で最小の機能しか備わってないということが最大の特徴です。(最小だったり最大だったりややこしいｗ)

機能があまり含まれていないので色々自由が効き、簡単に習得することができます。

もちろんライブラリを追加することで様々な機能を使うことができます。

#Djangoについて
Djangoはデフォルトで必要な機能を持ち合わせたフレームワーク。

認証、管理画面、RSSフィードなどよく使われる機能があらかじめ含まれています。

既存機能をサクッと導入したい場合は速い反面、初心者やフレームワークに慣れてない人にとってはとっつきにくい面があります。

#Flaskを使うと良いケース
・簡単なウェブアプリをサクッと開発したい
・REST APIを開発したい
・Pythonをつつき始めたばかりの初心者
・その他ウェブ言語でフレームワークを使用したことがない方
・HP+フォームなどのシンプルなページを実装したい方

#Djangoを使うと良いケース
・認証や管理画面があるようなガッツリとしたウェブアプリを作りたい方
・今までその他ウェブ言語でフレームワークを使用したことがある方
・MVCでの開発経験がある方

#最後に
最初に挙げた[モトダチ](http://motodachi.me/)はFlaskで構築してます。
Pythonのウェブアプリケーションは初めてでしたがサクサクと進める事ができました。

色々意見頂けると開発のモチベーションが上がります。
何かあればぜひコメント下さい。
compareToの大小比較について

#CompareToについて値の結果、どの比較がどの値になるか忘れてしまうことがあるので、備忘録。

**①文字列で比較する場合はcompareTo()**

```

public class Test {
	public static void main(String[] args) {
		 String a = "a";
		 String b = "b";
		 System.out.println(a.compareTo(b));
		 System.out.println(b.compareTo(a));
		 System.out.println(a.compareTo(a));
	}
}
```
下が実行結果です。

```
-1
1
0
```
辞書的に文字の位置が離れている場合に、-1か1を返します。
aはbの前なので-1
bはaのあとなので1
同一の場合は0

**②数値で比較する場合はInteger.compare()**

```

public class Test {
	public static void main(String[] args) {
		 int one = 1;
		 int two = 2;
		 System.out.println(Integer.compare(one,two));
		 System.out.println(Integer.compare(two,one));
		 System.out.println(Integer.compare(one,one));
	}
}
```
下が実行結果です。

```
-1
1
0
```
単純に計算結果。
1-2=-1
2-1=1
1-1=0です。
Glideを試してみる。

# はじめに
みなさん、PWAをご存知ですか？
PWAは「Progressive Web Apps」の略称で、モバイル向けwebサイトを**スマフォアプリライクに使用できる仕組み**です。
2018年にiosでも対応され、軽くトレンドになっている？

そんなPWAをプログラミング無しで簡単に実装できてしまう「Glide」を試してみる。

# Glideとはなんぞや
- google スプレッドシートから簡単にPWAのサイトを作成できるノンプログラミングツール
- googleアカウントでサインインすることで使用可能(別途登録不要)
- 無料プランと有料プランがある。

# なにを作る？

「最近、暑いなー」
「ビール飲みたいなー」

####「そーだ、ビアガーデン行こう！」

と思い立ち、今回、例題では都内のビアガーデンリストを作成しようと思います。

# さっそく試してみる

1.**[Glide](https://app.heyglide.com/)**にアクセスする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250217/069b25fd-4093-dc1c-988a-3433b4a1f855.png)

2.googleアカウントでサインインする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250217/e4aaa141-af6f-e88f-60e7-a1e015acfbb7.png)

3.New App(赤枠)をクリックして、読み込むスプレッドシートを選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250217/11254577-6054-960c-bed1-80780151ed81.png)

○スプレッドシート選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250217/da15214d-c005-a196-1177-83cbe76cc716.png)

4.スプレッドシートを選択しただけで、モバイル端末向けの画面にそれっぽいものができた！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250217/413e36eb-7c57-6b3f-f98e-3c1b13eb45ed.png)

大枠作成まで、**なんと5分！！**
ほとんどがスプレッドシートの記入だったので、サイト自体は30秒でできてしまいました。

○補足
初期情報として以下のようなスプレッドシートを使用しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250217/8447cced-3d04-e793-fdd4-f435da07c0df.png)

5. 各リストのアイコンを画像に変更する。
載せたい画像を保存し、googleドライブに保存します。
赤枠の「共有可能なリンクを取得」を押して、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250217/4595359e-7f0e-e527-d9f2-25250b14dc5a.png)

スプレッドシートにimgの列を追加して、
コピーしたURLをペースト。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250217/e08c61d8-9f1e-a9b9-6171-2c5112d9ec2a.png)

Glideの画面から、「Reload sheet」をクリック。
imageにシートのimgの列を指定し、「Show initial as default image」をOFFにする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250217/986786db-8ca8-c4a9-fa2d-ef9530702f76.png)

**アイコンも自分のgoogleアカウント内で生成することができます。**

ちなみに、「settings」からアイコンの画像を編集することもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250217/b72b9374-2225-0487-702e-3ea3b6ea2e77.png)

参考までに、今回作成した、詳細画面は以下のような基本情報を載せた形になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250217/cb91f9c4-2026-df21-ba4d-8d602bd7a4a3.png)


# おわりに
- アプリを共有したい場合も、左メニューの「Share app」をクリックすれば、簡単に共有できる。

- 他のQiitaの記事でも、公園リスト、旅程リスト等、表形式で表せるものを作成している人が多いが、あくまで、作成するサイトの元ネタがスプレッドシートなだけにリスト系のアプリを作るのは簡単だが、応用は難しい？

- スプレッドシートを共有しておくだけで、共同開発が可能な点は便利！

- まだまだ、機能がたくさんある。詳細画面に載せる情報の変更、googleMapの追加、ユーザーの編集機能の追加などなど。(やる気に満ちたら、本記事で触れていない機能についても、書こうと思います…。)
ログ関係のOSSについて調べた。

# ツールの概要

かなり備忘録としての印象が強いです。
何かお気付きの点がございましたら、コメントください。

### 1. fluentd
fluentdとは、<br>
> fluentd は __ログ集約ソフトウェア__ である、と、きっぱりと書かれていた。でも、"ログ" って言い切ってるけど、slack や Twillio などへの出力も後述するプラグインで対応できるので、広義での "ログ"、と思ったほうがよさそう。[1]

#### 参考サイト
[1][いまさらだけど fluentd に入門した](https://blog.a-know.me/entry/2015/06/14/094945)<br>
[2][fluentdでつくる監視系](https://qiita.com/kotatsu360/items/2985056d5af72c6eb5c2)

### 2. Elasticsearch
Electricsearchとは、<br>
- Elastic社が開発している、スケーラビリティに優れた全文検索エンジン
- リアルタイムデータ分析、ログ解析、全文検索など様々な分析が可能になる
- ログ集約のLogstashやfluentd、可視化ツールのkibanaと一緒に使われることが多い。また、日本語用に日本語形態素解析エンジンの kuromojiを導入して使われる。
- 複数のデータベースを横断して検索することが、ごく当たり前の用途として提供されている

#### 参考サイト
[1][3分で分かった気になる、Elasticsearchとは？](https://qiita.com/r548/items/3622048a622d9c0acc05)<br>
[2][実践！Elasticsearch](http://engineer.wantedly.com/2014/02/25/elasticsearch-at-wantedly-1.html)<br>
[3][2014-04-04
elasticsearchを全文検索サーバとして活用するなら読んでおきたい、6つのブログ記事をピックアップ（追記あり）](http://y-ken.hatenablog.com/entry/essential-japanese-blogs-for-elasticsearch-study)

### 3. Kibana
Kibanaとは、
> KibanaはElastic社が開発している__ビジュアライゼーション__のためのツール[1]

![elasticsearch-kibana.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291611/6730760a-99bb-dec9-4f29-d98e6f58dde1.png)


#### 参考サイト
[1][Kibanaで簡単! サクサク ビジュアライズしよう！](https://qiita.com/kitfactory/items/9c2f990d87e33fab828a)

### 4. Grafana
Grafanaとは、
> Grafana は Grafana Labs が公開しているログ・データ可視化のためのツール[1]

Kibanaと同じように可視化ツールであるが、Kibanaほどたくさんの種類があるわけではない。
簡単にモニタリングするためのダッシュボードを作成するのに使える。

#### 参考サイト
[1][10分で理解するGrafana](https://qiita.com/Chanmoro/items/a23f0408f0e64658a775)<br>
[2][手軽にシステムダッシュボードが作れる「Grafana」レビュー](https://knowledge.sakura.ad.jp/6831/)
Intel NUC(NUC8I5BEH)にVMware ESXi 6.7.0 Update 2をインストール

仕事でサーバ仮想化を触れる機会が増えてきたので自宅検証のためにESXi環境を作成してみる。
~~中古で適当なサーバ買おうとしたがスペースと電気代を考えて~~NUCに入れてみる。

##構成
■本体:NUC8I5BEH
https://www.intel.co.jp/content/www/jp/ja/products/boards-kits/nuc/kits/nuc8i5beh.html
■メモリ:DDR4-2400(PC4-19200) 16GB×2枚　　　260Pin 1.2V CL17 SP032GBSFU240B22
■ストレージ（m2):WDS500G2B0B（500GB）
■ストレージ（HDD) :WD20SPZX（2TB）
※これで8万円くらいとかいう安さ。。。

##インストール
最新版の6.7.0.update02をインストールしてみる。
（BIOSアップデートは実施せず、デフォルトのBIOSverはBECFL357.86A.0051.2018.1015.1513でした。）
VMware公式からisoファイルを落としてきて、
インストール用USBメモリを作成する。
参考：https://qiita.com/hktm/items/0bacdd144365c2da1165

※ちなみに無償版のVMware vSphere Hypervisor と製品版のVMware vSphereの中身は全く同一でライセンスで機能の有効無効を判断しているとのことらしいです。

特に何もせずUSBを差して起動するとインストーラが起動した。
※いつもの黄色画面

以降は以下を参考にしてESXiをインストール。
https://docs.vmware.com/jp/VMware-vSphere/6.7/vsphere-esxi-67-installation-setup-guide.pdf

※マニュアル読まなくても画面指示にしたがっていけば特に問題なくインストールできる

BIOSやドライバ関係で色々苦労しそうなイメージだったが何も考えずインストールでOKでした。
あとはインストール後IP設定してあげてブラウザからIPにアクセスして仮想マシン建て放題
gitのcommitの生成可否判断はpre-commitフック以前に行われる

gitは通常、変更がaddされていない場合はコミットを作成しない(`--allow-empty`が必要)。
しかし、`pre-commit`フックで何らかの操作を実行し、結果として差分が消失した場合でもコミットは作成される。

```sh:pre-commit
#!/bin/sh

git diff --cached | 対象ファイルに対してなんか色々処理 | 最後に再度addする
```
例えば上のようなフックで「色々処理」の結果、addしたファイルの変更が元に戻ったとする。この時でもコミットは作成される。`git diff HEAD~..HEAD`には何も表示されない。

更に極端なことを言えば、フック内でファイルを全てreset(アンステージ)してもコミットは作成される。

```sh:pre-commit
#!/bin/sh

git reset 
#賽の河原的なアレ
```

だからどうしたという話だが、ちょっと興味深かったのでメモ。
PythonでGoogleCloudStorageへファイルをアップロード・ダウンロードする方法

##まず最初に準備（サービスアカウント、バケット作成）
まずはこの記事を参考に以下のことをやります。
[GoogleCloudStorageでPythonからファイルをやりとりする方法](https://sleepless-se.net/2018/05/22/googlecloudstorage%E3%81%A7python%E3%81%8B%E3%82%89%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E3%82%84%E3%82%8A%E3%81%A8%E3%82%8A%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/)
- サービスアカウントの作成（API）
- クラウドストレージでバケットを作成

サービスアカウント作成時に、役割が「ストレージ管理者」になっていますが自分はそれが選べなかったので、「オーナー」にしました。
全リソースへのアクセス権限があるみたいなので迷ったらこれでいいのではないでしょうか。
![Screen Shot 2019-05-24 at 21.49.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337592/6ae4d7c3-6e1f-be37-fd02-7acfc2850b90.png)


##PythonでGoogleCloudStorageを操作

Googleクラウドのパッケージをインストールします。

```
sudo pip install --upgrade google-cloud
```

以下のスクリプトでバケットにローカルファイルのアップロードと、バケットからのダウンロードが可能です。

```python
import os
from google.cloud import storage
#クラウドストレージ（バケット）に接続
os.environ["GOOGLE_APPLICATION_CREDENTIALS"]='キーファイルパス（Json）'
client = storage.Client()
bucket = client.get_bucket('バケット名')

#ファイルをアップロード
blob = bucket.blob('保存ファイル名')
blob.upload_from_filename(filename='ローカルファイルパス')

#アップロードしたファイルをダウンロード
blob2 = bucket.get_blob('取得ファイル名')
print(blob2.download_as_string())

```
##以下のエラーが出た場合（No module named 'google.api_core.client_info'）
自分の場合はここで以下のエラーが出て先に進めなかったのですが、

```
ModuleNotFoundError: No module named 'google.api_core.client_info'
```

pythonの仮想環境を構築し、そこにライブラリをインストールすることで正常に動きました。
[venv: Python 仮想環境管理](https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e)

```
$ python3 -m venv venv
$ source venv/bin/activate
$ venv/bin/pip install --upgrade google-cloud
$ pip install google.cloud.storage
```

これらのコマンド打った後に、実行したら無事に操作できました。

##次にやりたいこと
- pythonのウェブフレームワークを使用して、簡単な文字起こしサービスを作成
- まずはローカルからではなくwebからアップロードしたものをバケットに送れるようにする
- Cloud Speech-to-Text を使用
- 今回はテキストファイルを用いたが、課題は結構アップロードからダウンロードまで時間がかかったこと
- 長い音声ファイルを場合のレスポンス。。
非同期通信実装　メモ

#非同期通信　実装
理解している箇所を列挙
##JavaScript,jQueryの準備

```ruby:Gemfile
gem'jquery-rails'
```
```:ターミナル
$bundle install
```
```ruby:application.js
// = require jquery
// = require jquery.ujs
```
application.jsに記述があるか確認。Railsバージョン５.１以前では記述がないので、バージョン毎の記述をしていく。

##JavaScript,jQuery記述

```ruby:javascripts/message.js
$(function(){
  $('イベント起こすid,class名').on('アクション名’, function(e){
    e.preventDefault();
    var formData = new FormData(this);
  })
})

```
javascripts/message.jsファイルを作成。
Unityのリッチテキストはエスケープできない (けれど、回避はできる)

# 前提

- スクリプトから動的に内容を変化させるuGUIのTextで、内容によって部分的にスタイルをコントロールできるようにしたかったので、リッチテキスト(⇒[Unityマニュアル](https://docs.unity3d.com/ja/current/Manual/StyledText.html)) を使用しました。
    - 例えば、左寄せで「ABC」と「**X** ABC」を切り替えたいような要求です。

# ハマったこと

- ユーザーが入力可能な文字列を挿入したら、文字列中にタグがあって化けてしまいました。
- タグをエスケープしようとしたのですが、Unityのリッチテキストにはエスケープ方法がありませんでした。
- `<` を `\<` に置き換えれば、確かにタグとして認識されなくなるのですが、バックスラッシュも表示されてしまいます。

# やりたいこと

- 有効なタグにならないようにしたい。
- なるべく入力に近い表示にしたい。

# 回避した方法

- 元の文字列`string`に対して、`string.Replace ("<", "<\u200B").Replace (">", "\u200B>")`を使うようにしました。
    - `"\u200B"`は、Unicodeのゼロ幅スペース([Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%BC%E3%83%AD%E5%B9%85%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9))です。
    - 実質的にエスケープできているといっても過言ではないですね?
- ゼロ幅スペースに対応できない環境では、普通のスペースを使用して回避できます。  
`string.Replace ("<", "< ").Replace (">", " >")`

# 反省

- ユーザー入力に由来する文字列を表示する場合は、リッチテキストは使わない方が良さそうです。
    - 入力データを保存したり編集したりしないなら、入力直後に処理するだけで解決しますが、編集できるなど処理前のものを残す必要がある場合は、処理前後の双方を保持するか、表示毎に処理する必要があって煩雑です。
    - 入力をそのまま保持する`Name`に対して、処理して返す`SafeName`プロパティを追加して使い分けるようにしました。
Railsで基本情報技術者試験の過去問題サイトを作る（３：親子関係、登録編）

# はじめに
ゆる〜く学ぶ。みんなのWeb勉強コミュニティー。　「にゅ〜ぶる会」を運用中です。
https://newburu.github.io/

そこで、何か教育用のコンテンツが欲しいなぁ〜と思い立ち、今回の企画をスタートしました！

Railsで基本情報技術者試験の過去問題サイトを作ります！

# 最終目標
- 問題・回答の登録は、Scaffoldで簡易でOK
- APIを用意して、ランダムに問題を抽出する機能を追加する
- TwitterBOT、LINEBOT、SlackBOTが出来たら良いな

# 履歴
１：構築編
　　https://qiita.com/newburu/items/ed59f47ac645b19620f6
２：日本語化(i18n)編
　　https://qiita.com/newburu/items/4f12fdb61bf6cd601545/
３：親子関係、登録編
　　本ページ
４：親子関係、参照編
　　https://qiita.com/newburu/items/51b11bd02691efc2cc0d
５：API編
　　https://qiita.com/newburu/items/89f9f847a2648bdd006c
６：SlackBOT編
　　https://qiita.com/newburu/items/aeeb9acb453da786bd59
７：Herokuデプロイ〜自動化編
　　https://qiita.com/newburu/items/0a8bb02e1e8c8fe737c7

# 今回やる事
- 親子関係を設定し、登録しやすくする

※レイアウトをやろうと思いましたが、こちらの方が優先なので、予定を変更させて頂きました。

# 親子関係を設定し、登録しやすくする

## 1. gem '[cocoon](https://github.com/nathanvda/cocoon)', gem '[jquery-rails](https://github.com/rails/jquery-rails)'を追加します。

<font color="red">Rails5.1からjQueryがなくなったため、jquery-railsも追加する必要があります。</font>

```ruby:./Gemfile
gem 'cocoon'
gem 'jquery-rails'
```
```terminal:bundle-install
$ bundle install
```

## 2. Modelに、親子関係を設定します。

・親(question)には、「has_many :answers」を追加します。
・親が削除された時に、一緒に子も削除されるように、「dependent: :destroy」をつけます。
・accepts_nested_attributes_forを使うと、親と子を一緒にcreate/update出来るようにします。
・削除できるよう「allow_destroy: true」をつけます。

```ruby:app/models/question.rb
  has_many :answers, dependent: :destroy
  accepts_nested_attributes_for :answers, allow_destroy: true
```

子(models/answer.rb)は、作成時にreferencesとしているため、自動で設定されています。

```ruby:app/models/answers.rb
  belongs_to :question
```

## 3. Viewに、親子同時に登録・更新出来るように設定します。

application.jsに以下を追加します。

```js:app/javascripts/application.js
//= require jquery
//= require cocoon
```
viewを変更します。

```slim:app/views/questions/_form.html.slim
  .answers
    = f.fields_for :answers do |answer|
      = render 'answer_fields', f: answer
    = link_to_add_association "追加", f, :answers
```

子供の情報登録用フォームになるviewファイルを新規作成します。

```slim:app/views/questions/_answer_fields.html.slim
.nested-fields
  .field
    = f.label :msg
    = f.text_area :msg
  .field
    = f.label :correct
    = f.check_box :correct

  = link_to_remove_association "削除", f
```

### 4. コントローラーで登録可能にします。
以下のように子のパラメータを受け取れるようにしましょう。

```ruby:app/controllers/questions_controller.rb
    def question_params
      params.require(:question).permit(:category1, :category2, :category3, :msg, answers_attributes: [:id, :msg, :correct, :_destroy])
    end
```

## 5. 確認します。

新規作成画面はこんな感じになります。
<img width="247" alt="新規作成画面" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118481/5a280873-ebab-80d5-a792-77d89e4166cf.png">

「追加」ボタンを押すたびに、子供の入力エリアが追加されます。
<img width="257" alt="追加" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118481/888beb16-e191-253a-1156-39fc57deae70.png">

# 今回はここまで
ありがとうございました！
次回は、参照画面などに、子供の情報を追加していこう。
[Ruby][Git] git log -L で特定の関数 (メソッド) の変更履歴が見られるらしいので Ruby でも試してみた

# 概要

次のツイートを見て便利そうだと思った。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">これは本当にとても便利なgitのログ機能なんですが、 `git log -L :関数名:ファイル名` でその関数の履歴が見れます <a href="https://t.co/wcul1OYr0W">pic.twitter.com/wcul1OYr0W</a></p>&mdash; ほぼろ (@rhoboro) <a href="https://twitter.com/rhoboro/status/1131343215125094400?ref_src=twsrc%5Etfw">May 22, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

どうやら

```
git log -L :<関数名>:<ファイルパス>
```

という形式で特定の関数の変更履歴が見られるらしい。
このツイートでは Python の関数の変更履歴を表示していたが、Ruby のメソッドでもできるか試してみた。

# 例

試しに Active Support コア拡張機能の [String#truncate](https://api.rubyonrails.org/classes/String.html#method-i-truncate) の変更履歴を確認してみる。ローカルに Rails のリポジトリを git clone して、次の git コマンドを実行する。

```
git log -L :truncate:activesupport/lib/active_support/core_ext/string/filters.rb
```

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6697/ba058d18-8961-ff1d-2d87-26f4f491f8f8.png)

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6697/19d6eb57-33c4-a00b-e78d-aa42dc974ef8.png)

本当に truncate のログと差分だけ表示された！メソッドの変更を追跡するのにファイルごとだと粒度が大きいので、メソッドごとに表示できるのは便利だ ☺️
Ajaxによる非同期通信で、データベースに二重に投稿される問題

# 問題
form_forでデータを受け取り、Ajaxによる非同期通信でHTMLを差し替えて投稿する際、
投稿内容がデータベースに二重に投稿される問題が起きる。

# 原因
form_forにて投稿する際、controllerのcreateアクションとformのPOST、両方がデータベースに投稿してしまう。

※このへん理解浅いので、理解が間違っていたらご指摘いただけると助かります。

# 解決法
jsファイルの非同期通信の関数の最後に **return false;** を記述しておく。
formのPOSTがキャンセルされるため、二重投稿されなくなる。

# 補足
かなりピンポイントな問題と対策な気がしますが、検索しても解決方法が出てこなかったので記載しておきます。
なんとなくの理解ですので、言い方や理解の仕方が間違ってる可能性あります。
Heroku 本番環境 [Mysql2::Error::ConnectionError: Access denied for user root@localhost (using password: NO)]　エラー

注)本ページに出てくる、usernameや、password、host値は存在しない値です。
#問題:
###
rails c production で User.createをしようとしたら、
```Mysql2::Error::ConnectionError: Access denied for user 'b2a63e570bc849'@'52.204.50.0３' (using password: NO)```
と言われてしまいました。

```terminal:ターミナル
$ heroku config #mysql周辺情報をチェックします。
# 注意　'mysql2://[ユーザ名]:[パスワード]@[ホスト名]/[スキーマ名]?reconnect=true'　です。

CLEARDB_DATABASE_URL:     mysql://kefbwfffn349:31w1dd54@us-cdbr-iron-east-04.cleardb.net/heroku_sufbd6sjdhsb5d?reconnect=true
DATABASE_PASSWORD:        31w1dd54
DATABASE_URL:             mysql2://kefbwfffn349:31w1dd54@us-cdbr-iron-east-04.cleardb.net/heroku_sufbd6sjdhsb5d?reconnect=true

$ mysql -u kefbwfffn349 -h us-cdbr-iron-east-04.cleardb.net -p  #mysqlに入れるか？
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 
...
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> exit # 入れました。
```

host,username,passwordはあってるのに、、、
となると,
# 検証
原因はエラー文の中のusing password: NOかな？？？と思い、

```yml:config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  username: root
  password: 
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

production:
  <<: *default
  database: heroku_sufbd6sjdhsb5d
  username: kefbwfffn349
  host: us-cdbr-iron-east-04.cleardb.net
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock
```
の```password: <%= ENV['DATABASE_PASSWORD'] %>```の部分を直接パスワードに置き換えることにしました。

```yml:config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  username: root
  password: 
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

production:
  <<: *default
  database: heroku_sufbd6sjdhsb5d
  username: kefbwfffn349
  host: us-cdbr-iron-east-04.cleardb.net
  password: 31w1dd54
  socket: /var/lib/mysql/mysql.sock
```

そしたら、mysqlに繋がった、、、とりあえずは助かった、、、
本来なら、```password: <%= ENV['DATABASE_PASSWORD'] %>```でheroku:configのDATABASE_PASSWORD(キー)が読み込まれて、31w1dd54(値)が取得されるはずなのに、、、
色々調べてみます。

注)本ページに出てくる、usernameや、password、host値は存在しない値です。
Flaskで「Hello World」を出力させる

##はじめに
[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしている松井です。
＊プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。

##Flaskのインストール
Flaskをpipでインストールします。

```
$pip install flask
$python3
>>> import flask
>>> flask.__version__
'1.0.2'
```

## プログラムを書く

```python:server.py
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello World'


if __name__ == '__main__':
    app.debug = True
    app.run(host='0.0.0.0', port=8000)
```

## プログラムを実行する


``$python3 server.py``をコンソールで実行します。
次に``Running on http://0.0.0.0:8000/``を見つけて、``http://0.0.0.0:8000/``の部分をコピーします。
それをGoogleで接続すると、``Hello World``と出力されます。

簡単でしたね。
``return``の部分をいじると、HTMLファイルなども表示できます。
ぜひ、いろいろ調べてみてください。
create-react-appのサーバとserverless offlineの開発でHTTPSを使う


ここら辺の続き。
https://qiita.com/celeron1ghz/items/bb3ac19ea837cb986e22


## 動機
普通に1台のPCで開発するぶんには、`create-react-app` の付属のサーバは `HTTPS=true yarn start` とするだけで一発でhttpsで起動できてべんり。

けどブラウザのカメラ機能を使うとなると話は別。

スマフォ等の実機で検証する際には `localhost` ではなく `192.168.1.2` 的なプライベートアドレスでアクセスしないといけなく、デフォルトで用意されている証明書は `localhost` 向けのためドメイン相違でエラーになります。

そもそも `localhost` でない場合は `https` でないと許可ダイアログが出る前にエラーになって何もできません。下記参照。

https://developers.google.com/web/fundamentals/media/capturing-images/?hl=ja

>警告:カメラに直接アクセスする機能は強力なので、ユーザーの同意を得るとともに、サイトを安全なオリジン（HTTPS）に配置する必要があります。

というわけなのでオレオレ証明書を作って配置する。


## オレオレ証明書を作る
ローカルの開発はIP変わる可能性があるのでshell fileにしておくとべんり。コマンドの意味はググってください。

```
DOMAIN=10.0.1.6
echo "generate cert for $DOMAIN..."

cd `dirname $0`
rm -f *.pem
openssl genrsa 2048 > key.pem
openssl req -subj "/C=JP/ST=Tokyo/L=Chuo-ku/O=Example K.K./OU=Example Section/CN=$DOMAIN" -new -key key.pem > csr.pem
openssl x509 -days 3650 -req -signkey key.pem < csr.pem > cert.pem

cat key.pem  >> server.pem
cat cert.pem >> server.pem
```


## クライアント側(create-react-app)
create-react-appで起動するサーバはnpm moduleの`webpack-dev-server`ですが
その証明書をどうやって置き換えるかといったら

https://github.com/facebook/create-react-app/issues/1411#issuecomment-347668164

直接置き換えろ！！という男気のある回答でした。

なので単純に `cp server.pem ../../client/node_modules/webpack-dev-server/ssl/` でおk。


## サーバ側(serverless)

証明書があるのであれば、`serverless.yml` でパスを指定するだけ！

```
custom:
  serverless-offline:
    httpsProtocol: .
```

簡単。

## 参照

https://qiita.com/bezeklik/items/6edfd4215a5456e37350
PHPの連想配列について(Progate)

##学習コース
**Progate**
PHP 道場コース Ⅰ → 連想配列の操作をマスターしよう9. → 全ての価格を表示しよう

##ソースコード

```php
<?php
$menus = array(
  array('name' => 'CURRY', 'price' => 900),
  array('name' => 'PASTA', 'price' => 1200),
  array('name' => 'COFFEE', 'price' => 600)
);

// この下にコードを書いてください
foreach ($menus as $menu) {
  echo $menu['name']."は".$menu['price']."円です";
  echo '<br>';
}

?>

---出力結果---
CURRYは900円です
PASTAは1200円です
COFFEEは600円です
```
##質問内容
```php
  foreach ($menus as $menu) { ~~~~}
```
`↑foreach内にあるこの[$menu]はどこからきたのでしょうか？
[$menus]は最初に定義されているのでわかるのですが。
例えばここが[$prices]なら[$price]といったように
単純に複数形「ｓ」を取ったものになるのでしょうか？
`
[雑メモ]Socialiteとabraham/twitteroauthで複数アカウントでツイート

ログインと登録がTwitterからのみのアプリを作成していて、
[こちら](https://qiita.com/daiki_44/items/fe11d57e53647f4b59f4)を参考にabraham TwitterOAuthと連携してみたものの、アクセストークンの取得がややこしい
Socialiteで簡単にログインと登録しつつ、取れるのでそれを用いてつぶやいてみる
Socialiteで参考にしたのは[こちら](https://qiita.com/Yuuki_Takahasi/items/e2ce2b256161ed5b61ba)

Socialiteで登録・ログイン→トークン取得→TwitterOAuthでツイートの流れ

```LoginController.php
class LoginController extends Controller
{
    use AuthenticatesUsers;

    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }

    /**
     * 認証ページヘユーザーをリダイレクト
     *
     * @return \Illuminate\Http\Response
     */
    public function redirectToProvider()
    {
        return Socialite::driver('twitter')->redirect();
    }

    /**
     * ユーザーのアクセストークンを取得する
     *
     * @return \Illuminate\Http\Response
     */
    public function handleProviderCallback()
    {

        try {
            $twitter_user = Socialite::driver('twitter')->user();
            //アクセストークン取得
            $token = $twitter_user->token;
            $token_secret = $twitter_user->tokenSecret;

            if ($twitter_user) {
                //ユーザーの取得または生成
                $user = User::firstOrCreate(['twitter_id' => $twitter_user->id]);
                //最新状態に更新
                $user->update(
                    [
                        'twitter_name' => $twitter_user->name,
                        'twitter_nickname' => $twitter_user->twitter_nickname,
                        'twitter_avatar_original' => $twitter_user->avatar_original,
                        'twitter_oauth_token' => $token,
                        'twitter_oauth_token_secret' => $token_secret
                    ]
                );
                Auth::login($user, true);
                return redirect()->route('activity.index')->with('success', 'ログインしました');
            }
        } catch (Exception $e) {
            return redirect()->route('top')->with('error', 'Twitterアカウント取得に失敗しました');
        }

        return redirect()->route('top')->with('erorr', 'エラーが発生しました。再度お試しください');
    }

    public function logout()
    {
        Auth::logout();
        return redirect()->route('top')->with('success', 'ログアウトしました');
    }
}

```

あとはログイン後のページでつぶやいてやる

```Hoge.php

public function tweet()
{
        $user = Auth::user();

        $twitter_user = new TwitterOAuth(
            config('twitter.consumer_key'),
            config('twitter.consumer_secret'),
            $user->twitter_oauth_token,
            $user->twitter_oauth_token_secret
        );
        //ツイートする
        $res = $twitter_user->post("statuses/update", [
            "status" => 'ツイート内容'
        ]);
}
```
だいぶスッキリしました

アクセストークンはセッションに入れるのと、保存するのどっちが良いのか...
[こちら](https://qiita.com/namizatop/items/439c0604ca15c1ef00cd)はServiceProviderを作成して、Facadeで呼び出せるようにしているけど、アクセストークンが変わる場合のうまい書き方が思いつかない

なにかアドバイスあればください
ABC - 010 - A&B&C

#AtCoder ABC 010 A&B&C
[AtCoder - 010](https://atcoder.jp/contests/abc010)

#A - ハンドルネーム

```java
	private void solveA() {
		out.println(next() + "pp");
	}
```

#B - 花占い

 - 最初分岐して・・・ってやったけど、よく考えたら2と3の最小公倍数の6の余りで分岐したほうが読みやすかった
    - コメントアウトしているif文の方もACではある

```java
	private void solveB() {
		int n = nextInt();
		int[] wk = IntStream.range(0, n).map(i -> nextInt()).toArray();
		int res = Arrays.stream(wk).reduce(0, (sum, i) -> {
			switch (i % 6) {
			case 1:
				return sum;
			case 2:
				return ++sum;
			case 3:
				return sum;
			case 4:
				return ++sum;
			case 5:
				return sum += 2;
			case 0:
				return sum += 3;
			}
			//			if (i % 2 == 1) {
			//				switch (i % 3) {
			//				case 0:
			//				case 1:
			//					return sum;
			//				case 2:
			//					return sum += 2;
			//				}
			//
			//			} else {
			//				switch (i % 3) {
			//				case 0:
			//					return sum += 3;
			//				case 1:
			//				case 2:
			//					return ++sum;
			//				}
			//			}

			return sum;
		});

		out.println(res);
	}
```

#C - 浮気調査

 - 三平方の定理を久しぶりに見た
 - ごり押しでも通るんだーって思った後に解法見たら楕円の定理でも解けるとな。。。わからん。。。

```java
	private void solveC() {
		int sX = nextInt();
		int sY = nextInt();
		int gX = nextInt();
		int gY = nextInt();
		int t = nextInt();
		int v = nextInt();
		int n = nextInt();

		for (int i = 0; i < n; i++) {
			int tmpX = nextInt();
			int tmpY = nextInt();
			double total = (Math.hypot(Math.abs(tmpX - sX), Math.abs(tmpY - sY))
					+ Math.hypot(Math.abs(tmpX - gX), Math.abs(tmpY - gY)));
			if (total <= t * v) {
				out.println("YES");
				return;
			}
		}

		out.println("NO");
	}
```
Python + mysql-connector-python の使い方まとめ

最近、docker と　python　ばかり弄り回しているのですが、pythonの構文ってすごい気持ちいがいいですよね。

プログラム経験がそこまで高くないので、今までは、Typescriptが一番気持ちがいいプログラム言語だと思っていたのですが、Pythonの楽な構文と見通しの良さとipythonでその場で実行してプログラムを確認できる環境にとても幸せを感じています。笑

ちょっとMYSQLを触っていたので、mysqlとpythonを繋げるmysql-connector-pythonの使い方を忘れないようにするためのメモ書きです。

参考サイト
https://basicincome30.com/python3-mysql-connector


```python
import mysql.connector as mydb

# コネクションの作成
conn = mydb.connect(
    host='hostname',
    port='3306',
    user='username',
    password='password',
    database='dbname'
)
````

これだけで、mysqlと接続完了接続。楽！！！
dockerを使っているなら、hostnameは、mysqlの起動しているドッカーコンテナのコンテナ名にすればOK。


```python
# コネクションが切れた時に再接続してくれるよう設定
conn.ping(reconnect=True)

# 接続できているかどうか確認
print(conn.is_connected())

```

mysqlは一定時間接続がないと止まるみたいなので、pingを送って接続が途切れないようにしておく。
接続確認も簡単。

# テーブル作成
```python
# DB操作用にカーソルを作成
cur = conn.cursor()

# id, name, priceを持つテーブルを（すでにあればいったん消してから）作成
table = 'test_table'
cur.execute("DROP TABLE IF EXISTS `%s`;", table)
cur.execute(
    """
    CREATE TABLE IF NOT EXISTS `%s` (
    `id` int auto_increment primary key,
    `name` varchar(50) not null,
    `price` int(11) not null
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
    """, table)
)
```

# データ挿入（INSERT)

```python
cur.execute("INSERT INTO test_table VALUES (1, 'BTC', 10200)")

# プレースホルダを利用して挿入
cur.execute("INSERT INTO test_table VALUES (2, 'ETH', %s)", (5000, ))
cur.execute("INSERT INTO test_table VALUES (%s, %s, %s)", (3 ,'XEM', 2500))
cur.execute("INSERT INTO test_table VALUES (%(id)s, %(name)s, %(price)s)", {'id': 4, 'name': 'XRP', 'price': 1000})

# executemanyで複数データを一度に挿入
records = [
  (5, 'MONA', 3000),
  (6, 'XP', 1000),
]
cur.executemany("INSERT INTO test_table VALUES (%s, %s, %s)", records)
```


# データ選択 (SELECT)
```python
cur.execute("SELECT * FROM test_table ORDER BY id ASC")

# 全てのデータを取得
rows = cur.fetchall()

for row in rows:
    print(row)

# 出力結果
"""
(1, 'BTC', 10200)
(2, 'ETH', 5000)
(3 ,'XEM', 2500)
(4, 'XRP', 1000)
(5, 'MONA', 3000)
(6, 'XP', 1000)
"""

# 1件取得
cur.execute("SELECT * FROM test_table WHERE name=%s", ('BTC', ))
print(cur.rowcount)
print(cur.fetchone())

# 出力結果
"""
1
(1, 'BTC', 10200)
"""
```



# データ更新 (UPDATE)・データ削除 (DELETE)

```
# UPDATE
cur.execute('UPDATE test_table SET name=%s WHERE id=1', ('ビットコイン',))
cur.execute('UPDATE test_table SET name=%s WHERE id=%s', ('イーサリアム', 2))

# DELETE
cur.execute('DELETE FROM test_table WHERE id = 3')
```

# コネクションを閉じる

```python
# DB操作が終わったらカーソルとコネクションを閉じる
cur.close()
conn.close()
```

mysql-connector-pythonのいいところは、commitしないくてもデータベースに反映されるところがいいね。


今後はPythonメインでプログラムを書いていきたいから、徹底的に覚えていこう。
golang + vscode + bingo(gopls) でコード補完を実現する

ある日突然コード補完が効かなくなり調べていると、
「[gocode やめます(そして Language Server へ)](https://mattn.kaoriya.net/software/lang/go/20181217000056.htm)」
を見つけました。

コード補完が無いと辛いので、bingo(gopls) を導入しました。
本記事はその備忘録です。

## 前提条件

- macOS High Sierra
- fish
- **$GOPATH 以下で作業しています。**
- Go 1.12 以上
  -  brew & goenv を使用している場合 1.12beta までしか対応していません。(**2019/05/23時点**)<br>
  `brew install(upgrade) go` で直接インストールし、goenv では system を選択しました。
- vscode と https://github.com/Microsoft/vscode-go はインストール済みです。
  - `> Go: Install/Update Tools` で各ツールもインストール済みです。<br>
  元の gopls もインストールされますが、後ほど bingo に置き換えます。

## 環境変数の確認

fish の例です。
1行目は goenv の設定です。使用していない人は不要です。
Go1.13 以降で `GO111MODULE=on` がデフォルトになった場合は最終行も不要です。

```shell:config.fish
status --is-interactive; and source (goenv init -|psub)
set -x GOPATH ~/go
set -x PATH $GOPATH/bin $PATH
set -x GO111MODULE on
```

## bingo(gopls) のインストール

https://github.com/saibing/tools#install に記載されているインストールコマンドを実行します。
`go install` すると、vscode 上からインストールした `$GOPATH/bin/gopls` が入れ替わります。

## vscode の設定

settings.json に以下の設定を追加します。

https://github.com/saibing/tools#vscode-go

`"gopls"` を設定すると、vscode のエラーが出ますが、特に問題ないそうです :sweat_drops: 

https://github.com/saibing/bingo/issues/181#issuecomment-485150495
>VSCode will complain but it should still work. Once we have a stable set of configs for gopls, we will merge them with the VSCode extension so that you don't get that error message.

そのうち修正されるようです。

## 動作確認

vscode を再起動してください。
`> Developer: Reload Window` ではうまくいかない？ことがありそう？です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61513/e39fc15b-3902-8486-ade5-0222469eb193.png)

このようにコード補完されます :smiley: 

動作が少し重いので、適時 `> Developer: Reload Window` してください。
また、「出力」でエラーなども確認できます。gopls を選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61513/4151c37b-52c2-e220-3e00-e489b4759dc2.png)

hover 時にエラーが出ることがあります。

## "Request textDocument/definition failed" エラーが出る場合

自身で作成したコードの補完が効かない事があります。
https://github.com/golang/go/issues/31492

リポジトリのトップに go.mod がないのが原因？のようです。
`.code-workspace` ファイルを設置して `folders` を設定します。

「[VS Codeのワークスペース](https://qiita.com/YuichiNukiyama/items/ef16a0219f46ea03a045)」を参考にしました。

## 参考記事

- https://twitter.com/mattn_jp/status/1085682458924732416
  - golsp が gopls にリネームされたようです。
- https://github.com/saibing/bingo
  - `golang/tools` を フォークした `saibing/tools` にこのリポジトリが移植されている？ようです。
- [Golang開発環境を作成する(module対応) - Ubuntu16.04/VSCode](https://qiita.com/ochipin/items/cae787d75ae91247c722)
- [Go get でインストールした外部ライブラリをきれいに削除する方法](https://qiita.com/aintek/items/4883a554ec50eaade51a)
  - gocode、godef などを削除しました。
- [go installコマンドについて](http://cuto.unirita.co.jp/gostudy/post/command-go-install/)
C/C++でファイルをロードしてコピーすることをした

簡単なゲームを作る際に、ファイル選択ダイアログからファイルを選ばせて、それをdatフォルダにコピーするという事がしたかったのでしました。
その時やった事を書きます。開発環境はVisual Studio2019になります。
あと、基本的にwindows.hとfstreamのインクルードが必要です。
##最初に
ファイルを選択する際に、いつも相対パスを使っていたのですが、どうやらファイル選択ダイアログでファイルを選んだあと、自身のディレクトリが動いてしまうという事を知らずにそこそこ詰まってしまいました。
なので、プログラムが一番最初に動いたときに絶対パスを保存しておいて、そこからファイル指定もろもろをするといいと思いました。

```c++:get_thisfile_path.cpp
//一つ目にはパスの長さの最大値、システムがMAX_PATHを定義してるので再定義は必要ないです
//二つ目は絶対パスの文字列を入れる変数を入れます
GetCurrentDirectory(MAX_PATH,this_abs_path); 
```
##ファイル選択ダイアログでファイルのパスを取得
```c++:get_file_path.cpp
TCHAR select_file_path[MAX_PATH];
OPENFILENAME ofn;

//構造体の情報を入れる
ofn.IStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hWnd;
ofn.lpstrInitialDir = this_abs_path; //初期位置
ofn.lpstrFile = select_file_path; //選択されたファイルのパスを格納
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = TEXT("wavファイル(*.wav)\0*.wav\0mp3ファイル(*.mp3)\.mp3"); //開くファイルの拡張子等指定
ofn.lpstrTitle = TEXT("音楽ファイルを選択"); //説明文を入れられる
ofn.Flags = OFN_FILEMUSTEXIST;

if(GetOpenFile(&ofn)){
    //もろもろの処理、今回の場合音楽のパスが
    //select_file_pathに入っている。
}
```

##ロードしたファイルをコピー
```c++:cpy_file.cpp
//this_abs_pathの文字列があれば、ここでほぼ相対パスだと思って使える
std::string save_file_path = this_abs_path + "/dat/hogefuga.wav";

//コピー元ファイル、コピー後ファイル
//三つめがTRUEだと上書き禁止,FALSEだと上書きする
if(!CopyFile(select_file_path,save_file_path,FALSE)){
  //エラー発生時はこれでエラーコードが見れる
  DWORD dwError = GetLastError(); 
}
Are Complicated Essays Giving You A Hard Time?

Singapore universities are quite strict when it comes to assessing essays. Many students find it difficult to score an A+ in essays. Contact MyAssignmenthelp.com and leave all your academic worries at bay. We provide unmatched quality online essay help to students of all education levels. From research to the structure, we take care of all the essay writing aspects with utmost precision.

You may find a plethora of online essay help providers. Not all of them can meet your expectations. We, on the other hand, aim at exceeding your expectations through dedication, punctuality and quality work.

Singapore universities may assign different types of essays to the students. Each essay has specific guidelines and you need to follow the rules strictly. Other essay help providers in Singapore usually specialize in two to three types of essays. At MyAssignmenthelp.com, you can get help with all types of essays right under one roof.

Our eminent essay writers are familiar with all the guidelines of Singapore Universities. You don’t have to worry about losing marks when we are here to tackle your paper. Check out the most common types of essays that we take care of at MyAssignmenthelp.com:

Persuasive essays- Our writers include relevant facts, evidence and examples to write a persuasive essay. We make sure your readers are convinced to believe your perspective on the given topic. Have a word with our experts to get the best online essay help for persuasive essays.

Descriptive essays- Nobody can beat our essay writers when it comes to descriptive essays. We apply the five common senses in the essay logically to satisfy the reader. Your readers can get a clear picture of what the topic is about through the essay. Get online essay help from us and make a fantastic impression on your professors.

Critical essays- Our writers are experienced enough tanalyzese a topic critically and come up with relevant arguments. We usually break down the topic into several parts and explain how the parts relate to each other or as a whole. We consider both s, des of an argument to construct an essay devoid of any loopholes.
Besides these, you can get essay help for narrative, expository, compare & contrast, causes& effects, admission and analytical essays. Do you need essay help for the format of your paper? Our writers are flexible with all the essay formats as per the rules of your University. Let us help you!

Get more information here:- https://myassignmenthelp.com/sg/essay-help.html
TeXworksで，TeXの文章をpdfにコンパイルできない(2019/05頃)

# 症状
+ [TeXインストーラ3](https://www.ms.u-tokyo.ac.jp/~abenori/soft/abtexinst.html)を使いwindows10上にTeXの環境を構築した
+ TeXworksを起動し，タイプセットをpdfplatexに設定し，pdfにコンパイルしようとしても，エラーで止まる
    + 2019年の4月上旬にインストーラを使い，インストールした人は問題なく使えている


# 原因
+ TeXworksが使っているw32texのサーバーから，pdfplatex.batが削除されたから
    + [w32texサーバーのchange log](http://w32tex.org/ChangeLog)の2019/04/29
    + TeXworksなら，代わりにptex2pdfを使うようにと書いてある

+ ptex2pdfはTeXworks上でタイプセットをpdfpTeXにすると使用できる
    + pdfpTeXでlatexファイルをpdfに変換しようとしても，エラーが出て変換できない


# 解決方法
## ptex2pdfを使う
+ TeXworksのデフォルトの設定では，pdfpTeXではLaTeXが変換できないので，変更
    + TeXworksの[編集] > [設定] > [タイプセット] を表示
    + pdfpTeXを選択し，[編集]をクリック
    + 引数に -l を追加し，引数の一番上に動かす
        + 引数 -l は変換するファイルがlatexであるときに必要

+ 設定の変更後，タイプセットをpdfpTeXにし，実行するとpdfに変換できる


## コマンドプロンプトから実行する
+ バッチファイルがないだけなので，コマンドを直接打てば，変換できる

```
platex hoge.tex
dvipdfmx hoge.tex
```

# 試したけどだめだった方法
+ 削除されたpdfplatex.batを作る
    + 保存場所は/w32tex/bin/pdfplatex.bat
    + バッチファイルの内容は[TeX Wiki](https://texwiki.texjp.org/?%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88)を参考

    + エラーが出てだめだった
    + 原因はわからない


---
# あとがき
この記事を書いた人は，macOS，linuxユーザーなので，現在手元にTeXworksがインストールされたPCを持っていません．2019年の５月頃に知人のPCにTeXworksをインストールしたときの記憶を頼りに書いているので，誤表記が若干あるかもしれないです．
nyagosでビットマップ表示

![nyagos.bmp.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52493/7abbd58d-a58a-9d58-d142-cae507725977.gif)

エスケープシーケンスの背景色で描画してみた。
24bitカラーと8bitカラーだけ、パースも適当だけど・・・

環境はWindows10(1903) + Windows標準のコマンドプロンプト + nyagos

最初、1byteずつ読み込んでいたんだけど、どうも取りこぼしているようだったので
最初に全部読み込んでからパースしてます。

```lua
nyagos.alias.bmp = function(args)
  local bmp = io.open(args[1], 'r'):read('*a')

  -- Headr
  local p = 1
  p = p + 2 -- BM
  p = p + 4 -- File Size
  p = p + 2 -- Reserved
  p = p + 2 -- Reserved
  local offset = bmp:byte(p, p + 1)
  p = p+ 1
  offset = offset + bmp:byte(p, p + 1) * 0x100
  p = p + 1
  offset = offset + bmp:byte(p, p + 1) * 0x10000
  p = p + 1
  offset = offset + bmp:byte(p, p + 1) * 0x1000000
  p = p + 1
  p = p + 4 -- Info Header Size
  local width = bmp:byte(p, p + 1)
  p = p + 1
  width = width + bmp:byte(p, p + 1) * 0x100
  p = p + 1
  width = width + bmp:byte(p, p + 1) * 0x10000
  p = p + 1
  width = width + bmp:byte(p, p + 1) * 0x1000000
  p = p + 1
  local height = bmp:byte(p, p + 1)
  p = p + 1
  height = height + bmp:byte(p, p + 1) * 0x100
  p = p + 1
  height = height + bmp:byte(p, p + 1) * 0x10000
  p = p + 1
  height = height + bmp:byte(p, p + 1) * 0x1000000
  p = p + 1
  p = p + 2 -- Plane. always 1
  local bits = bmp:byte(p, p + 1)
  p = p + 1
  bits = bits + bmp:byte(p, p + 1) * 0x100
  p = p + 1
  local is24bit = false
  local is8bit = false
  if bits == 24 then
    is24bit = true
  elseif bits == 8 then
    is8bit = true
  else
    print("Unsupported format")
    return
  end
  p = p + 4 -- Compress
  p = p + 4 -- Data Size
  p = p + 4 -- Resolution
  p = p + 4 -- Resolution
  local palleteSize = bmp:byte(p, p + 1)
  p = p + 1
  palleteSize = palleteSize + bmp:byte(p, p + 1) * 0x100
  p = p + 1
  palleteSize = palleteSize + bmp:byte(p, p + 1) * 0x10000
  p = p + 1
  palleteSize = palleteSize + bmp:byte(p, p + 1) * 0x1000000
  p = p + 1
  p = p + 4 -- Important Color
  local pallete = {}
  for i = 1, palleteSize, 1 do
    pallete[i] = {}
    pallete[i][1] = bmp:byte(p, p + 1);
    p = p + 1
    pallete[i][2] = bmp:byte(p, p + 1);
    p = p + 1
    pallete[i][3] = bmp:byte(p, p + 1);
    p = p + 1
    pallete[i][4] = bmp:byte(p, p + 1);
    p = p + 1
  end
  p = offset + 1

  -- Data
  local img = {}
  for j = 1, height, 1 do
    img[height-j+1] = {}
    local r, g, b
    for i = 1, width, 1 do
      if is24bit then
        b = bmp:byte(p, p + 1)
        p = p + 1
        g = bmp:byte(p, p + 1)
        p = p + 1
        r = bmp:byte(p, p + 1)
        p = p + 1
      elseif is8bit then
        local pp = bmp:byte(p, p + 1)
        p = p + 1
        if pp ~= nil then
          b = pallete[pp + 1][1]
          g = pallete[pp + 1][2]
          r = pallete[pp + 1][3]
        end
      end
      img[height-j+1][i] = '\027[48;2;' .. r .. ';' .. g .. ';' .. b .. 'm  \027[49m'
    end
    -- padding
    if is24bit then
      p = p + width % 4
    elseif is8bit then
      p = p + (width * 3) % 4
    end
  end
  for _, r in pairs(img) do
    for _, c in pairs(r) do
      nyagos.write(c)
    end
    nyagos.write('\n')
  end
end
```
uGUIで動的にサムネイルを生成する

# やりたいこと

- ステージ一覧で、ステージマップのサムネイルを動的に生成して張りつけたい。
    - 一覧される各要素は、動的に生成され、レイアウトグループで配置されます。
- uGUIで、動的にSpriteを生成してImageに貼り付けます。

# やったこと

- サムネイルの生成は時間がかかるので、非同期に行います。
- 個々のサムネイルを自律的に生成させます。

```cs:
private IEnumerator MakeThumbnail () {
	this.Loading.SetActive (true); // クルクルを表示
	this.Thumbnail.gameObject.SetActive (false); // サムネを非表示
	yield return null;
	var size = Mathf.Max (this.Level.Width, this.Level.Height); // 縦横大きい方
	var dx = (size - this.Level.Width) / 2; // 中央寄せのため横のパディング
	var dy = (size - this.Level.Height) / 2; // 中央寄せのため縦のパディング
	this.Texture2D = new Texture2D (size, size); // テクスチャを生成
	for (var y = 0; y < size; y++) {
		for (var x = 0; x < size; x++) {
			var color = this.Level.Matrix [x - dx, y - dy].Color; // 色を取得 (範囲外は自動判別)
			this.Texture2D.SetPixel (x, size - 1 - y, color); // 色を描き込む
			yield return null;
		}
	}
	this.Texture2D.Apply ();
	this.Texture2D.filterMode = FilterMode.Point;
	this.Thumbnail.sprite = this.Sprite = Sprite.Create (this.Texture2D, new Rect (0, 0, size, size), new Vector2 (0.5f, 0.5f));
	this.Thumbnail.gameObject.SetActive (true); // サムネイルを表示
	this.Loading.SetActive (false); // クルクルを非表示
}

// 自分が消えるときには、作ったデータも消す
private void OnDestroy () {
	if (this.Texture2D) { Destroy (this.Texture2D); }
	if (this.Sprite) { Destroy (this.Sprite); }
}
```

# 環境

- unity 2018.4.0f1