OmniAICreator/Qiita-1.07M huggingface dataset:
TypeScript, plotlyで3dグラフを描画する

# TypeScript, plotlyで3dグラフを描画する
vueを使って簡易的なデータの可視化ツールを作ろうとした際にハマったので
忘備録としてまとめる。

なお、普段はバックエンド側が主流でフロントエンドの実務経験はありません。
そんなレベルなので、もし間違いや改善点等あればご指摘いただけると幸いです。

## TL;DR
- TypeScript(vue/cli3.0環境)で型定義による補完を効かせながらコーディングしたい
- plotly.js, @types/plotly.js の組み合わせで2D散布図はプロット出来たが3D散布図はWebGLのエラーが出て不可
- plotly.js-distを使うと3D散布図まで表示出来たが、型定義ファイルがなく補完が効かない
- plotly.js-distに@types/plotly.jsのindex.d.tsをコピーして使用したところうまくいった。

## プロジェクト作成
プロジェクトはvue/cliを使用して作成します。
node.jsはインストール済みとします。

適当なフォルダで

```shell
npm install -g @vue/cli
```

でvue/cliをインストール。
続いて、

```shell
vue create plotly-app
```

でプロジェクト作成。
なお、マニュアルインストールを選択し、babel,typescript,をインストール。
デコレーターやtslintのインストールなどはお好みで。

## plotlyのインストール
[AngularでPlotlyのグラフを描画してみた](https://blog.brains-tech.co.jp/entry/2018/07/24/133401)
[Plotly.js](https://plot.ly/javascript/)

を参考にplotly.js、@types/plotly.js をインストールしscatterグラフを作成。
2Dグラフは問題なく作成できたが、3D Scatter を作成しようとしたところ、
`3d webgl is not supported`
がが表示されて失敗。
[Can't register module scatter3d #2502](https://github.com/plotly/plotly.js/issues/2502)
にもあるように、何人かは同様の現象が出ているようだが解決はしていない模様。

## plotly.js-distの使用
公式のページから[github](https://github.com/plotly/plotly.js)に飛んでみると、
`plotly.js-dist`を使用しろとのこと。
言われるがままにplotly.js-distをインストール。

- plotly.jsのアンインストール

```shell
npm uninstall plotly.js
```

- plotly.js-distのインストール

```shell
npm install plotly.js-dist
```

読み込みライブラリを変更

```ts
// import * as plotly from 'plotly.js';  // <- これを
import * as plotly from 'plotly.js-dist';  // <- これに変える
```

これで、3D Scatterグラフは描画できた。
でも、型定義ファイルは無いのでエラー出るし（でもトランスパイルは行われる）
補完は効かないしでとてもやりづらい。そのため、何とか型定義ファイルを使用できないか頑張ってみた。

## 型定義ファイルをコピーする
plotly.jsはアンインストールしているにも関わらず、importをplotly.jsのほうに変更するとwebgl のエラーが出てまた描画できなくなった。ここは理由がわからなかったが、@types/plotly.js/　にあるpackage.jsonとかがなんか関係してるのかな？（よくわかってません。詳しい人教えてください）
でも、さらっと型定義ファイル見た感じでは、結構丁寧に作られててすごいなという印象。なので、何とかこの型定義ファイルを使いまわそうと思い、plotly.js-distのフォルダへコピーしてみたところうまく動きました。
具体的にコピーしたのは以下。

`node_modules/@types/plotly.js/index.d.ts` → `node_modules/plotly.js-dist/index.d.ts`

今のところ、型補完も効くし、ビルド後も正常に動いていてとりあえずは使えている感じです。
COTOHA APIを使ってゲンシジン語と現代人語の対訳JSONを作る

# 必要なもの
* [COTOHA API](https://api.ce-cotoha.com/contents/ "COTOHA API公式ページへのリンクです")
* Python 3 (Python 3.7.2でやりました)
* 現代人語で書かれたテキスト（1センテンスが1行になっているものが望ましい)

# 現代人語で書かれたテキスト
```Meros.txt
佳き友は、気をきかせて教えてやった。
メロス、君は、まっぱだかじゃないか。
早くそのマントを着るがいい。
```
この記事では上の三行でやります。
もっと多くのテキストは「[構文解析のために1センテンス1行のテキストを作る](https://qiita.com/sgigagaeru/items/f38fdcf547e81dcb8642 "Qiitaの記事へのリンクです")」で作ってます。

# 対訳JSONの作り方
1. 上の三行を`Meros.txt`として保存する。
1. [COTOHA API](https://api.ce-cotoha.com/contents/ "COTOHA API公式ページへのリンクです")のアカウントを取得する。
1. 「[オレ プログラム ウゴカス オマエ ゲンシジン ナル] (https://qiita.com/Harusugi/items/f499e8707b36d0f570c4 "Qiita記事へのリンクです")」中のコードを`genshijin.py`とし、CLIENT_ID, CLIENT_SECRETを記入して保存しておく。
1. 次のコードを動かす

```python:make_json.py

from genshijin import auth, parse, CLIENT_ID, CLIENT_SECRET
from json import dumps

f = open('Meros.txt')
lines = f.read()
f.close()

access_token = auth(CLIENT_ID, CLIENT_SECRET)
l = []

for line in lines.splitlines():
  parse_document = parse(line, access_token)
  result_list = list()
  for chunks in parse_document['result']:
    for token in chunks["tokens"]:
      if token["pos"] != "格助詞" and token["pos"] != "連用助詞" and token["pos"] != "引用助詞" and token["pos"] != "終助詞":
        result_list.append(token["kana"])

  d = {}
  d['utsusemi'] = line
  d['genshijin'] = ' '.join(result_list)
  l.append(d)

print (dumps(l, ensure_ascii=False, indent=2))
```

# 実行結果
```json
[
  {
    "utsusemi": "佳き友は、気をきかせて教えてやった。",
    "genshijin": "ヨ キ トモ  キ キカセ テ オシエ テ ヤ ッ タ "
  },
  {
    "utsusemi": "「メロス、君は、まっぱだかじゃないか。",
    "genshijin": " メロス  キミ  マッパダカ "
  },
  {
    "utsusemi": "早くそのマントを着るがいい。",
    "genshijin": "ハヤク ソノ マント キ ル ガ イ イ "
  }
]
```

# 《走れメロス》全文の対訳JSON
[https://dazai-cotoha.herokuapp.com/reading/json/Meros.json](https://dazai-cotoha.herokuapp.com/reading/json/Meros.json "JSONファイルへのリンクです")にあります。御自由にお使いください。
jsのオブジェクトのプロパティにアクセスするスピードを比べてみた

偉い人のコードを読んでいると、オブジェクトのプロパティにアクセスする際に生存期間が短いところでもわざわざ変数を定義して参照しているケースがあったので、これはもしや速くなるのかということで試してみました。
リーダブルコード的には説明変数という意味もあるのかもしれませんが。
実行はchrome v.72です。

5回のプロパティへのアクセスを含むiterationを1000回回して経過時間を測りました。
それぞれ10回のtryの平均時間をconsole.logで出力します。

```js:使ったコード
var domo = {hoge: 'unu'};
var count;
var times;
var start;
var results;

results = [];
for (times = 0; times < 10; times ++) {
  start = performance.now();
  for (count = 0; count < 1000; count++) {
      var hm = domo.hoge;
      hm + hm;
      hm + hm;
      hm + hm;
      hm + hm;
      hm + hm;
  }
  results.push(performance.now() - start);
}
console.log("var", results.reduce((a,c) => a + c, 0) / results.length);

results = [];
for (times = 0; times < 10; times ++) {
  start = performance.now();
  for (count = 0; count < 1000; count++) {
      domo.hoge + domo.hoge;
      domo.hoge + domo.hoge;
      domo.hoge + domo.hoge;
      domo.hoge + domo.hoge;
      domo.hoge + domo.hoge;
  }
  results.push(performance.now() - start);
}
console.log("prop", results.reduce((a,c) => a + c, 0) / results.length);

```

結果。一応早いぽい！

```

var 0.18199999998323618
prop 0.3185000000055879

var 0.18700000001117587
prop 0.24299999994691462

var 0.18299999996088445
prop 0.24899999992921948
```

念の為、プロパティへのアクセスを1行まで減らしてみましたが、これでも早いぽいです。

```

var 0.07450000003445893
prop 0.11049999992828816

var 0.06550000002607703
prop 0.11349999995436519

var 0.06550000002607703
prop 0.11349999995436519
```
Elixir~Enum総ざらい3回目~

＃ここまでのあらまし

[Elixir~Enum総ざらい2回目~](https://qiita.com/kmizuno0211/items/b059e2a82b4e2a10f26c) のつづきです。

#Enum.drop

```elixir

Enum.drop([1, 2, 3], 2)
[3]

Enum.drop([1, 2, 3], 10)
[]

Enum.drop([1, 2, 3], 0)
[1, 2, 3]

Enum.drop([1, 2, 3], -1)
[1, 2]
```

Twitterで"dropは総和ではなく指定したindexだけ要素を落とす関数ですよ。
マイナスインデックスはrubyからの慣習で-1はラストのインデックスを指します。"
とのアドバイスいただきました。

つまり、ゼロから数えてn番目より要素を落としている...?
-1の場合、3を省いて1,2を返している...?

正確な解釈はやや遠いようです。

#Enum.drop_every

```elixir
Enum.drop_every(1..10, 2)
[2, 4, 6, 8, 10]

Enum.drop_every(1..10, 0)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Enum.drop_every([1, 2, 3], 1)
[]
```

1個目の式は、1から10で2の倍数の数字を全て返しているように思えます。
ふたつ目の式は、第二引数がゼロなのでリストのすべての数字を返しているのかな？
これもやはり3番目の式でこれまでの仮定が崩れてしまいます。

これもやはりノリとして英文のドキュメントは読めるのですが(略

#drop_while

```elixir
Enum.drop_while([1, 2, 3, 2, 1], fn x -> x < 3 end)
[3, 2, 1]
Enum.drop_while([1, 2, 3, 4, 2, 1], fn x -> x < 4 end)
[4, 2, 1]
```

ここまで2つ連続で法則性がわからなかったので自分で式を作って理解を深めてみました。
第一引数のリストのうち、最初に第二引数の数字が出てきてからのリストの残りを出力する関数のようです。
ドキュメントを通じて全部わかりませんじゃ済まないので焦った...

#Enum.each

```elixir
Enum.each(["some", "example"], fn x -> IO.puts(x) end)
"some"
"example"
:ok: 

Enum.each(["kento", "mizuno"], fn x -> IO.puts(x) end)
kento
mizuno
:ok

```
引数の"some"と"example"をそれぞれ返し、:ok: を返しているようです。
自作の式でもだいたい同じ挙動ですね。

#Enum.empty?

```elixir
Enum.empty?([])
true

Enum.empty?([1, 2, 3])
false
```

これは簡単ですね。引数が空ならtrue、なにか要素があればfalseをかえします。



このようすで数日のうちにEnumの関数をすべて触ってみる予定です。
うまずたゆまず、頑張ります。
Kento Mizuno
SI企業でテスト経験しかなかった僕が自社開発のweb系エンジニアになった話


<h1>当時の状況・条件</h1>

+ 26歳の時にSir企業で６ヶ月間ほど働いた経験あり。
+ ただし単純なテスト業務のみで開発の経験はゼロ
+ 入社してから3ヶ月間ほどJavaの研修を受けて学習していた
+ 退職してから2年のブランクがありプログラミングの知識は抜けている
+ 28歳というweb系企業で働くとしては高い年齢


<h1>転職活動をする上で持っていたマインド</h1>
<b>1.言語はPHPまたはRubyを選ぶ
2.選んだ言語でプログラミング基礎知識を身につける
3.求人サイトを使い'自分を作りすぎず'多くの会社の面接を受ける</b>

PHPまたはRuby以外の言語だと需要が少なすぎるので、web系企業で働きたいのであればこの2択。


また、勉強に終わりはありません。勉強しようと思えばいくらでも勉強できてしまうので、必ず期限を作って取り組むべき。ドットインストールでも本でもプログラミングスクールでもどこでもいいです。僕は研修を受けた経験があるのでprogateで1ヶ月間だけPHPを勉強しました。完全な未経験者であれば3ヶ月で十分かと。

そして会社には合う合わないが絶対あります。会社の雰囲気に合わせようと努力すると、消耗してストレスになってしまいます。なので、<b>あまり自分を作りすぎずに面接に臨みました。</b>もちろん内定率は下がりますが想定の範囲内。せっかく入社してもすぐやめてしまえば、会社にとっても社員にとってもお互いデメリットでしかないです。


<h1>自社開発企業にウケの良い職務経歴書</h1>
web系会社は、<b>自分でサイトを立ち上げたり、運用したりする経験があると評価してくれます。</b>僕は学生時代にアフィリエイトや転売ビジネスをかじったことがあり、その際にワードプレスの運営やサーバー・ドメイン契約などを経験したので、そこの部分を記載して面接に臨みました。


![スクリーンショット 2018-11-24 19.10.47.png](https://qiita-image-store.s3.amazonaws.com/0/302052/bea0a146-81e1-8759-10d7-d227376e5e01.png)


![スクリーンショット 2018-11-24 19.10.55.png](https://qiita-image-store.s3.amazonaws.com/0/302052/580b3527-b98c-b2ca-888c-6a11f9bf434b.png)

正直、転売やアフィリなどやっていても大したITスキルなど身につかないと思います（実際に僕がそうだった）。転売はただ単にアマゾンやヤフオクに出品するだけだし、アフィリエイトのブログ更新も簡単な操作で出来てしまうので。したがって面接当時はサーバーやネットワーク、プログラミングのスキルの知識なんて皆無でした。

ですが、自社開発のweb企業は、<b>自分なりにぐぐってサービスを０から立ち上げる経験</b>を評価しています。（入社後に実際に判断ポイントを聞いた）

PHPやRubyを独学したあと自分でサービスを立ち上げた経験があれば採用率は高くなります。

<h1>0からサービスを立ち上げた経験がない人</h1>
僕はアフィリや転売の経験があるので別ですが、もし何もサービスを立ち上げたことがない人であれば、独学して作ったwebアプリケーションをHerokuに公開し、転職用のポートフォリオとして活動するのがいいですね。わざわざサーバー契約してwordpressで公開するのはコスパが悪いので。<b>ポートフォリオ=0からサービスを立ち上げるマインドや力がある</b>という事で、企業はそこを見ています。優良なweb系企業に就職する確率を上げるために、ポートフォリオを作ってから面接に望むのがオススメ。



[入社して3ヶ月後に作ったポートフォリオ](https://qiita.com/shou_/items/a89f5d26b9c8f7f28d12 "入社して3ヶ月後に作ったポートフォリオ")
spring error メモ - バリデーションエラーの際フォームクラスのインスタンスがNULLになる


error log

```
Neither BindingResult nor plain target object for bean name 'domainReportCreateForm' available as request attribute
```


html

```html
<form id="createForm" th:attr="action=@{/domainReport/create}" th:object="${domainReportCreateForm}" method="post" enctype="multipart/form-data">
```

controller

```java
	public String create(@Validated @ModelAttribute DomainReportForm domainReportCreateForm, BindingResult result,
			Model model) {
```

解決

```java
	public String create(@Validated @ModelAttribute("domainReportCreateForm") DomainReportForm domainReportCreateForm, BindingResult result,
			Model model) {
```

* クラス名とインスタンス名が違うときは明示的にしなければいけない
* パラメータ順序も大切

参考

https://stackoverflow.com/questions/35318401/html-form-validation-using-thymeleaf-not-working-spring-boot/35330380#35330380

I think the trouble because you placed BindingResult incorrect. Replace it with MultipartHttpServletRequest, it must be after the validating parameter:

```
@RequestMapping(method= RequestMethod.POST, value = "/create")
public String createTest(@Valid @ModelAttribute("testForm") TestForm testForm,  BindingResult bindingResult, MultipartHttpServletRequest request) throws IOException {
if (bindingResult.hasErrors()) 
    return "createtestform";
```
不要なSwiftコードにWarningを出す【Periphery】

# はじめに

使われていないコードをずっとプロジェクトに残しておくことは技術的負債になります。

 - 使われていないコードを読む時間のムダ
 - 使われていないコードを修正する時間のムダ
 - 使われていないコードをビルドする時間のムダ

使われていないコードは**「到達不能コード」、「デッドコード」**とも呼ばれます。
不要なコードは書かない、という**「YAGNIの原則」**はデッドコードにも適用されるべきです。

https://ja.wikipedia.org/wiki/YAGNI
> "You ain't gonna need it"[1]、縮めて YAGNI とは、機能は実際に必要となるまでは追加しないのがよいとする、エクストリーム・プログラミングにおける原則である。

また、間違った実装により利用すべきコードを利用していない場合、**使われていないコードを知ることで間違った実装方法に気づける**というメリットもありそうです。

そこで、無償で利用できるPeriphery（ペリフェリー）というツールで**使われていないSwiftコードにWarningを出す**方法のご紹介をします。

# Peripheryとは

Periphery（ペリフェリー）はオープンソースとして提供されているデッドコードの分析ツールです。商用利用可能な**MIT License**で提供されています。

Githubリポジトリ: https://github.com/peripheryapp/periphery

例えば以下のようなものを検出できます。

 - 不要な型の検出（クラス、構造体、プロトコル）
 - 不要な関数とその引数、プロパティ
 - 不要なEnum、ケース
 - 不要なType aliases、associated types

PeripheryはCUIでの実行だけでなく、Xcodeに導入することで不要コードをWarningとしてハイライトすることも可能です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/113553/84607073-d2ca-1bc3-1141-f47145794c56.png)

Objective-Cと混在したプロジェクトでは、Objective-Cコードの利用有無は検出できないものの、一応`@objc`や`@objcMembers`などをみてObjective-Cで利用されていると判断してくれるようです。逆に未使用と判断されたものでもObjective-Cコードからの参照がある可能性があるのでここは注意が必要です。
https://github.com/peripheryapp/periphery?tab=readme-ov-file#objective-c

# Peripheryの導入と実行

Homebrewでの導入方法です。

```bash
# Homebrewのインストール（必要に応じて）
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

# Peripheryのインストール
brew tap peripheryapp/periphery
brew cask install periphery
```

CUIで実行する場合は以下のコマンドで実行できます。

```bash
periphery scan

# workspaceなど指定する場合
periphery scan --workspace MyApp.xcworkspace --schemes MyApp --targets MyApp
```

Xcode上で実行する場合は、**Aggregate Target**として別ターゲットに追加すると良いです。
Run Scriptでメインターゲットのビルド毎に実行することも可能ですが、実行に少し時間がかかってしまいます。

`File > New > Target...`を開き、`Cross-platform`内の`Aggregate`を選択します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/113553/bdfa1348-36ff-05cd-7f40-b3b9ce7b3dc7.png)

TargetのProduct Nameは「Periphery」などわかりやすいものにしておきます。

次に追加したTargetの`Build Phases`で`+`をクリックして、Run Scriptを追加します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/113553/44f9f527-5210-b3b5-893a-930b3dc29d76.png)

```bash
# Run Scriptの例（`--format xcode`オプションが必要）
periphery scan --workspace MyApp.xcworkspace --schemes MyApp --targets MyApp --format xcode
```

あとは作成したTargetに紐づくスキームを選択して実行するだけです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/113553/2c3f44e6-c423-7125-26f7-681c8c02bada.png)

# おわりに

試しに個人プロジェクトで試したところ、以下のような結果となりました。

 - 3500行（LOC）くらいのプロジェクトで実行時間は**90秒程度**（大きなプロジェクトでは数十分かかりました）
 - **43件**の不要コードを検出
 - **100行程度**のコードの削減に成功

また一部のコードではClassを抽象化するProtocolを定義したもののClassを直接利用していたため実装方法の誤りに気づくことができました。

他には[SwiftGen](https://github.com/SwiftGen/SwiftGen)で自動生成した画像リソースの取得コードが一部利用されていなかったため、画像リソースごと不要とみなして削除することができました。

より大規模なプロダクトではもっと効果を発揮しそうです。不要コードは気づかないうちに必ず溜まっていくものなので、こういったツールを利用してなるべくクリーンなコードを保ちたいです。
Django で model のプライマリーキーを設定する

Django で model を作成すると、id が　プライマリーキーになります。
テーブルの構造はこのようになります。

```text
MariaDB [django_city]> show columns from city_city;
+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| id         | int(11)     | NO   | PRI | NULL    | auto_increment |
| key        | varchar(10) | NO   |     | NULL    |                |
| name       | varchar(20) | NO   |     | NULL    |                |
| population | int(11)     | NO   |     | NULL    |                |
| date_mod   | date        | NO   |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+
```

primary_key=True　を設定すると、そのコラムが　プライマリーキーになり、 id は生成されなくなります。
次のように設定します。

```py:models.py
# ------------------------------------------------------------------
#
#	models.py
#
#					Feb/17/2019
# ------------------------------------------------------------------
from django.db import models

class City(models.Model):
	key = models.CharField(max_length=10,primary_key=True)
	name = models.CharField(max_length=20)
	population = models.IntegerField(default=0)
	date_mod = models.DateField()

	def __str__(self):
		return '<City: ' + \
			self.key + ', ' + self.name + '>'
# ------------------------------------------------------------------
```

これで出来るテーブルは次のようになります。

```text
MariaDB [django_city]> show columns from city_city;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| key        | varchar(10) | NO   | PRI | NULL    |       |
| name       | varchar(20) | NO   |     | NULL    |       |
| population | int(11)     | NO   |     | NULL    |       |
| date_mod   | date        | NO   |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
```

参考
[モデルフィールドリファレンス](https://docs.djangoproject.com/ja/2.1/ref/models/fields/)
CloudWatch Logsにslf4j/logbackでログを送付する単体Javaアプリ

忘れないうちにメモ。CloudWatch Logsにログを送付する仕組みを理解しようとサンプルを作っていたけど、参考にするサイトがなかなか見つからなかったので。

# 前提
1. なるべく作りたくない　→　GithubとかにあるOSSを利用
2. 最小限のコードで送付したい
3. Gradle対応

# 結果
こうなりました。

https://github.com/kojiisd/cloudwatch-logs-java-standalone

# 利用したOSS

cloudwatch-logback-appender
https://github.com/j256/cloudwatch-logback-appender

# 使い方
logback.xmlの内容を編集すればある程度自由にログを流しこめます。

```xml
    <appender name="CLOUDWATCH" class="com.j256.cloudwatchlogbackappender.CloudWatchAppender">
        <region>us-east-1</region>
        <accessKeyId>XXXXXXX</accessKeyId>
        <secretKey>XXXXXXX</secretKey>
        <logGroup>test-loggroup</logGroup>
        <logStream>test-logstream</logStream>
        <layout>
            <pattern>[%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - %msg%n</pattern>
        </layout>
        <maxBatchSize>32</maxBatchSize>
    </appender>
```

 ```accessKeyId``` や```secretKey``` は項目自体を削除すれば、実行マシンのAWSConfigを見に行くらしい（試してないけど）

# 実行結果
無事ログがCloudWatch Logsに出力されました。（ロググループやログストリームは存在しなければ作成してくれる）

![スクリーンショット 2019-02-17 19.18.35.png](https://qiita-image-store.s3.amazonaws.com/0/102769/72c31fb5-56e2-053c-5c84-9ac00fbf416a.png)

# 注意点
当たり前ですが、ライブラリの中でCloudWatch Logsにデータを送付するために、色々と初期化だったりデータ送付を行います。その処理はスレッド実行されるので、呼び出し元のロギング処理が終了してアプリが終了すると、自動的に子スレッド側も終了すわけで、ログがCloudWatch Logsに送付されません。（実際にはこんな単体アプリでのログ送付なんてないと思うのでそこまで気にすることではない気がしますが）OSS側のソースを見ていて気づきました。

それを回避するために、わざと実装の中にSleep処理を20秒ほど入れています。

# まとめ
注意点の部分さえハマらなければ、とても簡単に実現できました。
[React Native]Javaモジュールからハッシュを返す

React Nativeのバージョンは0.57.8。
前提条件としてReact NativeからAndroid向けのJavaモジュールの利用ができている事。

## TL;DR

`WritableMap`に変換して返す。

## 詳細

Java側では以下のように実装する。

```java
public class HogeModule extends ReactContextBaseJavaModule {
    :
    @ReactMethod
    public void getHash(Callback callback) {
        HashMap<String, String> hm = new HashMap<>();
        hm.put("first", "One");
        hm.put("second", "Two");
        hm.put("third", "Three");

        WritableMap map = new WritableNativeMap();
        for (Map.Entry<String, String> entry : hm.entrySet()) {
            map.putString(entry.getKey(), entry.getValue());
        }
        callback.invoke(map);
    }
    :
}
```

React Native側では以下のようにして受け取る。

```js
import {NativeModules} from 'react-native';
module.exports = NativeModules.Hoge;
:
      Hoge.getHash((map) => {
        console.log(map.first);
        console.log(map.second);
        console.log(map.third);
      });
:
```

`putString`の他に`putBoolean`や`putInt`など、[型に応じた`put`がある](https://github.com/facebook/react-native/blob/c86f59cb82c60cfbeb941d9bd73e9080a19c3042/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableMap.java#L18-L24)。

配列でも似たようなかたちで `WritableArray` というのがある。
ラズパイセットアップ～Lチカまで

#用意するもの
- RaspberryPi2 Model B
- ブレッドボード
- USB microB 電源アダプタ
- micro SD 16GB
- Ethernetケーブル
- ジャンパーワイヤー
- LED
- 抵抗1kΩ
- ラジオペンチ

#手順
##1.SDの用意
SDをフォーマット(FAT32)
https://www.disk-partition.com/jp/articles/how-to-repair-micro-sd-16gb-card-it-shows-31mb.html

Raspbianをインストール
https://qiita.com/Choke222/items/6f12f3f3a0eef10e94cb

##2.SSH接続
https://qiita.com/hikobotch/items/a33fc77114a4963cc68b

##3.Lチカ
以下の配線図を作成
https://qiita.com/t114/items/89be2c866724e193a5cb

以下の方法で手動Lチカ
https://tool-lab.com/2013/12/raspi-gpio-controlling-command-1/

```
$ sudo echo 23 > /sys/class/gpio/export
$ ls /sys/class/gpio/
export     gpio23/    gpiochip0/ unexport
$ cd /sys/class/gpio/gpio23
$ ls
active_low  device  direction  edge  power  subsystem  uevent  value
$ sudo echo out > directio
$ sudo echo 0 > value
$ sudo echo 1 > value
```
光った！少し感動。

##4.プログラムからLチカ
http://forestofazumino.web.fc2.com/turtlereal/turtlereal_gpio.html

```
$ mkdir workdir
$ cd workdir/
$ ls
$ vi Lchika.c
```
```Lchika.c
void main (){
  int fd = open("/sys/class/gpio/export", O_WRONLY);
  write(fd, "23", 2);
  close(fd);
  sleep(1);
  fd = open("/sys/class/gpio/gpio23/direction", O_WRONLY);
  write(fd, "out", 3);
  close(fd);
  fd = open("/sys/class/gpio/gpio23/value", O_WRONLY);
  while(1){
    write(fd, "1", 1);
    sleep(1);
    write(fd, "0", 1);
    sleep(1);
  }
  close;(fd);
}
```
```
$ gcc Lchika.c -o test
$ ls
$ ./test
```
1秒ごとに光った！
さくらvpsのCentOS7にdockerをインストールしたときの備忘録


## はじめに
最初は別記事を参考に`yum install` でdockerをインストールしたが、バージョンが古いものをインストールしてしまったため、最終的に、公式ドキュメントを参考に下記手順でやった結果、最新版が正常にインストールされました。

## 手順
###不要なdockerモジュールをアンインストール

```shell
$ sudo yum remove docker \
                docker-client \
                docker-client-latest \
                docker-common \
                docker-latest \
                docker-latest-logrotate \
                docker-logrotate \
                docker-engine
```

### repositoryを利用してインストール
#### インストール用のrepositoryのセットアップ

```shell
$ sudo yum install -y yum-utils \
                    device-mapper-persistent-data \
                    lvm2
```

#### 安定的なrepositoryを追加
```shell
$ sudo yum-config-manager \
     --add-repo \
     https://download.docker.com/linux/centos/docker-ce.repo
```

### docker CEをインストール
```shell
$ sudo yum install docker-ce docker-ce-cli containerd.io
```

### インストールするバージョンを確認
```shell
$ yum list docker-ce --showduplicates | sort -r

docker-ce.x86_64  3:18.09.1-3.el7                     docker-ce-stable
docker-ce.x86_64  3:18.09.0-3.el7                     docker-ce-stable
docker-ce.x86_64  18.06.1.ce-3.el7                    docker-ce-stable
docker-ce.x86_64  18.06.0.ce-3.el7                    docker-ce-stable
```

### バージョンを指定してインストール
```shell
$ sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io

#今回は下記のようにした
$ sudo yum install docker-ce-18.09.1 docker-ce-cli-18.09.1 containerd.io
```

### dockerを起動＆チェック
```shell
$ sudo systemctl start docker
$ sudo docker run hello-world
```

#### もし`sudo systemctl start docker`時に`failed`になる場合…
すでにdockerがインストールされている場合、`/var/lib/docker`をremoveしてください

```shell
$ sudo rm -rf /var/lib/docker
```

以上で、さくらvps環境にdockerをインストールできました。
何でもかんでもyumでインストールすればいいという意識を変える必要があるなというのと
インストール予定のモジュールのバージョンを確認することを意識したいと思います。

## 番外編
### dockerコマンドを`root`ユーザー以外も利用できるようにする場合
```shell
$ sudo groupadd docker
$ sudo gpasswd -a <username> docker
$ sudo systemctl restart docker
# 再ログイン
$ docker info
```

以上です。
Pythonでテーブルをスクレピングしてcsvに保存する

# はじめに
webサイトでスクレイピングをしたい。テーブルで書かれているところを必要なところだけ欲しいと思って、試しに以下のサイトでやってみたので、メモとして残します。

対象のサイトは以下になります。

[JR西日本宮島フェリー](http://jr-miyajimaferry.co.jp/timetable/)

# 画面を見てみる

<img width="952" alt="スクリーンショット 2019-02-17 18.36.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/137532/4cb14d6c-4711-1b90-4bcb-3b5eba1744b6.png">

htmlをソース表示で見てみる　　tableタグ一部抜粋

```html
<table cellpadding="0" cellspacing="0">
		
		<tr align="center"> 
		<th colspan="5" class="riku"><b>宮島口発</b></th>
		</tr>
		<tr align="center"> 
		<th>時</th>
		<th colspan="4">分</th>
		</tr>
		<tr align="center"> 
		<td><b>5</b></td>
		<td>&nbsp;</td>
		<td>&nbsp;</td>
		<td>&nbsp;</td>
	
		<td>&nbsp;</td>
		</tr>
	
		<tr align="center" class="b"> 
		<td><b>6</b></td>
		<td>&nbsp;</td>
		<td>25</td>
		<td>&nbsp;</td>
		<td>&nbsp;</td>
		</tr>
	
		<tr align="center"> 
		<td><b>7</b></td>
		<td>05</td>
		<td>&nbsp;</td>
		<td>40</td>
		<td>57</td>
		</tr>
```

こんな感じでテーブルが二つあるような構成になっています。
tableタグは二つ使われており、時間と分はtdタグで囲まれている状態です。
headerとなっているthは今回は不要とします。

# 環境
Python    3.6.5
requests  2.18.4
beautifulsoup4  4.6.0

Beautifulsoupというwebスクレイピングを簡単にできるモジュールがあります。
今回はこれを使えば割と簡単にできそう。


# コード

```ferry_scraping.py


import requests
from bs4 import BeautifulSoup
import csv

url = 'http://jr-miyajimaferry.co.jp/timetable/'
html = requests.get(url)
soup = BeautifulSoup(html.text,'html.parser')

def tableToCSV(filename, table):
    # 時間単位で１行としたいため
    rows = table.findAll('tr')
    
    with open(filename, 'wt', newline = '', encoding = 'utf-8') as f:
        writer = csv.writer(f)
        for row in rows:
            csvRow = []
            for cell in row.findAll('td'):
                csvRow.append(cell.get_text())

            # はじめのヘッダー部分のtrは行に含めないため
            if len(csvRow) > 0:
                writer.writerow(csvRow)

table_miyajimaguti_start = soup.find_all("table")[0] #　宮島口発
table_miyajima_start = soup.find_all("table")[1] #　宮島発

tableToCSV("ferry_miyajimaguti_start.csv", table_miyajimaguti_start)
tableToCSV("ferry_miyajima_start.csv", table_miyajima_start)

```

#  結果
うまく二つのCSVとして出力できました。一番左のカラムが時間です。

```ferry_miyajimaguti_start.csv
5, , , , 
6, ,25, , 
7,05, ,40,57
8,10,25,40,55
9,10,25,40,55
10,10,25,40,55
11,10,25,40,55
12,10,25,40,55
13,10,25,40,55
14,10,25,40,55
15,10,25,40,55
16,10,25,40,55
17,10,25,40,55
18,10,25,45, 
19,15, ,45, 
20, ,27, , 
21,10, , , 
22,00, ,42, 
```


```ferry_miyajima_start.csv
5, , ,45, 
6, , ,40, 
7, ,20, ,55
8,10,25,40,55
9,10,25,40,55
10,10,25,40,55
11,10,25,40,55
12,10,25,40,55
13,10,25,40,55
14,10,25,40,55
15,10,25,40,55
16,10,25,40,55
17,10,25,40,55
18,10,25,40, 
19,00,30, , 
20,00, ,42, 
21, ,25, , 
22,14, , , 
 
```

# 最後に
わりと簡単にできました。サイトの構成が変わるようなものはメンテナンスしなきゃいけなそうですが、
このサイトに関しては、基本はこの形かなと思います。
同様なサイトは同じような形で流用できるかと思うので、参考にしてください。
ふむふむlinuxのパッケージ管理

linuxっていっぱいあって難しい

とりあえず代表的なもので言うと３つあると覚えた
　Debian系
　　基本は無料
　　代表的なものは、Ubuntu
　　商用利用向きではなさそう
　　手軽に利用できる
　Redhat系
　　有料が多い
　　代表的なものは、CentOS
　　商用利用するならこれかな
　　CentOSは無料で利用できる
　Slackware系
　　有料が多い
　　代表的なものは、Suse
　　ヨーロッパでよく利用されている
　　商用利用するのに向いてはいるが日本では少ない
　　Open Suseは無料で利用できる

パッケージ管理もいっぱいあってどうしよう
取り敢えず以下を覚えておく

<table>
　<tr><th>系統</th><th>基本</th><th>依存関係を解決</th></tr>
　<tr><th>Debian系</th><th>dpkg</th><th>apk</th></tr>
　<tr><th>Redhat系</th><th>rpm</th><th>yum</th></tr>
　<tr><th>Slackware系</th><th>rpm</th><th>zypper</th></tr>
</table>
はじめてのGOLD「Function」

関数型インターフェースの話をします。
突然ですが、以下のコードを見てください。

```java:Func.java

interface Foo {
    public Function<String,String> doIt(Function<Integer,String> f);
}
```

```java:Main.java
Foo foo = f -> x -> "ABC" + f.apply(x.length());
System.out.println(foo.doIt(x -> x + "$").apply("DEF"));
```

これはラムダ式です。
ラムダ式の基本に立ち返って、`Main.java`を省略せずに書いてみます。

```java:Main.java

Foo foo = 
    (Function<Integer,String> f) ->
        {return (String x) -> {return "ABC" + f.apply(x.length());};}
```

長くなって余計にわからなくなったかもしれませんが、これを部分で見ていきます。
ポイントは、
・どのラムダ式がどの関数型インターフェースの定義をしているのか
・ある時点での戻り値を把握する
の二点だと思います。なので常にこれを意識していきます。


上記のコードは、冒頭の
`public Function<String,String> doit(Function<Integer,String> f)`
の定義です。

ですので、引数が`Function<Integer,String>`となります。
このFunctionの定義はまだしていない、ということを確認してください。

次に戻り値`Function<String,String>`を見てみます。

```
(String x) -> {return "ABC" + f.apply(x.length());}
```

String型を引数にとり、String型を返します。
戻り値のFunctionの処理はここで定義されました。

doItの定義と、doItの戻り値の定義が行われました。
次に引数`Function<Integer,String>`の定義です。
これは`Main.java`の２行目で行っています。

```
foo.doIt(x -> x + "$").apply("DEF")
```

`x -> x + "$"` がそれです。
あえて書き直すと、

```
foo.doIt((Integer x) -> {return x + "$";}).apply("DEF")
```

となります。
Integer型を引数に、String型を返しています。

それぞれの定義を確認したところで、値の流れを見てみます。

まず、`doIt()`が呼ばれ、関数の定義(`x -> x +"$"`)を渡します。
そして、また別の関数の定義(`x -> "ABC" + f.apply(x.length())`)を戻します。

doItが実行された時点では、まだ値は関数の定義のままです。

`doIt()`に連なっている`apply("DEF")`を実行することで具体的な値が生まれます。

`doIt()`から戻ってきた`Function<String,String>`の引数に`"DEF"`が渡ります。

値を代入してみると、

```
"ABC" + f.apply("DEF".length())
```

ということになります。

`"DEF".length()`のInteger型を利用して、引数の`Function<Integer,String> f`が実行されます。

```
"DEF".length() + "$"
```

ここではString型の`"3$"`が戻ります。
すると、`doIt()`の戻り関数は

```
"ABC" + "3$"
```

となり、最終的な値は`"ABC3$"`です。

ラムダの中のラムダを説明してみました。
何かご意見や補足あれば、よろしくお願いいたします。
3秒でわかるWPFでCtrl+C(Copy)のときになんか実行する方法

`Window`要素の直後に

```xml
    <Window.CommandBindings>
        <CommandBinding Command="Copy" Executed="OnCtrlC"/>
    </Window.CommandBindings>
```

を書く。C#側は

```csharp
    public partial class MainWindow : Window
    {
        private void OnCtrlC(object sender, RoutedEventArgs e)
        {
            //なんか
        }
    }
```

以上。

実例

[yumetodo/ImageSizeRateCalculator: https://teratail.com/questions/174798 ](https://github.com/yumetodo/ImageSizeRateCalculator)

# License

[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/deed.ja)

<a href="https://commons.wikimedia.org/wiki/File:CC-BY_icon.svg#/media/File:CC-BY_icon.svg"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/CC-BY_icon.svg/1200px-CC-BY_icon.svg.png" alt="CC-BY icon.svg" width="88px"></a>
Windows10にVagrantでCentos7環境構築する

# 環境
- VirtualBox 5.1.24
- Vagrant 2.0.4

# 手順
## Boxのリスト表示
ほしいBoxがリストに表示されていないことを確認します。

```powershell:powershell
> vagrant box list
```

## Boxのダウンロード
今回はVagrantCloudのリストで上位にあったものをDLします。
VagrantCloudのBoxリスト
[https://app.vagrantup.com/boxes/search](https://app.vagrantup.com/boxes/search)
今回使用するCentOS7
[https://app.vagrantup.com/centos/boxes/7](https://app.vagrantup.com/centos/boxes/7)

以下のコマンドでBoxを追加します。
「`https://...`のパスにあるイメージを基に、`centos/7`という名前でBoxを追加するよ」という意味だと思ってます。

```powershell:powershell
> vagrant box add centos/7 https://app.vagrantup.com/centos/boxes/7
```

ちなみにこのイメージをダウンロードする場合、引数`add`に続くBox名を`centos/7`以外を指定するとエラーになってしまいました。
というわけで`centos/7`というBox名にしています。

ダウンロードが始まると、プロバイダの選択肢が表示されます。
今回はVirtualBoxを選択します。

```powershell:powershell
1) hyperv
2) libvirt
3) virtualbox
4) vmware_desktop

Enter your choice: 3
```

ダウンロードが終わったら、下記コマンドでBoxが追加されていることを確認します。

```powershell:powershell
> vagrant box list
centos/7  (virtualbox, 1901.01)
```


## 仮想マシンの作成
以下コマンドで仮想マシン用のディレクトリを作成して移動します。
パスはほかのマシンと被ってなければどこでもいい、はず。

```powershell:powershell
> mkdir centos7
> cd centos7
```

次に、VagrantFIleを作成します。
`vagrant init`コマンドを実行し、カレントディレクトリにVagrantFIle（仮想マシンごとの設定ファイル）を作成します。
引数に先ほどダウンロードしたボックス名`centos/7`を指定することで、作成されるVagrantFIleに`centos/7`の名前が自動で反映されます。

```powershell:powershell
> vagrant init centos/7
```
## Vagrantfileの編集
いろいろやることはあるかと思いますが、ひとまずSSHでつなげるようにhost-onlyネットワークのIPアドレスをアンコメントアウト→編集しておきます。
今回は`192.168.33.30`としています。

```:変更前のVagrantfile
  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  # config.vm.network "private_network", ip: "192.168.33.10"
```

```:変更後のVagrantfile
  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  config.vm.network "private_network", ip: "192.168.33.30"
```

そのほかの設定については[Vagrantfile 覚書](https://qiita.com/JhonnyBravo/items/06f383e408c57735e348)が詳しいようです。

## 仮想マシンの起動
以下コマンドで、仮想マシンを起動します。

```powershell:powershell
> vagrant up
```
読書メータでcsvをインポートする方法

# 概要

読書メーターでcsvをインポートする方法を調査した。その結果をまとめる。

# インポート手順

読書メータのウェブ版において、以下の手順でインポートできる。

1. 右上の「メニュー」から「アカウント設定」を選択。
2. 表示された画面で「インポート」タブを選択。
3. 「CSV(ブクレコ形式)をインポートする」ボタンを押下。

![import.png](https://qiita-image-store.s3.amazonaws.com/0/114392/dd28ca82-bbac-1d56-7536-c2b72669f956.png)

現時点（2019/02/17）では、読書メータのアプリ版には同機能はない。

# ファイル仕様
## フォーマット

フォーマットはCSV。詳細は以下。

|項目            |値         |
|---------------|-----------|
| セパレータ      | ,         |
| エンコーディング | Shift-JIS |
| 改行コード      | LF        |

## カラム

カラムは以下の13個。

```javascript
ブクレコレビューID,作成日時,更新日時,ブクレコ本ID,ISBN10,ISBN13,本のタイトル,著者,出版社,レビュー,評価,"1:公開レビュー, 0:非公開レビュー","1:コメントを許可する, 0:コメントを許可しない"
```

この内、入力できるのは3項目だけ。詳細は以下の通り。

- 作成日時
    - yyyy/MM/DD hh:mm
    - 例：2019/02/17 18:00
- ISBN10
    - nnnnnnnnnn
    - 例：4532195411
- レビュー
    - 任意桁数の文字列
    - ただし、「255文字を超えるレビューは、該当する感想・レビューのコメント欄に追加」されるらしい。
- `1:公開レビュー, 0:非公開レビュー`
    - 1固定
- `1:コメントを許可する, 0:コメントを許しない`
    - 1固定
- その他の項目
    - すべて空欄

# 実験

いくつかのファイルを作って実験してみた。

## レビューなしの場合

以下のファイルをインポートしてみた。

```javascript
ブクレコレビューID,作成日時,更新日時,ブクレコ本ID,ISBN10,ISBN13,本のタイトル,著者,出版社,レビュー,評価,"1:公開レビュー, 0:非公開レビュー","1:コメントを許可する, 0:コメントを許可しない"
,2019/02/17 18:00,,,4532195411,,,,,,,1,1
,2019/02/17 18:00,,,4101800103,,,,,,,1,1
```

登録されなかった。

## レビューありの場合

以下のファイルをインポートしてみた。

```javascript
ブクレコレビューID,作成日時,更新日時,ブクレコ本ID,ISBN10,ISBN13,本のタイトル,著者,出版社,レビュー,評価,"1:公開レビュー, 0:非公開レビュー","1:コメントを許可する, 0:コメントを許可しない"
,2019/02/17 18:00,,,4532195411,,,,,インポートテスト１,,1,1
,2019/02/17 18:00,,,4101800103,,,,,インポートテスト２,,1,1
```

登録された。

![4532195411.png](https://qiita-image-store.s3.amazonaws.com/0/114392/c8247344-4f0f-5875-81a0-189d4cc88ec1.png)

![4101800103.png](https://qiita-image-store.s3.amazonaws.com/0/114392/75d2bb4c-c7ac-a965-725d-d67d37c3501f.png)

## 同一書籍複数レビューありの場合

以下のファイルをインポートしてみた。

```javascript
ブクレコレビューID,作成日時,更新日時,ブクレコ本ID,ISBN10,ISBN13,本のタイトル,著者,出版社,レビュー,評価,"1:公開レビュー, 0:非公開レビュー","1:コメントを許可する, 0:コメントを許可しない"
,2019/02/17 18:00,,,4532195411,,,,,インポートテスト１,,1,1
,2019/02/17 19:00,,,4532195411,,,,,インポートテスト２,,1,1
```

登録された。

![4532195411_2.png](https://qiita-image-store.s3.amazonaws.com/0/114392/64dd9b83-34c7-0261-f2b1-111558430b43.png)

## レビューに半角スペースありの場合

以下のファイルをインポートしてみた。

```javascript
ブクレコレビューID,作成日時,更新日時,ブクレコ本ID,ISBN10,ISBN13,本のタイトル,著者,出版社,レビュー,評価,"1:公開レビュー, 0:非公開レビュー","1:コメントを許可する, 0:コメントを許可しない"
,2019/02/17 18:00,,,4532195411,,,,,イ ン ポ ー ト テ ス ト １,,1,1
,2019/02/17 19:00,,,4532195411,,,,,インポートテスト２,,1,1
```

登録された。

![4532195411_3.png](https://qiita-image-store.s3.amazonaws.com/0/114392/d9453f14-5430-c7a5-a891-5d360cb1923a.png)
react-reduxの6.0.0を入れると発生するエラー（Uncaught TypeError: __WEBPACK_IMPORTED_MODULE_0）

react-reduxの6.0.0だと以下エラーが発生することがある

```Uncaught TypeError: __WEBPACK_IMPORTED_MODULE_0_react___default.a.createContext is not a function```

現時点では、5.0.6をインストールで回避

```yarn add react-redux@5.0.6;```
プログラミング学習記録1〜#100DaysOfCode始めました〜

##今日からプログラミングの学習過程を記録していきます
twitterで「100DaysOfCode」というものを知り、プログラミング学習のモチベーションになる素敵な活動だなと思ったので、今日から100DaysOfCodeを始めようと思います。

学習記録の書き方は今の所まったく定まっておりませんが、その日やったことだけでなく、それをやって何を感じたのか？という感情も記録していくつもりです。

##今日やったこと
- Progate HTML&CSS初級編、中級編、上級編の「そのまま復習」
- Progate Ruby1の「リセット復習」
- Qiitaの使い方確認　

##Progateはある程度「リセット復習」したら、あとは「そのまま復習」でいい
直接コードを打ち込んで学習できるのがProgateのいいところだと思いますが、実際に打ち込むのは数回（数周）でいいなと思います。

- **最初の数周→「リセット復習」でコードを実際に打ち込んで復習**
- **ある程度理解したら→実践or忘れてしまった時に「そのまま復習」で読むだけ（見るだけ）の復習**

という感じですね。

ある程度内容を理解できるようになったら、コードを打ち込んでやる復習よりも読むだけ（見るだけ）の復習の方が時間がかからないからです。

楽にできるのもあって、なんとなく復習し過ぎがちになってしまうProgateなのですが、ある程度のレベルに達したら見切りをつけることが大事なのかなと思います。


###Progate HTML&CSSの空のdivを作って、回り込みを防ぐ方法は古いらしい
これはテックアカデミーの教材に書かれていました。

最近はclearfixだったり、overflow:hidden;で回り込みを防ぐやり方がよく使われているみたいです。

##Qiitaの使い方を確認した
投稿の仕方とタグの種類を確認しました。

見出しだったり、文字装飾が簡単にできるエディタで非常に書きやすいですね。

あと、タグに関してなのですが、とりあえず勉強したものに関するタグだけをつけることにしました。

「初心者」や「新人プログラマ」といったタグもありましたが、投稿数が少なかったので、HTMLやRubyといったメジャーなやつだけつけていきます。


##まとめ
久しぶりに文章を書きました。

あまりまとまらない文章になってしまいましたが、後々ブログでちゃんとまとめて書いていきたいと思います。

おわり
できるリーダー(テックリード)になるためのトレーニング法①

## はじめに
うめりんです。
少しでも「参考になった」と感じて頂けた方は、ぜひ**いいね**:thumbsup_tone2:お願いします:smiley:

## ①すぐに近似値を出せるように、普段から時間感覚を意識して覚えて（記録して）おく

考え方はフェルミ推定に共通する部分も多くあるかもなのですが、難解なことでは無く誰でも身につけられるものです。

## なぜ必要なのか？
リーダーになると何かにつけて
「ザックリどれぐらいかかります？」と聞かれる（概算を求められる）ことが、めちゃくちゃ多くなります。

その際、”詳細な仕様を元に積み上げで見積もりをすること”しか経験が無い（手法を身につけて居ない）と、回答に時間がかかり過ぎたり、一応出してみたものの見積もりと実績の差が大きくなり過ぎてしまったりすることが、よく起こります。

こういった期待に応えられない状況が続くと、リーダーとなった本人も辛いですし、周りからの信頼も上がってきません。

## 具体的に何をすれば良いのか
まずは、普段のフルビルド時間・デプロイ時間など、開発運用において避けて通れない（必ず発生する）ものの時間を測り、いつ誰から聞かれた時にも即答できるよう覚えておきます。
測った後に覚える時の注意点なのですが、42分なら40分、55分なら1時間、など端数を後々に何らかの計算をし易い近似値に丸めておくことが大事です（これにより覚え易くなる効果もあります）。
これをやっておくと副次的な効果として、コードや環境などに異常が発生した際に（普段より時間がかかるようになったり、終わるのが想定より早すぎる場合に）すぐ気付けるようになります（あれ？何かいつもと違うぞと感じられるようになる）。

次に、自身が過去に経験のある機能や要件ごとに、設計・実装・テストに対して、何にどれだけ時間がかかったかを洗い出します。
コツは「洗い出す時に細かくし過ぎないこと」です。細部が決まっていない時に概算が出せることがゴールなので、その時に役立つデータになるよう意識した粒度として下さい。操作可能なUI数、画面数、API数、演出(アニメーション)数、扱うデータ数などが比較的分かりやすい指針です。既存機能の流用度合いが高い場合は、調査にかかった時間やその機能を知る経験者が居たかの状況も合わせて記録しておくと重宝します。
スクラムを用いているチームの場合はストーリーポイントも参考程度にはなりますが、実績値として使えないことも多くブレが大きいのであまりオススメしません。
また、不具合修正とリファクタリングは既存実装における負債の大きさが違い過ぎることが多いので、一旦は洗い出しの対象外とした方が良く、これらを見積もる際には概算で話さず調査時間をしっかり取った方が良いです。

そして最後に、バージョンアップ開発のフェーズや運用データのリリースなど、より大きな単位に対しての数を把握します。期間(or 稼働日数)、PR(or MR)の数、不具合修正の数、関わったメンバの数、などが一例として考えられます。
これらを手元に持った上で定期的に眺めて「今回の開発は、あの時と同様の規模だな」のように感じられるようになれば、できるリーダーに必要な感覚の1つが身についたと自信を持って頂いて大丈夫だと思います。

## おわりに
そこまで経験が無いけれど、もしリーダーに運良く抜擢され、何度か失敗しても長い目でみてくれて任せ続けて貰えれば、実戦の中から必要だと自覚できる人が多いとは思うのですが、この手のことは「もっと早く教えて欲しかった」となることが多く、教える側（前任者、先達）もしっかり意識して来た人でないと「慣れるしかない」のように策を持っていない人が多いので、まとめてみました。
複数のネットワークを跨いだROSネットワークの構築メモ


# 概要
最近，研究室で「モーションキャプチャでロボットの動きをトラッキングしてそのデータとロボット上のLiDARのデータをもとにリアルタイムにロボットを動作させる」必要がありました．複数のネットワークを跨いでROSを動作させる必要があったのですが，できて当然なのか，単に誰もやろうとしないのか，調べてもちょうど同じようなことをしようとしている例が見つからず若干苦戦したので，メモしておきます．なお，文章中に登場するipアドレスなどは，実物とは異なります．

# 条件
- ロボットにはPC1(Ubuntu 16.04LTS)が搭載されており，ethernetのポートが1つ(enp3s0)ある他，wifi(wlp112s0)を利用できる．ethernet側は固定ipアドレスが設定済み(192.168.0.100)である．このipアドレスは変更しない
- ロボットにはLiDARが1台搭載されており，ロボットのethernetポートにLANケーブル1本で接続されている．ipアドレスは192.168.0.110で，このipアドレスは変更しない
- モーションキャプチャはethernet hubを経由してPC2(Ubuntu 16.04LTS)に接続されている．PC2にはehternetのポートが1つ(enp4s0)あり，wifi(wlp114s0)も利用できる．ethernet側は固定ipアドレスが設定済み(192.168.10.200)である．このipアドレスは変更しない
- PC1とPC2は，無線で直接(市販のwifiアクセスポイントなどを介さずに)接続したい

図で表すと，こんな感じになります
![img.png](https://qiita-image-store.s3.amazonaws.com/0/273785/eacae5ed-3372-6eae-d232-98fccc93b8b6.png)

# 手順
### 接続
まず，PC1とPC2をwifiで接続するため，[Ubuntu16.04 でのアクセスポイント化](http://tatanaideyo.hatenablog.com/entry/2017/07/16/072209)を参考に，PC2をアクセスポイントとしました．これにPC1を接続すると，新たなネットワーク(10.42.0.0/24)が作られました．

PC1のwifi側ipアドレスは，10.42.0.100に固定しておきました．
これで，接続自体はできましたが，まだ各ネットワーク間のpingは通りません．

以下，[複数のネットワーク間を跨いだ通信を行う環境を簡易的に作成する](http://blog.futurestandard.jp/entry/2017/06/02/125745)を参考に，設定を進めていきます．

### ipフォワーディング
両PCにおいてethernet，wifiのそれぞれに来るパケットをもう一方に流して欲しいので，ipフォワーディングの設定を行います．

```bash
# iptableの設定を削除(共通．不要?)
$ iptables -t nat -F
$ iptables -F

# 双方向のipフォワーディングを設定(PC1)
$ iptables -A FORWARD -i enp3s0 -o wlp112s0 -j ACCEPT
$ iptables -A FORWARD -o enp3s0 -i wlp112s0 -j ACCEPT

# 双方向のipフォワーディングを設定(PC2)
$ iptables -A FORWARD -i enp4s0 -o wlp114s0 -j ACCEPT
$ iptables -A FORWARD -o enp4s0 -i wlp114s0 -j ACCEPT
```
### ルーティングテーブルの設定
両PCでゲートウェイの設定を行い，もう一方のPCのethernet側ネットワークにアクセスできるようにします．

```bash
# PC1
$ ip route add 192.168.10.0/24 via 10.42.0.1 dev wlp112s0
# PC2
$ ip route add 192.168.0.0/24 via 10.42.0.100 dev wlp114s0
```

これで，相手PCのethernet側ネットワークへのアクセスができるようになりました．

# 確認
両PCのROS_MASTER_URIをPC2に設定します．

```bash
$ export ROS_MASTER_URI=http://192.168.10.200:11311
```

ROS_IPも設定します．

```bash
# PC1
$ export ROS_IP=192.168.0.100
# PC2
$ export ROS_IP=192.168.10.200
```
PC2でroscoreを起動し，rostopic pub/echo等で疎通が確認できたら，成功です．

# 備考
今回はUbuntuのアクセスポイント化をGUIで行いましたが，この方法だとIEEE802.11gでの接続になっているらしく，少々速度に不安があります(PointCloudのやり取りにもたついている様子．tfも怪しい)．もしかしたら通信速度に起因するものでは無いかもしれませんが，create_apを使うとIEEE802.11acが使えるらしいので，いずれ試してみようと思います．
Laravelにおけるファイルアップロードあれこれ

## ファイル情報取得
### ファイル取得

- file()

```php
$file = $request->file('uploadFile);
```

- all()

```php
$inputs = $request->all();
$file = $inputs['uploadFile];
```

### ファイル名取得

- getClientOriginalName()

```php
$file = $request->file('uploadFile);
$fileName = $file->getClientOriginalName();
```

### 拡張子取得

- getClientOriginalExtension()

```php
$file = $request->file('uploadFile);
$fileName = $file->getClientOriginalExtension();
```

### ファイルサイズ取得

- getClientSize()

```php
$file = $request->file('uploadFile);
$fileName = $file->getClientSize();
```

### さらに細かい情報を知りたい

- https://readouble.com/laravel/5.5/ja/requests.html
- https://api.symfony.com/3.0/Symfony/Component/HttpFoundation/File/UploadedFile.html

## ファイルのバリデーション

### 拡張子

- mimes

```php
'uploadFile' => 'mimes:pdf'
```
※ [そのほかの拡張子](https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types)

### ファイルの最大サイズ

- max

```php
'uploadFile' => 'max:10240' // 10MB（キロバイト換算になる）
```

## 備考
- Laravelのファイルアップロードは、symfonyのuploadFileを拡張したものである
micro:bitのLEDをそろばんにみたてて整数：10万までを表示

#IoTカウンタにするための表示方法としてつくってみた
- Aボタンを押すと+1
- Bボタンを押すと-1
- A+Bを押すと0リセット
- 10万を超えると「E!」を表示して、数値を横スクロールで表示
- 5は明るさ255,1~4は明るさ25で表示

#公開ソース
[LEDでソロバン表示](https://makecode.microbit.org/_8dqHiRiHiEqp)
[外部入力をソロバン表示](https://makecode.microbit.org/_JXEhRJfdvAYi)
ベイズ推論の勉強用ノート（４）ー 事後分布の推定

# 目的
[ベイズ推論による機械学習入門](https://www.amazon.co.jp/dp/4061538322)の勉強用のノート。
式を後で参照するために残しておく。

# 関連
[ベイズ推論の勉強用ノート（１）ー 基本的な定義](https://qiita.com/tkosht/items/de4cb8876b4aedde5a6e)
[ベイズ推論の勉強用ノート（２）ー 離散確率分布](https://qiita.com/tkosht/items/a5aee011a35e53764cd1)
[ベイズ推論の勉強用ノート（３）ー 連続確率分布](https://qiita.com/tkosht/items/8213b228a980eeeed1b7)

# パラメータの事後分布

- $D$：訓練データの集合
- $\theta$：モデルに含まれる未知のパラメータ

条件付き確率の定義から、同時分布$p(D, \theta)$は、以下のように分解できる。

```math
\begin{align}
p(D, \theta) = p(D|\theta)p(\theta)
\end{align}
```

パラメータ$\theta$に対する事前の不確実性は、事前分布$p(\theta)$ を設定することで、モデルに反映される。

- $p(D|\theta)$：$\theta$の関数と見たとき、尤度関数(likelihood function) と呼ぶ
- 特定のパラメータ$\theta$から、どのようにしてデータ$D$が発生するのかをモデル化している部分

データ$D$を観測した後の、パラメータ$\theta$の不確実性は、以下のように更新される。（式は、ベイズの定理そのもの）

```math
\begin{align}
p(\theta|D) = \frac{p(D|\theta)p(\theta)}{p(D)}
\end{align}
```

- この条件付き分布$p(\theta|D)$ を計算することが、
ベイズ学習の枠組みにおける「学習」に相当する
- $p(\theta|D)$は、パラメータ$\theta$の事後分布
- 新しいデータ$D'$が得られたら、$p(\theta) \leftarrow p(\theta|D)$ として、$p(\theta|D') = \frac{p(D'|\theta)p(\theta)}{p(D')}$と更新する
- 実際は、$p(\theta|D,D') =
 \frac{p(D'|\theta)p(\theta|D)}{p(D')}$ を計算している点に注意する
Three.jsのキーフレームアニメーションを絶対時間で再生

# 概要
glTFに書き出したモデルのアニメーションを動画に合わせて再生したかったのだけど、指定した時間のフレームを再生させる方法が見つからなかったので備忘録。 
delta指定めんどくさいねん...

ちなみにこの[デモ](https://oregl.ukon.dev/gl/DevilSuzanne/)に使いました。
# コード

```javascript
var mixer;
var action;
var video = document.getElementById('video');

function init(){
    var loader = new THREE.GLTFLoader();
	loader.load( 'models/model.glb', function ( gltf ) {
		var model = gltf.scene;
		var animations = gltf.animations;
		
		scene.add(model);
		
		mixer = new THREE.AnimationMixer(model);
		action = mixer.clipAction(animations[0]);
		
		action.play();
		video.play();

		animate();
	}
}

function animate() {
    var time = video.currentTime;
    action.time = time;
    mixer.time = time;
	mixer.update(0);
	
	renderer.render( scene, camera );
	requestAnimationFrame( animate );
}
```

だいぶ端折ってますが、モデルをロードしたときにclipActionを取り出しておいて、フレームを更新するたびに時間を指定してからミキサーを時間差0でアップデートしてます。

このデモでは動画とキーフレームアニメーションをリンクさせたかったため動画の再生時間を渡しています。

この方法で良いのかな...?
kaggle :  mercedes-benz-greener-manufacturing について

#「mercedes-benz-greener-manufacturing」の事例

https://www.kaggle.com/c/mercedes-benz-greener-manufacturing
メルセデスベンツの製造工程で、様々な車種でどのようなオプションがあるかによって検査時間がどのように変わるかを分析します。
検査時間により二酸化炭素の排出量が削減されます。

#kernel例
提出されているkernelを見てみましょう。

stacked then averaged models [~ 0.5697]
https://www.kaggle.com/hakeem/stacked-then-averaged-models-0-5697

今回のポイントは385の次元を持つデータをどのように扱うかでした。

###次元を圧縮して12次元のデータを作ります。
下記のモデルで次元を圧縮します。
PCA
ICA
GRP
SRP

###圧縮した次元を追加して、xgboostのモデルで学習します。

###結果
次元を削減しなかった場合はスコア「0.55526」
次元を削減したカラムを追加した場合は、スコア「0.56847」に少し上がりました。
PHP 先頭の単語を大文字にする

<h1>今回挑戦するプログラミング問題</h1>

codewars 5級
「The Hashtag Generator」


<h1>実現したいこと</h1>
+ #をつけて返す
+ 各文字列の最初を大文字にする
+ 返す文字列が140文字以上の場合はfalseとする
+ 空文字列が与えられば場合はfalseとする

```
" Hello there thanks for trying my Kata"  =>  "#HelloThereThanksForTryingMyKata"
"    Hello     World   "                  =>  "#HelloWorld"
""                                        =>  false
```



<h1>コーディング</h1>
```
function generateHashtag($str) {
  $result = '#'.$str = str_replace(' ', '', ucwords($str));
  if(empty($str) || strlen($result) > 140) return false;
  return $result;
}
```
+ ucwords()で各単語の最初の文字を大文字にする
+ str_replaceでスペースを取り除き、先頭に#をつける
+ 条件を確認して結果を返す
Djangoのログイン機能の実装方法

Djangoのログイン機能の実装方法
こちらのサイトに詳細が記載されている
https://it-engineer-lab.com/archives/544

こちらの公式ドキュメントも参考に出来る
まだ半分が英語だが。
https://docs.djangoproject.com/ja/2.0/topics/auth/default/

こちらはカスタムユーザモデルの話
https://qiita.com/okoppe8/items/10ae61808dc3056f9c8e
S3でStaticWebsiteHostingしようとして「アクセス拒否」「403」で悩んだ

#AWS Activated活用したい
AWS Activatedを利用出来るようになったので、あまりコストを気にすることなくガンガン使っていこうと思った。S3に静的コンテンツを配置したら簡単にホスティング出来る、ということだったので、ちょっとやってみたらいろいろハマったのでメモしておく。不正確なところがあるかもしれませんがご容赦下さい。

##S3のアクセス権限が変更できない
* S3→「+バケットを作成する」バケット名にはドメイン名を指定すること、というルール。
* 作成したバケット選択
* 「アップロード」で、適当なindex.htmlをアップロード。
* 「プロパティ」タブからStatic website hostingにて「このパケットを仕様してウェブサイトをホストする」にチェック。
* インデックスドキュメントをindex.htmlに指定し「保存」する。
* 「アクセス権限」タブから「パケットポリシー」選択
* パケットポリシーエディタで以下入力

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadForGetBucketObjects",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<作成したS3バケット名>/*"
        }
    ]
}
```
* 「保存」実行！！
![s3-error1.png](https://qiita-image-store.s3.amazonaws.com/0/108331/0f58351e-f108-61eb-f830-10f66e3ae913.png)
* 不吉な！！
* 作成したS3バケットの「プロパティ」タブの下の「Static website hosting」をクリックして、エンドポイントをクリック
* HTTP 403: Access Denied
* 不吉な！！

##対処
* 「アクセス権限」タブの「パブリックアクセス設定」にて「新規のパブリックバケットポリシーをブロックする (推奨）」のチェックはずして「保存」
* IAMでアクセス権チェック。足りなければ付与。「AmazonS3FullAccess」があればいいはず（もっと最小限でもいい）
* S3バケットにアップロードしたindex.htmlをクリック
* 「公開する」をクリック
* エラー　アクセス拒否！！
* 親バケットに戻って「アクセス権限」タブから「パブリックアクセス設定」「バケットにパブリックポリシーがある場合、パブリックアクセスとクロスアカウントアクセスをブロックする (推奨) 」チェックボックスを外して「保存」
* 再度index.htmlを「公開する」
* 公開された！！

## エンドポイントにアクセス出来た！！

みんなこんなことやってるんですか？？
[React Native]FlatListを更新する方法

React Nativeのバージョンは0.57.8。

以下のように`extraData`を設定しておく。

```jsx
<FlatList
  data={...}
  extraData={this.state.refreshFlatList}
  renderItem={this.renderItem.bind(this)}
  keyExtractor={(item, index) => index.toString()}
/>
```

初期化の際の値はどちらでも可。

```js
constructor(props) {
  super(props);
  this.state = {refreshFlatList: true};
```

リストを更新したいタイミングで値を反転する。

```js
this.setState({refreshFlatList: !this.state.refreshFlatList});
```

# 参考

- [reactjs - How to re-render flatlist? - Stack Overflow](https://stackoverflow.com/questions/43397803/how-to-re-render-flatlist)
RailsのMailerでGmailを使う方法

<h1>Mailerを使いたい</h1>

RubyとRailsを使って個人で今ゲームに関してのブログ的なアプリ開発をしています。
その時に、お問い合わせフォームをライター募集と自分の学習をかねて作ろうかなと思って、ついでにMailerも使って行こうとなったわけです。
で、お問い合わせフォームについては軽くHTMLやらCSSを使った時に勉強したので、わりとさらっと行けたんですが、Mailerはよくわからないということでやったんですが、思わぬところでつまづきました。
<h2>何につまづいた？</h2>

つまづいたのは技術的なところというよりも、別のところでした。
Mailerについては<a href="https://www.sejuku.net/blog/48739" target="blank">サイト</a>を参考しながらやっていて、少しづつ調べたりしてやっていき、コンソールからメールを送るフェーズまではいったんですが、動きが一切ない。（メールが届かない。）
ログをみても送れました的なコメントで時にエラーのメッセージがない。はてさてどうしたものかとなったわけです。

<h2>Googleの2段階認証が要</h2>

どうやら何か悪いらしいと送信元のアドレスにいったら、ログインのブロックログが。
どうやらGoogleのログインがうまくいっていなくて、しかもアプリの環境設定で、

<pre>config.action_mailer.raise_delivery_errors = false</pre>

の部分、つまりMailerのエラー文を表示するメソッドをfalseにしていたことが判明。要は送れてないしログインをブロックされていたということがわかりました。

<h2>解決に向けて</h2>

で、解決方法なんですが、エラーが表示されていないことも問題ではあったんですが、一番の問題はログインできていないこと。
これをどう解決するかというと、Googleのアカウントの方で2段階認証と、アプリログインパスワード（通常のアカウントのパスワードと違う、専用のパスワード）を入れなくてはならないらしいとわかりました。

<h2>Googleの認証</h2>

これは楽チン。
自分のアカウントのところから2段階認証をオンに。
その後は手順通りに進めれば終わりです。

<h2>アプリログインパスワードの取得</h2>

で続いてはパスワードの取得。
これもアカウントからとればいいです。
メールについてのアカウントで、自分の開発環境に合わせたもの（MacならMac、WinならWinで。）を取得してください。
※このパスワードは一度しか表示されないので確実にどこかに保存してください。

<h2>パスワードを使う</h2>

最後はパスワードを使いましょう。

<pre>
config.action_mailer.smtp_settings = {
      address: 'smtp.gmail.com',
      port: 587,
      domain: 'gmail.com',
      user_name: 'あなたのGmail',
      password: '取得したパスワード',
      authentication: 'plain',
      enable_starttls_auto: true
  }
</pre>

ここにある通り、取得したパスワードの部分に先ほどのものを入れてあげれば完了です。
コンソール起動しっぱなしだとエラーが発生したりするので、一度コンソールを切ってから再度やってみてください！

<h2>終わりに</h2>

Mailerの技術的な部分も不安定で、その上でエラーだったのでちょっとビビりました。
細かな部分でもこういったことが怒るので、気をつけてあげないと怖いですね。
Git エイリアスをUnix風のコマンドで設定する その２（git-alias, git-unalias）

## はじめに

ご無沙汰しております。 
いまだ性懲りもなくGit エイリアスにかまけておりまして、今回はその第2弾の記事となります。

[前回の記事](https://qiita.com/Khios/items/b37dba93b24ecfc10e58)では、Git エイリアスを簡単に設定するために編み出したエイリアス（`alias.alias`）についてご紹介しました。 
ところが、記事を書き終えた後、**わざわざエイリアスにする必要ある？**ということに気付いてしまいまして、新しく作り直しておりました。

というのも、Gitにはパスの通ったディレクトリにある `git-` で始まる実行ファイルがサブコマンドとして使えるというハックがあるんですよ（[git-flow](https://github.com/nvie/gitflow)で有名ですね）
要するに、`export PATH="$HOME/bin:$PATH"` なんてときに `~/bin/git-subcommand` という実行ファイルがあれば、なんと `git subcommand ...` という風に使えてしまう訳です。 
しかも言語によらないので、シェルスクリプトだろうがPythonだろうが、あまつさえC++製の実行ファイルでもOKです。

それならば、`git-alias` というサブコマンド形式にしてしまった方が記述の自由度も高いし、メンテも楽だということで、エイリアスをやめてサブコマンドに移行しました。 
あと、ついでに `git-unalias` も作りました。エイリアスの削除もUnixライクにできます！

ちなみに、相変わらずシェルスクリプトで書いています。 
ソースがかなり肥大化してしまったので、最早シェルスクリプトじゃない方が良いかもしれません……。

## インストール

<https://github.com/khiosorg/git-alias>

```
$ git clone https://github.com/khiosorg/git-alias.git && cd git-alias
$ ./install.sh /usr/local/bin
```

`./install.sh` の引数を変えると、お好みのディレクトリにインストール（要はコピー）できます。省略すると `/usr/local/bin` です。 
パスを通すのを忘れないでくださいね。

~~※まだREADME書いてないです。すみません。~~ 
README書きました！拙い英語で逆に読みにくいと思います。すみません。

## git-alias

```
$ git alias [-p] [name[=value] ... ]
```

- `-p`: 一覧表示です。

## git-unalias

```
$ git unalias [-ad] name [name ...]
```

- `-a`: 全てのエイリアスを削除します。
- `-d`: いわゆるdry runというやつです。

## 最後に

追加機能のアイデアを色々考えているので（パターンマッチ、正規表現、インタラクティブ等）今後も細々とメンテを続けていく予定です。 
たまにGitHubの方をのぞいてみてください笑

あと、`git-` 型サブコマンドを集めたライブラリとして[git-extras](https://github.com/tj/git-extras)を紹介しておきます。 
色んなサブコマンドがあるので面白いと思いますよ。 
`git-alias` もあったりしますが、拙作の方が高機能のはず！笑