OmniAICreator/Qiita-1.07M huggingface dataset:
サーバ側で作成したPDFをブラウザで表示させた時のファイル名を正しく設定したい

##やりたいこと
TCPDFとFPDIを利用して、Web上でユーザが入力した情報をテンプレートのPDFに文字として埋め込む機能を実装した。
実際に作成したPDFを一旦ブラウザ上で表示するようにする。
（必要事項入力→作成ボタン押す→文字を埋め込んだPDFをブラウザで表示）

##起きた問題
実際に動作を確認した時、以下のブラウザでそれぞれ変な動作になった。

**chrome**
・ブラウザのPDFビューワーに表示されるファイル名が、PDFを表示させているソースコードのファイル名になる。(XXX.phpみたいな)
・ダウンロードボタンを押した時のデフォルトファイル名も、XXX.phpのようなソースコードのファイル名になる。
・実際にダウンロードされるファイルが、HTML形式のコード。

**Edge**
・表示されるPDFのファイル名は問題ないが、ビューワーのダウンロード機能でダウンロードすると、デフォルトのファイル名が「無題.pdf」になる。


今回、ブラウザ上に作成したPDFを表示させるのに、TCPDFのOutputメソッドを出力モード「I」(ブラウザのビューワーで出力)を利用した。
引数として表示させたいファイル名を指定すれば、Content-Dispositionのfilenameに指定したファイル名が設定されると思っていたが・・・想定していた通りに動作しなかった。

ちなみにfirefoxでは正しく動作した。ありがとうfirefox。


##解決策
一番簡単なのは、作成ボタンを押したら、PDFファイルを一旦サーバ上に保存し、それを直接表示させるようなURLを生成して出力させる方法かな。と、直感では思ったが、今回はファイルを保存しない方法で解決してみた。


####ビューワー上で表示されるファイル名
URLがビューワーで表示させたいファイル名になればいいので、URLはファイル名に設定し、実際に走らせたいPHPファイルに内部で書き換えてしまう。

```php
//PDF作成
$pdf = $pdf->Output('PDFファイル名', 'S');
header("Location:URL"); //ここでXXX.pdfみたいにファイル名を記述
```

```:.htaccess
RewriteEngine On
RewriteRule ^.*\.pdf$ 表示処理をするPHPファイル名
```

####ダウンロードする時のファイル名を正しく設定
上記の.htaccessで呼び出したPHPファイル内でPDFの表示処理をさせる。
PDF作成時からファイルを跨いでの処理のため、作成したPDFを一旦セッションに保持させる。その際、TCPDFのOutputの出力モードはSを指定する。

```php
//PDF作成
//出力モード「S」：PDFを文字列として出力する。
$pdf = $pdf->Output('PDFファイル名', 'S');
session_start();
$_SESSION["pdf"] = $pdf; //セッションに退避
header("Location:URL"); //ここでXXX.pdfみたいにファイル名を記述
```


あとは表示処理側のPHPで退避したセッションから取り出す。
ダウンロード時のファイル名はContent-Dispositionのfilenameに設定すればOK。

```php
session_start();
$data = $_SESSION["pdf"];
header('Content-Type: application/pdf');
header('Content-Disposition: inline;filename=DL時のファイル名');
echo($data);
exit;
```

これでchrome、Edge共にダウンロード時のデフォルトファイル名が正しく設定された上、chromeではきちんと作成したPDFファイルがダウンロードされた。

だいぶ回りくどい方法になってしまったが、PDFを保存したり、消したりといったことを考えなくていいので楽といえば楽だったかなと。

IEだとinline指定時にfilenameが正しく設定されないという話はちらほら見かけたが、chromeでこのような現象に出くわしてる例が全くと言っていいほど見かけず、四苦八苦した。



##参考
今回の解決方法はここの方法をガッツリ適用させました。
・サーバ側で作成したPDFの表示とクライアントPCへの保存 - 闘うITエンジニアの覚え書き
https://www.magata.net/memo/?%A5%B5%A1%BC%A5%D0%C2%A6%A4%C7%BA%EE%C0%AE%A4%B7%A4%BFPDF%A4%CE%C9%BD%BC%A8%A4%C8%A5%AF%A5%E9%A5%A4%A5%A2%A5%F3%A5%C8PC%A4%D8%A4%CE%CA%DD%C2%B8
Windows企業内プロキシ配下でcreate-react-app（yarnを使う）

#はじめに
当社のLANはプロキシサーバー経由でインターネットへ接続する構成です。Reactアプリケーションを社内で制作するため、プロキシ経由で通信をするようネット情報を参考にしましたが非常に苦戦。

```npx create-react-app <application name>```

で固まってしまい、netstat コマンドで観察するとダイレクト接続しようとしています。

その後なんとかインストールできたので、方法を共有します。


##環境
- Windows 10
- Node.js v12.10.0
- npm 6.10.3
- yarn 1.17.3

#方法

Node.js(+npm) と yarn 導入済みとします。

まずはプロキシサーバーへの通信設定

```bat:プロキシ設定
npm -g config set proxy http://host:port
npm -g config set https-proxy http://host:port
npm -g config set registry http://registry.npmjs.org/
npm -g config set strict-ssl=false
yarn config set proxy http://host:port -g
yarn config set https-proxy http://host:port -g
```

```bat:create-react-app準備
npm -g install create-react-app
yarn global add react react-dom react-scripts react-scripts-ts
@rem react-scripts-ts は TypeScript を使うとき
```

これで、キャッシュさせることが解決の鍵。このあと

```bat:reactアプリケーション作成
create-react-app <application name>
@rem または create-react-app <application name> --typescript
```

で、React のアプリケーションディレクトリが準備されるでしょう。

#さいごに
環境構築がうまくできないことで、React導入を諦めてしまうケースも多いと思います。勿体ない！！

Microsoft 社などでも企業内プロキシの存在が蔑ろにしている傾向を感じることがしばしばですが（WindowsUpdate などの標準機能利用に netsh winhttp[^1] やらbitsadmin[^2] やらコマンドを打て、とか）プロキシ導入を止めさせる何かの戦略なのかと穿ってしまいます。かつては自ら[ISAサーバー](Microsoft Internet Security and Acceleration Server)という製品も出していたのに...

誤り・冗長なこと、もっと簡単な方法がある、などありましたらご指摘くださいませ！

余談ですが、このような社内のプロキシサーバーを、一定の外国圏のお方たちは corporate proxy などと呼んでいるようです。

#参考にしたサイト（感謝！）
- [node.js – 企業ファイアウォールの内側でcreate-react-appを使用する](https://codeday.me/jp/qa/20190505/777154.html) - [コードログ](https://codeday.me/jp/) さん

[^1]: https://qiita.com/gitya107/items/9302c07412e4990b1121 - @gitya107 さん

[^2]: https://ranp.myds.me/wordpress/2018/12/14/post-176/ - Noobest Engineering meiryoさん
ASP.NET MVC 基礎 その1【テンプレート、共通パーツ】

## アジェンダ

- テンプレート構造
- Viewが表示される流れ
- テンプレート類
 - _Layout.cshtml
 - _ViewStart.cshtml
- 共通パーツ

## テンプレート構造

├ Views
├ Shared （共通パーツ格納ディレクトリ）
│  ├ _Layout.cshtml（アプリの既定のレイアウト）
│  ├  _Header.cshtml
│  └  _Footer.cshtml
└ _ViewStart.cshtml （各ビューの前に実行する処理を記載する）

## Viewが表示される流れ

1. /Views/_ViewStart.chtmlが読み込まれる
2. /Views/Shared/_Layout.chtmlが読み込まれる(1.で指定しているから)
3.の_Layout.chtml中の@RenderBody()が呼ばれる(2. に記述されているから)
@RenderBody()は**テンプレートに1箇所のみ**
4. 必要に応じて@RenderSection()が呼ばれる
@RenderSection()は**複数箇所でも可**

## テンプレート類

### _Layout.cshtml

アプリの既定のレイアウト。
ファイル名の先頭に「_(パーシャル)」を付ける。

```html:_layout.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body>
    @RenderBody()

    @Scripts.Render("~/bundles/jquery")
    @RenderSection("scripts", required: false)
</body>
</html>

```

**@RenderBody() とは**
このテンプレートを使ったページの本体を出力する。

**@RenderSection()とは**
@RenderSection(セクション名, required: 必須かどうか)のように引数を用いて、メインのボディ部分以外も、カスタマイズできるようにしている。

具体的に言うと。。

■レイアウトでscriptsセクションを呼び出すように指定して

```html:_layout.html
@RenderSection("scripts", required: false)
```

■各ページでscriptsセクションを用意してあげる。

```html:index.html
@section scripts{
<script type="text/javascript">
    $(function(){
        //index.htmlで使うjsの処理を記述
    });
</script>
}
```

### _ViewStart.cshtml

最初に実行する処理を記載する。

```html:_ViewStart.html
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}
```
【Swift】dictionaryでvalueの最大値だけを取得する

日本語のサイトで,ぱっと出てこなかったので自分用に記録.
`Optional型`がまだいまいち理解できておらず`Forced unwrapping`をガンガン使ってしまうが、よくないんだろうな...

#dictionaryでvalue最大値を取得
```dictionary.swift
let dictionary: [String: Int] = ["1": 55, "2": 104, "3": 9]
let greatestDic = dictionary.max { a, b in a.value < b.value }

print(greatestDic) // -> "Optional(("2": 104))"

let maxValue = greatestDic!.value
print(maxValue) // -> 104
```

#配列・辞書の使い方が難しい
入力値が増えてくると多次元配列をどう扱っていいか、辞書を使ったほうがいいのか等々うまくコントロールできなくなってきています。
こういう問題は競技プログラミング的な勉強をしたほうがいいのだろうか。
ONNXで eliminate_identity 最適化


ONNXがサポートしている最適化 eliminate_identity を調べてみました。

ソースで検索するとここが見つかりました。

https://github.com/onnx/onnx/blob/master/onnx/optimizer/passes/eliminate_identity.h

```c++
  bool patternMatchPredicate(Node* node) override {
    return node->kind() == kIdentity;
  }
  bool runTransform(Node* node, Graph&, NodeDestroyType& destroy_current)
      override {
    node->output()->replaceAllUsesWith(node->input());
    destroy_current = NodeDestroyType::DestroyOne;
    return true;
  }
```

nodeのkindがkIdentityだと、そのノードの入力を出力に置き換えて、ノード自体を削除してるようです。

そもそもの identity の仕様はここ。

https://github.com/onnx/onnx/blob/master/docs/Operators.md#Identity

入力をそのまま出力するノードです。多分単位行列的な意味で、identity という名前なんでしょう。

実際にやってみましょう。

Identityのnodeが入ったグラフを作ります。

![eliminate_identity.onnx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327/4f545bf1-728e-a5c0-eb71-6b4255f8ed6f.png)


```python
# 最適化パスを指定
passes = ['eliminate_identity']

optimized_model = optimizer.optimize(model_def, passes)
onnx.save(optimized_model, 'onnx/eliminate_identity_optimized.onnx')
```

passにeliminate_identityを指定して、optimizer.optimizeを呼び出します。

![eliminate_identity_optimized.onnx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327/4c335ff2-a452-5c3c-76e8-a9d44b100e71.png)


予想通り、Identity のノードが削除されました。

全ソースはこちら

```python
import onnx
from onnx import helper
from onnx import TensorProto
from onnx import optimizer

X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [1, 2])
Y = helper.make_tensor_value_info('Y', TensorProto.FLOAT, [1, 4])

node_def = helper.make_node(
    'Pad',
    ['X'],
    ['pad_out'],
    mode = 'constant',
    value = 1.5,
    pads = [0, 1, 0, 1]
)

I_op = helper.make_node(
    'Identity',
    inputs = ['pad_out'],
    outputs = ['Y']
)


graph_def = helper.make_graph(
    [node_def, I_op],
    'test-model',
    [X],
    [Y]
)

model_def = helper.make_model(
    graph_def,
    producer_name='onnx_example'
)

onnx.save(model_def, 'onnx/eliminate_identity.onnx')

# 最適化パスを指定
passes = ['eliminate_identity']

optimized_model = optimizer.optimize(model_def, passes)
onnx.save(optimized_model, 'onnx/eliminate_identity_optimized.onnx')
```
[備忘録]Pythonで特定のclassの内容をスクレイピングする

#概要
PythonのBeautifulSoup4で特定のページの特定のclassの内容を取得する方法のメモ。

#インストール
必要なライブラリをインストール

```
$ pip install beautifulsoup4
```

#スクレイピング
Qiitaの自分のプロフィール欄を題材に試してみます。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248994/7241ca3f-ca91-9c9b-3a88-c624616ae7a3.png)

自分の記事一覧から各記事のタイトルを取得します。


##ソースコードはこちら。
必要に応じて対象サイトのURL、要素とclass名を書き換えてください。


```python:scraping.py
#モジュールのインポート
import urllib.request
from bs4 import BeautifulSoup

#対象のサイトURL
url = "https://qiita.com/sksk_go"

#URLリソースを開く
res = urllib.request.urlopen(url)

#インスタンスの作成
soup = BeautifulSoup(res, 'html.parser')

#必要な要素とclass名
name = soup.find_all("div", class_="ItemLink__title")

#取得したタイトル情報を出力
ret = []
for t in name:
    ret.append(t.text)

print(ret) # ['item1', 'item2', ～]
```

##実行結果
```
$ python scraping.py
['AIに自分の顔を判定させたら失敗した話（番外編）', '○○に似てると言われ困ったので、AIに判定させてみた', 'obnizで夏っぽいことしてみた', 'LINEで減塩量を可視化しようとした話', 'IoTを活用して、ただいまと言ったらおかえりが返ってくる仕組みを
作る', '悩める恋心を助けるためのLINE Botを作ってみた']
```

成功してますね。

業務でもたまに使うのでメモ代わりに。
Dockerで作成した既存Rails RefineryCMSプロジェクトにRefineryCMS拡張機能を追加

# この記事ですること
* [RailsプロジェクトのDockerをクローンして、RefineryCMSを追加した際の手順](https://qiita.com/bonny_d/items/2a3e04b68a74b4a2392d)からの続き。
* 基本的に公式サイトの[Generate an Extension to Use Your MVCs](https://www.refinerycms.com/guides/generate-an-extension-to-use-your-mvcs)の手順を行う


# 拡張機能eventの生成
* 下記コマンドを実行  
event機能をengineとして追加  
eventには、title,date,photo,blurbという項目を作成する  
各項目のデータ型については公式サイト参照

```
$ docker-compose run rails rails generate refinery:engine event title:string date:datetime photo:image blurb:text
Starting lambellweb_data_1 ... done
Starting lambellweb_db_1   ... done
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
Running via Spring preloader in process 36
      create  vendor/extensions/events/lib/generators/refinery/events_generator.rb
  :
      append  Gemfile
------------------------
Now run:
bundle install
rails generate refinery:events
rake db:migrate
rake db:seed
Please restart your rails server.
------------------------
```

Gemfileには下記が追加されている

```
gem 'refinerycms-events', path: 'vendor/extensions'
```


* 前述のログ出力の通り、下記を実行

```
docker-compose run rails bundle install
docker-compose run rails rails generate refinery:events
docker-compose run rails rake db:migrate
docker-compose run rails rake db:seed
```

# 確認
* サーバー起動

```
docker-compose up
```

* http://localhost:3000/ にアクセス  
Events が追加されている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281492/68b6d117-64d3-96dd-c981-a488441e6a2a.png)

* http://localhost:3000/refinery/events にアクセス  
Eventsタブが追加されている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281492/1cfab058-229f-8bdb-74ff-07641a4bd9e4.png)
【前処理】小数点がカンマになっているデータをピリオドに変えたい

意外と知らない人が多かったため記事にしてみました。
手っ取り早く答えだけ知りたい方は結論まで飛ばしてください。

※Python3とPandasを使用することを前提としています。
# 背景
とあるデータを元に機械学習を行おうとしたところ

中のデータを見てみると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492154/c5b19bd3-19a0-76a3-898f-e2ebaebf5a23.png)

11,2や12,9など見慣れぬ表記が

Google先生に聞いてみると、どうやらドイツなどの一部地域では、小数点を'.'ではなく','で表記しているそうです。

しかし、このまま読み込んでしまうと

```python
df = pd.read_csv("ファイルのパス")
print(type(df['distance'][0]))
```

```text:output
<class 'str'>
```

このようにfloat型として扱いたいデータがstr型として扱われてしまいます。

ではどうすればこの問題を回避することができるのでしょうか

# アイデア1：諦めてExcelで編集
Excel等で元データをいじれば解決しそうですが、このやり方はあまりスマートではありませんね。
また、Jupyter Notebook等でレポートを作成する際にも、元データの編集の履歴が残らないと、運用の際に不具合が起きる可能性がある上、再現性が低くなります。

# アイデア2 str.replaceで置換してfloat型に変換
Excelで元データをいじるのがスマートでないなら、Pythonで変換してみましょう。

```python
df['consume']= df['consume'].str.replace(',' ,  '.').astype(float)
df['temp_inside']= df['temp_inside'].str.replace(',' ,  '.').astype(float)
df['distance']= df['distance'].str.replace(',' ,  '.').astype(float)
```

このように各列に対して','を'.'に置換する処理を行い、float型に変換すると

```python
print(type(df['distance'][0]))
```

```text:output
<class 'numpy.float64'>
```

無事、float型として扱えるようになりました。

しかし、このやり方にも問題点はあります。

今回は対象とする列が少なかったため、一つずつ置換するやり方を行いましたが、これが100列、1万列となればどうでしょうか。
一つずつ変換をすれば確かに問題は解決しますが、ミスの原因になりやすいし、ソースが汚くなってしまいます。

どうにかして、全てを一括で変換する方法はないのでしょうか

# アイデア3(おすすめ)：読込の時点で小数点を識別する記号を指定
これが今回紹介したかった方法です。

pandasでcsvを読み込む際には `read_csv` という関数を使いますが、この関数には `decimal` という引数があります。この引数を以下のように指定すると

```python
df = pd.read_csv("ファイルのパス", decimal=',')
```

たった一行で','を小数点として読み込ませることができます
実際に変換したデータを見てみると

```python
df.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492154/9b11424c-8e3d-f71b-c08d-49af65ac6105.png)

このようにすべてのデータに対して小数点が','から'.'に変換されています。

もちろんデータ型を確認しても

```python
print(type(df['distance'][0]))
```

```text:output
<class 'numpy.float64'>
```

float型として扱われています。

# 結論

```python
df = pd.read_csv("ファイルのパス", decimal=',')
```

このように `read_csv` の引数として `decimal=','` と指定するだけで小数点を','から'.'に変換されfloat型として扱うことができます。

是非データ分析等を行う際にご活用ください 。



`read_csv`の細かい仕様等は[公式のドキュメント](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html)をご参照ください。
AWS ElastiCacheに外部から接続【socat + socks プロキシ編】

EC2インスタンスを立ててプロキシするような記事はあるけど、
https://qiita.com/suzuki_sh/items/1d20c467bb46501bce2e

[socat](https://linux.die.net/man/1/socat) が socks4a プロトコル使えるので、 socks プロキシ経由で繋げば iptable いじらなくてもいけるよ、っていう話。
本番環境向けとかでは使わないほうが良いと思う。

## 踏み台サーバに socks プロキシを通す

```bash
ssh -D 1080 bastion
```

## local のポートに繋ぐ

```bash
socat -dd TCP-LISTEN:16379,fork,reuseaddr SOCKS4A:localhost:XXXXX.XXXXXX.XXXX.XXXXX.cache.amazonaws.com:6379,socksport=1080
```

```bash
$ redis-cli -h localhost -p 16379 ping
PONG
```

## unix domain socket に繋ぐ

```bash
socat -dd UNIX-LISTEN:ec.sock,fork,reuseaddr SOCKS4A:localhost:XXXXX.XXXXXX.XXXX.XXXXX.cache.amazonaws.com:6379,socksport=1080
```

```bash
$ redis-cli -s ec.sock ping
PONG
```

おわり。
CocoaPodsに最新バージョンがない場合

##はじめに
CocoaPodsを使ってライブラリを入れたいが、CocoaPodsに最新バージョンがない場合の対処法

##開発環境
Xcode11
Swift4.2

##状況
pod 'Analytical', '~> 0.9.1'
をすると、下記エラーが発生する。

CocoaPodsのAnalyticalを見ると、「Analytical 0.8.0」とあるので、最新は0.8.0と認識されているようだ。

```
[!] CocoaPods could not find compatible versions for pod "Analytical/Log":
  In Podfile:
    Analytical/Log (= 0.9.1)

None of your spec sources contain a spec satisfying the dependency: `Analytical/Log (= 0.9.1)`.

You have either:
 * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
 * mistyped the name or version.
 * not added the source repo that hosts the Podspec to your Podfile.
 * 
```

##対処法
```
pod 'Analytical', :git => 'https://github.com/Legoless/Analytical.git', :branch => 'master'
```

このようにすると、masterから最新版を取得してくれる。

他のライブラリでも実施可能。
AWS S3 New()で困ったお話し

S3 Selectしたい要件があったので実装してみたが、
動く環境によって実装方法が違ったというお話。

ちゃんと公式ドキュメント読めば予め回避できたかもしれない。。

前提条件として、S3Bucketには適切なアクセス権限がついているものとする。
※EC2ロールの許可

### だめパターン(roleARN指定)
EC2と同じroleでNew()すればよいやろ。

```golang
sess := session.Must(session.NewSession())
creds := stscreds.NewCredentials(sess, arn)
S3: s3.New(
	sess,
	aws.NewConfig().WithRegion(region).WithCredentials(creds),
)
```

EC2にあげて、さぁテスト。

```
AccessDenied: Access denied
    status code: 403
```

なんでや...

### ユーザ指定
こうならlocalでもどこでも動くけど、
S3所有者だと権限強すぎだし、
別ユーザ作成するのもな。。。

```golang
sess := session.Must(session.NewSession())
conf := aws.NewConfig().WithRegion(region).WithCredentials(credentials.NewStaticCredentials([id], [secKey], ""))
S3: s3.New(
	sess,
	conf,
)
```

### 正解(EC2で実行しているのでsessionをshare)
こうだった。
※EC2実行ロールでS3アクセスできる前提。

```golang
sess := session.Must(session.NewSessionWithOptions(session.Options{
	SharedConfigState: session.SharedConfigEnable,
}))
S3: s3.New(
	sess,
	&aws.Config{Region: aws.String(region)},
)
```

参考：https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/go/example_code/s3/s3.go#L44
地味に役立つafter TIPS✍


#配置したレイヤーに合わせてコンポジションをリサイズ

https://video-knowledge.com/ae_comp_resize

(1)スクリプトを使う
(2)目標範囲を設定してクロップする


#選択したレイヤーの長さをワークエリアに設定
command+option+B

http://www.ayatoweb.com/ae_lab/lab76.html


#レイヤーのカット
shift+command+D


#コンポジションのループ
2つのレイヤーをloopOutでループさせたいけど
1フレーム空白ができてしまうときの改善方法

(1)タイムリマップを設定
(2)終わりのキーフレームの１つ前に新たにキーフレームを生成
(3)最初のキーフレームをコピー
(4)元々あった終わりのキーフレームの位置にペースト
(5)編集＞キャッシュの消去＞すべてのメモリを行う。

https://www.youtube.com/watch?v=Ngja9-TEpzU


#XMPメタデータを作らないようにする

環境設定＞メディア＆ディスクキャッシュ
□読み込み時に　XMP　ID　をファイルに書き込む
のチェックをはずす。


#Dockの表示/非表示
command+option+D

↑すごく便利。知れてよかった！
afterだけではなく、Photoshop/Illustratorでも効く。

地味Tipsで地道に時短。大事な3Gですね…
【Ubuntu】Amazon Correto 8をインストール手順

[Amazon Corretto 8 のインストール手順](https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-8-ug/generic-linux-install.html)から、Ubuntuのインストール手順のみ忘備録としてまとめました。

## 環境
Ubuntu 18.04

## Amazon Corretto 8のJDKをダウンロード、インストール

```bash
# java-common パッケージをインストール
sudo apt-get update && sudo apt-get install java-common
# Linux .deb ファイルをダウンロード
wget https://d3pxv6yz143wms.cloudfront.net/8.222.10.1/java-1.8.0-amazon-corretto-jdk_8.222.10-1_amd64.deb
# Amazon correttoをインストール
sudo dpkg --install java-1.8.0-amazon-corretto-jdk_8.222.10-1_amd64.deb
```

上記の「Linux .deb ファイル」のダウンロードURLは、jdk_8.222.10-1（2019年9月20日時点）のものなので[こちら](https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-8-ug/downloads-list.html)から最新版が出ていないか要確認。

以上

## 参考
[Amazon Corretto Documentation](https://docs.aws.amazon.com/corretto/index.html)
FlashAir開発用サイト（2019.9～）

#はじめに

「FlashAir Developers」という東芝の公式サイトがあり、
FlashAir開発に必要な情報が存在したが、2019年9月に閉鎖したため、

#経緯
[無線LAN搭載SDメモリーカード「FlashAir」開発者向けサイトが9月で閉鎖]
(https://www.itmedia.co.jp/news/articles/1906/14/news108.html)

[閉鎖された公式サイト（FlashAir Developers）]
(https://www.flashair-developers.com/ja/discover/app/)

#開発者向け情報のバックアップ

[githubのバックアップ]
(https://flashair-developers.github.io/website/)

[Wayback Machineのバックアップ]
(http://web.archive.org/web/20190810000622/https://www.flashair-developers.com/ja/)
ONNXでeliminate_deadend 最適化

ONNXがサポートしている最適化eliminate_deadend を調べてみました。

字面から接続先がない何か（deadend）を消してくれそうです。

ソースで検索するとここがひっかります。
https://github.com/onnx/onnx/blob/master/onnx/optimizer/passes/eliminate_deadend.h

```c++
unsigned int EliminateDead(Graph& graph) {
    unsigned int nodes_removed = 0;
    auto nodes = graph.nodes().reverse();
    for (auto it = nodes.begin(); it != nodes.end(); it++) {
      auto node = *it;
      if (!node->hasUses()) {
        nodes_removed++;
        it.destroyCurrent();
      }
    }
    return nodes_removed;
  }
```
ソースを見ると、グラフのノードを逆順にして、使っていないnodeを削除しているようです。大事なのはノード単位の最適化らしいということ。

実際にやってみましょう。

![eliminate_deadend.onnx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327/6a852d28-98c0-752f-eec2-d872ca9433c0.png)

こういうONNXを作ります。
Yはグラフの出力に接続されていますが、Reluの出力はどこにもつながっていません。

```python
graph_def = helper.make_graph(
    [node_def, relu0_op],
    'test-model',
    [X],
    [Y]
)
```

ONNXで最適化を行うためには、最適化のpassを指定してoptimizer.optimizeを呼び出します。今回試したいのは、eliminate_deadendなので、このようにしました。

```
# 最適化パスを指定
passes = ['eliminate_deadend']

optimized_model = optimizer.optimize(model_def, passes)
onnx.save(optimized_model, 'onnx/eliminate_deadend_optimized.onnx')
```

実行してみると、見事にReluが削除されました。やったね。

![eliminate_deadend_optimized.onnx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327/270f3b67-de28-d96b-7bf9-282179a229ed.png)

全ソースはこちら

```python
import onnx
from onnx import helper
from onnx import TensorProto
from onnx import optimizer

X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [1, 2])
Y = helper.make_tensor_value_info('Y', TensorProto.FLOAT, [1, 4])

node_def = helper.make_node(
    'Pad',
    ['X'],
    ['Y'],
    mode = 'constant',
    value = 1.5,
    pads = [0, 1, 0, 1]
)

relu0_op = helper.make_node(
    'Relu',
    inputs = ['Y'],
    outputs = ['relu0_out']
)


graph_def = helper.make_graph(
    [node_def, relu0_op],
    'test-model',
    [X],
    [Y]
)

model_def = helper.make_model(
    graph_def,
    producer_name='onnx_example'
)

onnx.save(model_def, 'onnx/eliminate_deadend.onnx')

# 最適化パスを指定
passes = ['eliminate_deadend']

optimized_model = optimizer.optimize(model_def, passes)
onnx.save(optimized_model, 'onnx/eliminate_deadend_optimized.onnx')

```
Rails6 のちょい足しな新機能を試す84（parameterize編）

# はじめに

Rails 6 に追加された新機能を試す第84段。 今回は、 `parameterize` 編です。
Rails 6 では、 `parameterize` で `locale` オプションを指定できるようになりました。

Ruby 2.6.4, Rails 6.0.0 で確認しました。

```shell
$ rails --version
Rails 6.0.0
```

今回は、name (名前) 属性をもつUser の CRUD を作成し、 URL を parameterize を使って変更することで動作確認します。

# プロジェクトを作る

```shell
rails new rails_sandbox
cd rails_sandbox
```

# User の CRUD を作る

name の属性をもつ User のCRUDを作ります。

```shell
bin/rails g scaffold User name
```

# Userモデルに to_param メソッドを追加する

User モデルで、 to_param メソッドを追加します。このメソッド内で `locale` オプションつきの `parameterize` メソッドを使います。

```ruby:app/models/user.rb
class User < ApplicationRecord
  def to_param
    "#{id}-#{name.parameterize(locale: :de)}"
  end
end
```

# config/application.rb を修正する

ドイツ語環境を整えるのが面倒なので、 `I18n::InvalidLocale` を避けるために、 `config/application.rb` を編集します。

```ruby:config/application.rb
...
I18n.enforce_available_locales = false
```

# ドイツ語用のロケールファイルを作成する

ドイツ語の変換ルールの locale ファイルを用意します。

```yaml:config/locales/de.yml
de:
  i18n:
    transliterate:
      rule:
        Ä: AE
        ä: ae
        Ö: OE
        ö: oe
        Ü: UE
        ü: ue
        ß: SS
```

# マイグレーションを実行する

```shell
$ bin/rails db:create db:migrate
```

# 画面からユーザーを登録する

`bin/rails s` を実行し、 http://localhost:3000/users/new にアクセスしてユーザーを登録します。

name には、 `Jürgen` と入力します。 [Create User] ボタンを押します。

![user_new.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209941/11fbeca3-8620-220d-e79f-339da802622e.png)

詳細画面のURLは、 `http://localhost:3000/users/1-juergen` と変換されていることがわかります。
(`Jürgen` → `juergen` と変換される。）

![user_show.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209941/d72c5c18-a52d-ecd3-5e3f-9f64b79d2d97.png)

# locale を指定しなかった場合

今回の場合、 locale オプションを指定しなかった場合

つまり、

```ruby:app/models/user.rb
class User < ApplicationRecord
  def to_param
    "#{id}-#{name.parameterize}"
  end
end
```

とした場合、URLは、 locale オプションは、nil になり、 `I18n.locale` が使われます。
今回は、 `I18n.locale` をデフォルトから変更していないため、 `I18n.locale` は `en` になるため、 URLは、 `http://localhost:3000/users/1-jurgen` となります。
(`Jürgen` → `jurgen` と変換される。）

# 試したソース

試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try084_parameterize_locale

# 参考情報

* [What is new in Rails 6.0](https://bogdanvlviv.com/posts/ruby/rails/what-is-new-in-rails-6_0.html)
* [Add locale option to #parameterize](https://github.com/rails/rails/pull/35571)
* [I18n.transliterate](https://github.com/ruby-i18n/i18n/blob/master/lib/i18n.rb#L268)
neovimのアップデート

いつもneovimの新しいバージョンが出た際に、どうやってインストールしていたか忘れて調べることとなってるので
手順を備忘録として残しておきます。

## 1. uninstall

```shell
sudo rm /usr/local/bin/nvim
sudo rm -r /usr/local/share/nvim/
```

## 2. clone

https://github.com/neovim/neovim

```shell
git clone https://github.com/neovim/neovim.git
```

## 3. install

https://github.com/neovim/neovim/wiki/Installing-Neovim#install-from-source
を参考に

```shell
cd neovim
make CMAKE_BUILD_TYPE=Release
sudo make install
```
Nextcloud 17 の正式リリースはもうすぐです。

Nextcloud の次期メジャーバージョンである Nextcloud 17 の実装機能が凍結され、リリース候補版として、2つ目のリリース候補版である **Nextcloud 17 RC2** がリリースされました。

※ダウンロードはここから: [Nextcloud 17 RC2](https://download.nextcloud.com/server/prereleases/nextcloud-17.0.0RC2.zip)

予定では、正式版リリース前の最後のリリース版となっており、いよいよ 2019年9月26日に Nextcloud 17 が正式リリース予定となっております。もうすぐですね！

### Nextcloud 17 今後のリリーススケジュール

* Beta 1: 2019-08-15
* Beta 2: 2019-08-22
* Beta 3: 2019-08-29
* Beta 4: 2019-09-05
* RC 1: 2019-09-12
* RC 2: 2019-09-19　**← NOW !!**
* Release: 2019-09-26

ダウンロードしてインストールしましたが、目立った不具合は確認されず、より洗練してきている印象です。アプリも Nextclour 17 への対応がだんだん追い付いてきております。

また、Nextcloud 17 でのリリース機能について、 Nextcloud 社よりアナウンスがされております。
新機能の概要としては下記のとおりです。

* リモートデバイスからファイルを強制的に消去するリモートワイプ機能
* リッチテキストエディタ "Text" の機能アップ
* 安全に閲覧させるための強制透かし機能
* ユーザーの最初のログイン後に2要素認証の設定を有効化もしくは強制させる機能
* Outlook Add-in での安全なメールボックス
* LDAP 書き込みのサポートにより、Nextcloud から LDAP ユーザーを管理可能
* Amazon S3 のバージョニングのサポート、IBM Spectrum との統合、Global Scale との連携

よりセキュアに Nextcloud を運用するための機能強化が図られております。

＜参考＞
[Nextcloud 17 scales up and improves data protection with Remote Wipe, collaborative text editor, 2FA updates, IBM Spectrum Scale support and Global Scale improvements](https://nextcloud.com/blog/nextcloud-17-scales-up-and-improves-data-protection-with-remote-wipe-collaborative-text-editor-2fa-updates-ibm-spectrum-scale-support-and-global-scale-improvements/)


**★この記事は、[スタイルズ社のNextcloudサイト](https://nextcloud.stylez.co.jp/) の [Nextcloudブログ](https://nextcloud.stylez.co.jp/nextcloudblog)にも公開しております！**
ログ出力のガイドライン


#はじめに
筆者のログの使い方の備忘録です。
NLogを前提として記述しています。

#全般
バイナリデータの容量は知れているので、迷ったら出力しておく。
一応、容量は計算しておく。

必ず出力したい内容　→　出力日時、レベル、事象内容
可能なら出力したい　→　スレッド番号、ファイル名、クラス名、関数名、ソース行数

出力ファイル自体を増やすのもあり。
ファイル1はF～Iまで出力、ファイル2はD～Tまで出力、など

レベルのイニシャルは上から「FewIdt」と覚える。（Few ID t）

#レベル方針

##Fatal(致命的)
死人やケガ人、莫大な損害などが発生する可能性があるときに使用する。
使用する開発領域は限られており、業界によっては未使用でいい。

##Error(誤り)
原則発生してほしくはないが、Fatalほど被害がない対象に使用する。
システムダウンやデータ破損が発生する可能性があるときや、
Exceptionをキャッチしたときに。（Exceptionと同じE）

##Warn(警告)
実装はしているが、取扱注意の動作をするときに使用する。
「本当によろしいですか？」などの警告を無視して実行されたときなどに。

##Info(情報)
正常系を通ったことを知るために使用する。
正常系ログを出力しない人も見かけるが、保守段階で動作状況を知るために必要である。
関数の始まりや終わり、入出力値などを出力しておく。
使用頻度が最も多い。

##Debug(デバッグ)
文字通りデバッグ用として使用する。
開発時に使用して、簡易テストするために使う。

## Trace(追跡):
開発時に流れを追ったり、時間計測が必要な時に使用する。
Traceを使わずにDebugにまとめてもよく、使用頻度は低い。
WindowsとMacの比較メモ

#はじめに
筆者が調べて特徴的だと思った違いのメモ。

#Win
MsOfficeが強力だが、有料。
PCゲーム、VRに強い。
全体的な自由度が高い。
価格のコスパ有利。
マシンの選択肢が多い。


#Mac
プリインストールPGが強力で無料。（特に画像、動画、音楽などの加工）
モバイルゲームに強い。
iPhone,iPadなどと連携してエコシステムを作成したら強い。（逆に言うと、ちぐはぐだと微妙）
全体的な自由度が低い。
マシンの選択肢が少ない。
BackSpaceキーがない。（fn+Deleteでできる。）
iOSアプリを開発・リリースするなら、事実上必須。


#その他
エコシステムをどちらに寄せるかという視点もある。
Googleサービスを使えばどちらからもアクセスしやすい。
2019年時点ではOS由来の脆弱性はどちらも安定している。
Macの「iWork」「Numbers」「Pages」が、MsOfficeに相当する。
使い続けたほうにいろいろ慣れてしまう。
　キーボード、コマンド、CRLF、、、
開発学習 社員同士のコミュニケーション活性化

社員管理システム
コンセプト:社員同士のコミュニケーションのきっかけ作り
→似顔絵変換
→興味があるキーワードタグ付け

バージョン管理技術習得
テスト自動化技術習得

ドキュメント
システム概要図
システム構成図
【備忘録】SQL Serverに接続できない場合の対処法

先日SQL Serverを新たに導入したのですが、外部PCから接続できず苦戦しました。
その際に試したことを記録しておきます。
誰かの助けになれば。

##現象と原因予想
DBサーバにSQL Serverをインストールし各種設定を行いました。しかしいざAPサーバからデータベース接続しようとしたところ、何度試しても接続に失敗してしまいます。

A5SQLで接続を試み、下記のメッセージを得ました。
Cannot connect to server on host 'ipadress' Connectiontimed out

原因の切り分けとして、まず同様の操作をDBサーバ内で行いました。
問題なく動作するため、サーバ間の接続（ファイアウォールあたり？）でコケているのかな、と予想しました。

##まず試したこと
まずQiitaの他記事でまとめられているようなことを片っ端から試行/確認しました。
[以下 参考記事]
[【TIPS】SQL Server Expressに接続できない](https://qiita.com/ttoori-ttoori/items/a146a97bb9071894e247)
[外部のSQL Serverに接続できないときの備忘録](https://qiita.com/Nanakusajp/items/7211a5721e725fc6329c)


一応書いておくと、確認したのは下記項目です。
・TCP/IP有効化・ポート設定
・Windowsファイアウォール設定
・SQL Server Browserの起動

しかし繋がらない。。。

##他に試したこと
###DB設定
####リモートサーバ接続の許可
MSSMSにて
インスタンスを右クリック
＞「サーバのプロパティ」の左側メニュー「接続」をクリック
＞「このサーバへのリモート接続を許可する」にチェック

####アクセス権限の設定・確認
私の場合はローカルで接続できたのでここちは問題ないかなと思いつつ一応確認。

①インスタンスの権限
MSSMSにて確認
インスタンスをクリック
＞「セキュリティ」＞「ログイン」＞該当ユーザで右クリック
「ログインのプロパティ」にて
＞「ユーザマッピング」操作したいテーブルにチェックがついているか？ロールは適切か？
（接続確認がしたいのでとりあえず「db_owner」にしておく）
＞「セキュリティ保護可能なリソース」で「SQLの接続」など必要項目にチェックがついているか？

②データベース権限の確認
インスタンスをクリック
＞「データベース」＞操作したいデータベース＞「セキュリティ」＞「ユーザー」＞該当ユーザで右クリック
＞「メンバーシップ」で「db_owner」にチェックがついているか？


###プログラムの許可
私の場合はこれが原因でした。

Windowsファイアウォールで下記プログラムへの接続を許可する必要があります。
%ProgramFiles%\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\Binn\sqlservr.exe

コントロールパネル＞システムとセキュリティ＞Windowsファイアウォール
＞詳細設定＞受信の規則＞新しい規則
・規則の種類 ... 「プログラム」
・プログラム... 「このプログラムのパス」にパス入力
・操作... 「接続を許可する」
・プロファイル...とりあえず全てに適用
・名前 ... 好きな名前を入力



これでAPサーバから接続できるようになりました。
よかったよかった。
正規表現を用いてphpとstringの差分を整える

Phpを用いたtxtスクリプトでは改行が自動挿入されません。
```"\n"```を行末に加えることで解決します。

```example.php
<?php if ($isMaskMail) { ?>
連絡先          ：  XXXXXX
緊急連絡先      ：  XXXXXX
<?php } else { ?>
連絡先          ：  <?php echo($phone) . "\n"?>
緊急連絡先      ：  <?php echo($contactPhone) . "\n"?>
<?php } ?>
```
Railsとmysqlの連携 ~設定をどこに書くのか~

# これもまた何故かよく忘れる
英単語覚えていくと、結構重要な単語なのに覚えられない単語がいくつか出てくる瞬間あるじゃあ無いですか。それと同じだと思っています。なので、覚書です。gemにmysql2を入れてあることが前提になります。

## 手順1
mysqlでデータベースとユーザーを作成するクエリを実行する。

```
mysql> create database rails_app_sample;

mysql> create user 'dev_user'@'localhost' identified by '*******';
```

## database.ymlに先の設定を書く

```database.yml
default: &default
  adapter: mysql2
  host: localhost
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: dev_user
  password: ******
  socket: /tmp/mysql.sock

development:
  <<: *default
  database: rails_app_sample
```

こんな感じで、開発用の階層に設定を書いていきます。これでmigrateできれば問題ありません。
ONNXがサポートしている最適化一覧を取得

ONNXには最適化の機能も含まれています。

https://github.com/onnx/onnx/blob/master/docs/PythonAPIOverview.md

このプログラムを実行すると、サポートしている最適化の一覧を表示できます。

```python
from onnx import optimizer

all_passes = optimizer.get_available_passes()
print("Available optimization passes:")
for p in all_passes:
    print(p)
print()
```

順番に実行してみたい。

```text
Available optimization passes:
eliminate_deadend
eliminate_identity
eliminate_nop_dropout
eliminate_nop_monotone_argmax
eliminate_nop_pad
eliminate_nop_transpose
eliminate_unused_initializer
extract_constant_to_initializer
fuse_add_bias_into_conv
fuse_bn_into_conv
fuse_consecutive_concats
fuse_consecutive_log_softmax
fuse_consecutive_reduce_unsqueeze
fuse_consecutive_squeezes
fuse_consecutive_transposes
fuse_matmul_add_bias_into_gemm
fuse_pad_into_conv
fuse_transpose_into_gemm
lift_lexical_references
nop
split_init
split_predict
```
## onnxのバージョン
実行したONNXのバージョンです。バージョン上がれば内容も変わりそうです。

```python
>>> import onnx
>>> onnx.__version__
'1.5.0'
```
1.5.0ですね。[^1]

## 実際に最適化を試してみた　[^2] [^3]
- [ONNXでeliminate_deadend 最適化](https://qiita.com/natsutan/items/734015372858a6a9cf92)
- [ONNXで eliminate_identity 最適化](https://qiita.com/natsutan/items/ff8b32f1d74f30a5a362)
- [ONNXで eliminate_nop_dropout 最適化](https://qiita.com/natsutan/items/3b50a49adae84a0242d8)
- [ONNXで eliminate_nop_monotone_argmax 最適化](https://qiita.com/natsutan/items/b13429cdb855ee7d77d0)
- [ONNXで eliminate_nop_pad 最適化](https://qiita.com/natsutan/items/52652ee9533e0440bece)
- [ONNXで eliminate_nop_transpose 最適化](https://qiita.com/natsutan/items/fb07004ea9747f75974a)
- [ONNXで eliminate_unused_initializer 最適化](https://qiita.com/natsutan/items/9bdb26f694fd0eea3723)
- [ONNXで extract_constant_to_initializer 最適化](https://qiita.com/natsutan/items/ed22141f90b3027e122a)
- [ONNXで fuse_add_bias_into_conv 最適化（駄目でした）](https://qiita.com/natsutan/items/cc6900f7f7706158cd80)
- [ONNXで fuse_bn_into_conv 最適化（駄目でした）](https://qiita.com/natsutan/items/24f72c8c86a29fd6568d)
- [ONNXで fuse_consecutive_concats 最適化](https://qiita.com/natsutan/items/0c81aeaad942254f9cfc)
- [ONNXで fuse_consecutive_log_softmax 最適化](https://qiita.com/natsutan/items/14555d5c2114b6c13175)
- [ONNXで fuse_consecutive_reduce_unsqueeze 最適化](https://qiita.com/natsutan/items/9656faac457f7b73bf03)
- [ONNXで fuse_consecutive_squeezes 最適化](https://qiita.com/natsutan/items/c0b41192ada75c73e769)
- [ONNXで fuse_consecutive_transposes 最適化](https://qiita.com/natsutan/items/d3e9f81b6f62e8238a5a)
- [ONNXで fuse_matmul_add_bias_into_gemm 最適化](https://qiita.com/natsutan/items/626a8591a2a6675a0486)
- [ONNXで fuse_pad_into_conv 最適化（駄目でした）](https://qiita.com/natsutan/items/e4235c1e83002243cf51)
- [ONNXで fuse_transpose_into_gemm 最適化](https://qiita.com/natsutan/items/e60a828a1a3ab20d1593)
- [ONNXで split 最適化](https://qiita.com/natsutan/items/a1e2bc6dff95b40644f8)


[^1]: 途中から1.6に上げたが、最初からやり直す気力が無い
[^2]: lift_lexical_referencesは試すところまでもっていけず。Python APIのもう一つ下のレイヤーだと思う。
[^3]: nopは意味のないOPを削除するのではなく、最適化自体を何もしない。
[Linux] 区切り文字を変更する (IFS)


# IFS (Internal Filed Separator)

## 区切り文字を変更する

```bash
#!/bin/bash

OLD_IFS="$IFS"
IFS=$'\n'
...
IFS="$OLD_IFS"
```

### 区切り文字の指定例
```
IFS=$' \t\n' # スペース, タブ, 改行 (default)
IFS=$','
IFS=$'-'
IFS=$':'
IFS=$';'
IFS=$'' # 未指定も可能
```

## IFSの情報をダンプする
```
# macOS(10.14.5) の IFS情報
$ echo -n "$IFS" | od -b
0000000   040 011 012                                                    
0000003
```
React HooksのuseMemo,useEffectの動きを確認する

# React Hooksの動きを確認する

　便利だから何となくhooksを使っているという状況なので、実際の動きを確認してみることにしました。

## 検証用ソースコード

プログラム自体は単純で、チェックボックスを表示するだけのプログラムです。
チェックボックスを押してコンポーネントが再評価される際に、どういう動きをするのかという確認です。

```tsx:
import React, { useMemo, useEffect, useState } from "react";
import * as ReactDOM from "react-dom";

function App() {
  console.log("Function Start");
  useMemo(() => {
    console.log("Memo");
  }, []);
  //パラメータ有りuseEffect
  useEffect(() => {
    console.log("Effect[] Start");
    return () => {
      console.log("Effect[] End");
    };
  }, []);
  //パラメータ無しuseEffect
  useEffect(() => {
    console.log("Effect Start");
    return () => {
      console.log("Effect End");
    };
  });

  const [checked, setChecked] = useState(false);
  console.log("Function End");
  return (
    <>
      <input
        type="checkbox"
        checked={checked}
        onChange={e => {
          console.log("Check");
          setChecked(e.target.checked);
        }}
      />
    </>
  );
}
ReactDOM.render(<App />, document.getElementById("root") as HTMLElement);
```

## 検証結果

- ページ表示直後
Function Start
Memo
Function End
Effect[] Start
Effect Start

- チェックボックスを押した後
Function Start
Function End
Effect End
Effect Start

## 所感

　useMemoは作成直後に一回だけ呼ばれるため、本来の使い方ではありませんが、classコンポーネント移植時、コンストラクタでやっていた処理の代替で使えそうです。

　また、実際にやってみてよく分かっていなかったのは「Effect End」のタイミングです。前回のEffectを終了させてから再び開始されます。表示中の処理を行う箇所なのだから、確かにその動作が適切なわけです。

　hooksを使うと小さなコンポーネントを作る場合は、非常に手軽に使えるので重宝します。しかし重量級のコンポーネントの作成などは、classを使ってstateやプロパティを定義した方が使いやすい場合もあります。今後も適材適所でバランス良く使っていこうと思います。
Electron+React+Typescriptの開発環境を作る・改

# はじめに
前に[Electron+React+Typescriptの開発環境を作る](https://qiita.com/butachin/items/f8027bb7f6a4f01ad8e6)という記事を書いたのですが，create-react-appがTypescriptをサポートしたことによって，上記のやり方はオススメできなくなってしまったので，推奨される開発環境づくりをここに書いておこうと思います．

# アプリ起動まで
## アプリ作成
アプリ名は，小文字にしてください．npxを先頭につけるとcreate-react-appがグローバルにインストールされていなくても使用できます．

```
$ npx create-react-app [アプリ名] --typescript
```

# Electronの設定
[electron](https://github.com/electron/electron)と[electron-is-dev](https://github.com/sindresorhus/electron-is-dev)と[concurrently](https://github.com/kimmobrunfeldt/concurrently), [wait-on](https://github.com/jeffbski/wait-on)をインストールする．

```
$ yarn add -D electron electron-is-dev concurrently wait-on
```

publicフォルダ内にelectron.jsを作成する．

```public/electron.js
const electron = require('electron')
const app = electron.app
const BrowserWindow = electron.BrowserWindow

const path = require('path')
const isDev = require('electron-is-dev')
let mainWindow

function createWindow () {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    resizable: false,
    webPreferences: {
      nodeIntegration: true
    }
  })
  mainWindow.loadURL(
    isDev ? 'http://localhost:3000' : `file://${path.join(__dirname, '../build/index.html')}`
  )
  if (isDev) {
    // Open the DevTools.
    // BrowserWindow.addDevToolsExtension('<location to your react chrome extension>');
    mainWindow.webContents.openDevTools()
  }
  mainWindow.on('closed', () => (mainWindow = null))
}

app.on('ready', createWindow)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (mainWindow === null) {
    createWindow()
  }
})
```

package.jsonを編集する．
BROWSER=none yarn startを記述することでelectron起動時にブラウザが開かなくなります．
※Windowsの人はset BROWSER=noneとしてください．Macの人は下記の記述のままでOKです．

```package.json
{
 .
 .
 "homepage":"./",
 "main":"public/electron.js",
 .
 .
 "scripts":{
  .
  .
  "dev": "concurrently \"BROWSER=none yarn start\" \"wait-on http://localhost:3000 && electron .\""
 }
}
```

# アプリ起動
```
$ yarn dev
```

# 最後に
この業界は目まぐるしい速さでアップデートされていくので，今回のようにバージョンが変わったことによって，今までのやり方が変わることは多々あります．出遅れないようにしていきたいです．

# 参考
[[非推奨][TypeScript] create-react-appで始めるだいたいストレスフリーな開発環境の構築](https://qiita.com/Julia0709/items/f4bd953f8f96e11b678a)
[[TypeScript] create-react-appで始めるだいたいストレスフリーな開発環境の構築2
TypeScript](https://qiita.com/Julia0709/items/dfce1eed86e82c484040)
Golang で import cycle not allowed に引っかかった人へ

#はじめに

今回はエラーの紹介です。
Golang 初心者の方で、packageに、こんなエラーが出た人はいるんではないでしょうか？？

<img width="121" alt="スクリーンショット 2019-09-25 11.41.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233118/7867a9fe-b008-fc4f-d1c7-cca25c9a0884.png">
↓

```
can't load package: import cycle not allowed
```

import cycle ってなんやねん？
って人向けに記事を書きます。

# シンプルに関数を互いのパッケージで使わないでねって意味

### 成功例

例えばなんですけど

```main.go
import "./a"

func main() {
	a.PrintGreeting()
}
```

``` a/sample.go
package a

import (
	"fmt"

	"../b"
)

func PrintGreeting() {
	test := b.Greeting()
	fmt.Println(test)
}
```

```b/sample.go
package b

func Greeting() string {
	return "hello world"
}
```

っていうファイルがあって

```
$ go run main.go
```

の実行結果が

```
hello world
```

みたいになります。

### 失敗例

``` main.go
import "./a"

func main() {
	a.PrintGreeting()
}
```

``` a/sample.go

package a

import (
	"fmt"

	"../b"
)

func PrintGreeting() {
	test := b.SecondGreeting()
	fmt.Println(test)
}

func FirstGreeting() string {
	return "hello world"
}
```

```b/sample.go

package b

import "../a"

func SecondGreeting() string {
	return a.FirstGreeting()
}
```

このときに、今回のエラーが出ます！（汗）

つまりは、パッケージ内の関数を互いに呼んだときにエラーが出てるということです。（Cycleってそういう意味！）

関数を闇雲に沢山作っていくと、こういうエラーに遭遇します。

#結論
**設計を大事にしてメソッドを闇雲に生やすのは辞めましょう〜**

#宣伝
Qiitaの更新情報は Twitter でも共有してます！
是非フォローしてください！

https://twitter.com/ko_watanabe_jp

それでは！
DockerでTermuxのパッケージビルドを試す

# Termuxって何？

- Android端末でLinuxコンソールを動かすアプリです。
- Google Playから入手できます
-  ☞ https://play.google.com/store/apps/details?id=com.termux&hl=ja
- 本家
https://termux.com/

# もっと詳しく
- Android OSのカーネルはLinuxそのものであり、Linuxが動くこと自体はなんら不思議ではないですし初期のころからBusyBoxのようなLinuxのコマンドを１つのelfに固めて実行するコンソールアプリケーションはありました

- Termuxは、いわゆる BusyBox ではありますが、パッケージが比較的充実していますので、それ自体で軽量Linuxとして使用できます。

- TermuxはUbuntuなどのLinuxと異なり、ディレクトリ構成が以下のような制約を受けます。[Differences from Linux :Termux Wiki](https://wiki.termux.com/wiki/Differences_from_Linux)
- アプリのディレクトリとして、 /data/data/com.termux/files/ が起点となり、その下にusr/ や home/ が置かれます。
- それ以外の場所（例えば/etc/ や /var/、/tmp/ といった、普通のLinuxには存在するディレクトリはアプリからのアクセス権限がありませんし、必要ファイルが存在しない場合がほとんどです）
- このような環境で動くパッケージやLinuxコマンドをビルドするには、どうすればよいか、それを解説していきます。

# クロスビルド用のパソコンを用意する
- Termuxで動くパッケージを作るやり方は[Githubで公開](https://github.com/termux/termux-packages)されています。
- ホストOSはx86_64のLinuxがあれば可能です。ARM64のバイナリー作成にはAndroid-sdkを使用します。
- さらに、環境構築を誰でも簡単に行えるようにDockerfileが用意されていますので、Dockerの実行環境さえ用意できればホストPCはWindowsでもMacでも良いことになります。(もちろん LinuxでもOKです)

# とりあえずLinuxにDockerを入れてみる
- Ubuntu18.04LTSにDockerを入れます
 $ sudo apt install docker.io

- TermuxのGitリポジトリをクローンします
 $ git clone https://github.com/termux/termux-packages.git

- Docker build します
 $ cd termux-packeages/scripts/
 $ sudo docker build .

- Docker を実行します。
 $ sudo ./run-docker.sh

# 試しにパッケージを１つ作ってみます。
- Docker の中にも git cloneしたTermuxのリポジトリが現れています
 builder@7e9e46c4b0fa:~/termux-packages$ 

- 試しに bc（コマンドライン電卓、おなじみの多倍長演算ツール）を作ってみます。
 builder@7e9e46c4b0fa:~/termux-packages$ ./build-package.sh bc


- ARM64のバイナリーは、以下の場所に生成されています。
 ~/.termux-build/bc/massage/data/data/com.termux/files/usr/bin/bc
- x86_64のバイナリーも生成されています。
 ~/.termux-build/bc/host-build/bc/bc

- ARM64のパッケージは以下の場所に作成されているようです
 ~/.termux-build/bc/package/data.tar.xz


# Dockerを使わないやり方
- お勧めするわけではありませんが、素のUbuntu Linuxでも
 termux-packages/scripts/setup-ubuntu.sh 

- と
 termux-packages/scripts/setup-android-sdk.sh 
- を実行すれば、クロスビルド環境(Android-sdk)を用意することは可能です。
- パッケージビルドはDockerの中で行うのと同じです。
 ./build-package.sh 作成したいパッケージ名
- Android端末そのものを使用してセルフビルドすることも可能らしいです。（後で調べます）
- Termuxのパッケージに含まれていないLinuxのパッケージを新規にビルドする場合はそれなりにビルドスクリプトを工夫したりビルドがうまくいかない場合の対処を行う必要があります。
- Termuxはchroot (proot) を使用せずに$PREFIX 環境で動かすのでそれに対応したビルドを行う必要があるのと、Androidのlibc(bionic)がglibcと互換性が無いためにソース等に手を入れる必要があるということです。

# なぜTermuxは人気があるのか

- 動作が軽いこと
- ---- chroot(proot)が遅すぎるだけかも、というのはあります。
- ルート権限が要らない
- 必要十分な機能がそろっている
- CUIコンソール向きである
- ストレージやメモリーを圧迫しない


# 参考
- Termux wikiのFAQです。
https://wiki.termux.com/wiki/FAQ
AWSにtestrailを導入してJiraと連携した話

#はじめに
とりあえず手間取ったところもいくつかあったのでメモです。
#awsインスタンス用意
- ubuntu18.04 LTS
- 環境的にはVPC配下になるのでプライベートIPだけ用意
- NATのセキュリティルールインバウンドにssh:22とhttp:80を追加
- ubuntuの初期Userは「ubuntu」、Keyペアを用意してtera termログイン
- awsのインスタンス自体はTokyoリージョンに立てたが、`apt-get update`をするとhttpアクセスで失敗するので`/etc/apt/source.list`の`http://... archive.ubuntu.com`の`...`部分を削除していく編集をした
    - 数行あるので全部。これやらないと`apt-get update`で`Connection timed out`だらけになり、接続できないのでセキュリティルールの設定が間違っているのか？とか結構ハマった。

#環境準備
- mysqlをInstall
    - MariaDBもInstallしたほうが良い？みたいなのがあったけど18.04LTSではInstall出来なかった。ちょっと自分では力不足で断念。
- apache2をInstall
- PHP7.2をInstall
    - testrail5.7系はPHP7.0では動作しないので注意。トライアル時点で結構ハマった。
- testrailのInstallマニュアルにPHPライブラリがいくつか必要、と書いてあるのでそれを参考に`apt-get install PHP7.2-json`みたいな形で入れていく
- ioncubeライブラリが必要なのでDLしてtestrail Installマニュアルに従って設定する
    - apache2とcliのPHP.iniを編集する必要があるので注意（片側だけではダメ）

mysqlとapache2については以下のURLを参照にした（とういうかtestrailのInstallマニュアルに書いてあった）。
https://www.howtoforge.com/tutorial/install-apache-with-php-and-mysql-on-ubuntu-16-04-lamp/

#testrailインストール
特にInstallマニュアルに従っていれば問題なし。
ただし、Install途中にライセンスを求められるのであくまでライセンス発行をしてもらってからInstall開始することをお勧めする。
以下エラーが起きたときにどこを見て解決したのかを箇条書き（トラブルシューティング）。

- `http://xxx.xxx.xxx.xxx/testrail`へ接続したときにエラーが起きた
    - `/var/log/apache2/error.log`にPHPのエラー分が出ているのでエラーが出ているところのPHPファイルを見て何が足りないのかを確認する
    - 大抵はPHPのライブラリがそろっていなかったりが原因なのでライブラリをInstallして再接続してみる。どのPHPライブラリが不足してるかはPHPを見れば記載あり。

#jira連携
Jiraとの連携は以下の手順で実施する。

- testrail側の設定で管理から統合を選択する
- 欠陥と参照それぞれでJira統合の設定をクリック
- Jira統合の設定画面でJiraのアドレスとJiraアカウントのメールアドレスを入れる
- Jiraアカウント側でAPIトークンを発行する
- 発行したAPIトークンをtestrail側に入力してJira統合の有効化をクリック

これで連携は完了。欠陥（バグ）があった場合は欠陥をプッシュというところからJiraのプロジェクトを選択してそこに向けてタスクを送信すればOK。
ちょっと反応が遅いのが気になった（AWSでVPC組んでる影響か…？）
これで脱エクセルにまた一歩近づいた。
SQL Server Agentを有効にしてジョブを実行できる状態にする

# はじめに
SQL Serverで定期的にジョブでSQLを実行したい場合や、レプリケーションを設定する場合、SQL Server Agentの起動が必要です。
初期設定では、SQL Server Agentが起動していないため、起動させる方法をメモします。

AWS EC2にSQL Serverをインストールした環境で確認しました。
- Windows Server 2019
- SQL Server 2017 Standard Edition

# SQL Server Agent 起動
SQL Serverが起動しているサーバーにログインします。
次にSQL Server Configuration Managerを起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324247/2ccded7e-ced6-89f5-c61b-9ffb85123c96.png)

SQL server ServicesにSQL Server Angetがあり、初期状態ではStateが `Stopped` となっています。
こちらをStartさせます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324247/61ca98fb-86aa-0836-8353-a1e81824dc68.png)

Stateが `Running` に変わったことを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324247/f3671762-f350-8837-58df-8b3638a6d140.png)

SQL Server Management Studioでログインしてみると、ジョブが利用できるようになっています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324247/5f522fdd-b750-fdbf-6d4a-197f18491032.png" width=50%>


簡単ですが以上です。
MAMPで複数のローカルホストを設定メモ

# 複数のローカルホストを設定
毎回ディレクトリを設定から変更、選択して行おうこともできますが、
案件が多かったり同時に動いている場合都度設定を変更するのは面倒。

各ディレクトリごとに設定は必要ですが、
一度設定してしてしまえば検証時など楽なのでその設定のメモです。

まず下記ファイルのある箇所を修正します。
`/MAMP/conf/apache/httpd.conf`

```conf:httpd.conf
# Virtual hosts
#Include /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf
```
下記のように修正

```conf:httpd.conf
# Virtual hosts
Include /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf
```

そして下記にあるファイルに動かしたいディレクトリを指定します。
`MAMP/conf/apache/extra/httpd-vhosts.conf`

一番下に下記のように追記します。

```conf:httpd-vhosts.conf
Listen 8001

<VirtualHost *:8001>
    DocumentRoot "userからのディレクトリのパス"
    <Directory "userからのディレクトリのパス">
        AllowOverride All
    </Directory>
</VirtualHost>
```

「Listen 8001」と「VirtualHost *:8001」の値を合わせて増やして行けば、
複数のディレクトリに対してMAMP環境で動かすことができるはすです。

アクセスする際は`http://localhost:8001/`でアクセスできるようになると思います。
固定IPが振られている場合は`固定IP:8001`でもいけると思います。

[こちらの記事を参考にさせていただきました](https://qiita.com/tsukishimaao/items/cab4caa065d901608856)
ありがとうございます。
※ミスなどあれば指摘いただけると幸いです。
React Router 記事本

## React Router ポイント

- 基本メソッド
- 404エラー

## React Routerの基本メソッド（コンポーネント）

- BrowserRouter
- Route
- Link

## 基本

- ルーティングの設定
  - どのパスで、どのコンポーネントを表示するか
- Link
  - パスを指定
 

```javascript

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import { Route, Link, BrowserRouter as Router } from 'react-router-dom'
import App from './App'
import Users from './users'
import Contact from './contact'
const routing = (
  <Router>
    <div>
      <ul>
        <li>
          <Link to="/">Home</Link>
        </li>
        <li>
          <Link to="/users">Users</Link>
        </li>
        <li>
          <Link to="/contact">Contact</Link>
        </li>
      </ul>
      <Route exact path="/" component={App} />
      <Route path="/users" component={Users} />
      <Route path="/contact" component={Contact} />
    </div>
  </Router>
)
ReactDOM.render(routing, document.getElementById('root'))
```

## Switch 

- コンポーネントを完全に切り替える
  - `<Route path="/users/:id" component={Users} />`詳細画面に行く時とか

```javascript

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import { Route, Link, BrowserRouter as Router, Switch } from 'react-router-dom'
import App from './App'
import Users from './users'
import Contact from './contact'
import Notfound from './notfound'
const routing = (
  <Router>
    <div>
      <ul>
        <li>
          <Link to="/">Home</Link>
        </li>
        <li>
          <Link to="/users">Users</Link>
        </li>
        <li>
          <Link to="/contact">Contact</Link>
        </li>
      </ul>
      <Switch>
        <Route exact path="/" component={App} />
        <Route path="/users/:id" component={Users} />
        <Route path="/contact" component={Contact} />
        <Route component={Notfound} />
      </Switch>
    </div>
  </Router>
)
ReactDOM.render(routing, document.getElementById('root'))
```


## パラメーター

- user1,2などをどう実装するか
　- Users（親）　User（子）の構造

```javascript

import React from 'react'
import { Route, Link } from 'react-router-dom'
const User = ({ match }) => <p>{match.params.id}</p>
class Users extends React.Component {
  render() {
    const { url } = this.props.match
    return (
      <div>
        <h1>Users</h1>
        <strong>select a user</strong>
        <ul>
          <li>
            <Link to="/users/1">User 1 </Link>
          </li>
          <li>
            <Link to="/users/2">User 2 </Link>
          </li>
          <li>
            <Link to="/users/3">User 3 </Link>
          </li>
        </ul>
        <Route path="/users/:id" component={User} />
      </div>
    )
  }
}
export default Users

```

## Link, NavLinkの違い

## History Object

履歴



## 記事
https://dev.to/saigowthamr/react-router-beginners-guide-ljb
【OCI】oracle cloud -仮想クラウド・ネットワーク構築編(ネットワーク・セキュリティグループ)-【初心者向け】

# ネットワーク・セキュリティグループ

仮想ファイアウォール
アクセスを許可したり、トラフィックを制御することができます。

## 前回の記事でインターネットゲートウェイを作成しました。

インターネットゲートウェイの作成を見たい方はこちらから
[インターネットゲートウェイ編](https://qiita.com/manaki079/items/b88bb705e42366578649)

## ネットワーク・セキュリティグループの作成
サブネットを作成したいVCNの詳細ページ
左側のリソース→ネットワーク・セキュリティグループをクリック
![instance_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111276/7578b2d5-e2e1-0ffc-7c01-f7b4b3ffabef.png)
ネットワーク・セキュリティグループの作成をクリック
![instance_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111276/85631cfd-d2cc-42b9-55fd-3ff91f0bcd6f.png)

| 項目       | 概要|
|:-----------------|:-----------------|
| 名前             | 任意のセキュリティグループ名を入力します。 |
| コンパートメントに作成           | 作成するコンパートメントが間違っていないか確認|
次をクリック
![instance_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111276/daedfb42-326b-7117-bb20-fb356057a907.png)

| 項目       | 概要|
|:-----------------|:-----------------|
| 方向             | イングレス OR　エグレス(エグレスは基本設定しないかと思います) |
| ソース・タイプ           | 他のセキュリティグループなどを選択することもできます(今回はCIDR)|
| IPプロトコル           | 許可したいプロトコルを選択(今回は仮想マシンへSSHするための22番を指定)|
| ソース・ポート範囲           | 何番ポートからを通すか(基本はALL)|
| 宛先ポート範囲           | 許可するポート範囲を指定|

作成をクリック
![instance_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111276/87873b5c-abfc-03fb-77dc-73a8ba6e254a.png)

これでセキュリティグループの作成は完了
![instance_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111276/6f0a3c20-4347-e184-c531-18ea5f31fe54.png)

## 次回
セキュリティ・リストの修正を行っていきます。

[セキュリティリスト編はこちら](https://qiita.com/manaki079/items/d18c26cc9504d77a577b)