OmniAICreator/Qiita-1.07M huggingface dataset:
AWS Glue で pg8000 driver を使って PostgreSQL の RDS インスタンスに接続する

## Overview

AWS Glue のスクリプトで、DynamicFrameWriter を使ってできることより、もう少し色々細かいことをやりたかったので、PostgreSQL の RDS インスタンスに Python のライブラリで接続したかった。

その手順メモ。

なお、Glue では pure-Python なライブラリしか使えない。例えば pandas のような C library は未サポート。なので pg8000 を使う。

## Procedure

手順

1. pg8000, scramp (依存で必要) の tar ファイルをダウンロード
2. tar を解凍して zip を作る
3. zip を s3 に置く
4. Glue job の設定、Python library path に s3 のパスを入力

詳細は以下

### 1. pg8000, scramp (依存で必要) の tar ファイルをダウンロード

pypi から tar がダウンロードできるのでローカルに落とす。

(pypi > "Download files")

以下直リンク

* [pg8000](https://pypi.org/project/pg8000/#files)
* [scramp](https://pypi.org/project/scramp/#files)

### 2. tar を解凍して zip を作る

落としてきた tar を解凍すると、中にライブラリ本体のソースコードがあるのでそれを抜いて zip にする。

**pg8000**

```
$ tar xzf pg8000-1.16.5.tar.gz --strip-components 1 pg8000-1.16.5/pg8000/
$ zip -r pg8000.zip pg8000
  adding: pg8000/ (stored 0%)
  adding: pg8000/_version.py (deflated 31%)
  adding: pg8000/__init__.py (deflated 58%)
  adding: pg8000/core.py (deflated 76%)
  adding: pg8000/exceptions.py (deflated 77%)
  adding: pg8000/converters.py (deflated 74%)
```

**scramp**

```
$ tar xzf scramp-1.2.0.tar.gz --strip-components 1 scramp-1.2.0/scramp/
$ zip -r scramp.zip scramp
  adding: scramp/ (stored 0%)
  adding: scramp/_version.py (deflated 31%)
  adding: scramp/__init__.py (deflated 41%)
  adding: scramp/core.py (deflated 75%)
  adding: scramp/utils.py (deflated 56%)
```

### 3. zip を s3 に置く

ここでは仮に以下の場所に置いたとする。

* `s3://tommarute/python/lib/pg8000.zip`

* `s3://tommarute/python/lib/scramp.zip`

### 4. Glue job の設定、Python library path に s3 のパスを入力

以下に入力。

![glu-python-lib.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145721/ff73747e-4ade-ee6d-f2cc-af9b2b736ec9.png)


複数あるのでカンマで区切る。

`s3://tommarute/python/lib/pg8000.zip,s3://tommarute/python/lib/scramp.zip`

これで設定は完了

### 使う

後は普通に import して使えばOK

例えばこんな感じ

```python
import pg8000

DSN = {
    'host': 'postgres.xxxx.us-east-1.rds.amazonaws.com',
    'port': 5432,
    'database': 'ec',
    'user': 'tommarute',
    'password': 'secret'
}

table = 'my_contact'

with pg8000.connect(**DSN) as con:
    res = con.run("SELECT count(*) FROM information_schema.tables WHERE table_name = :table", table=table)
    table_count = res[0][0]
    print(f'table_count of {table} = {table_count}')
```

使い方のサンプルは [pg8000 の Github リポジトリ](https://github.com/tlocke/pg8000)に豊富に載っている。

なお、Glue の jupyter notebook で使いたい場合は、Dev endpoints の設定で上記 4 で行った設定をすればいける。

## 参考

* https://stackoverflow.com/questions/47081088/aws-glue-truncate-destination-postgres-table-prior-to-insert
* https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-python-libraries.html
Tableauデータ分析 ~ 入門から実践まで ~ メモ

# What's this?

[Tableauデータ分析 ~ 入門から実践まで ~ ](https://www.shuwasystem.co.jp/book/9784798050263.html) の`第10章 商品分析` を手を動かしながら学習した際のメモ

# はじめに

第10章では、「商品」の視点でどのように分析するかを段階ごとに解説


1. データの把握
2. 全体感の把握
3. データのカスタマイズ
4. トレンドの把握（売上推移編）
5. トレンドの把握（構造把握編）

- 1~3 前処理  
分析結果が良かったとしても、前処理が正しく行われていないと、分析結果自体を疑われかねない。

- 4,5 トレンド把握  
  全体感の把握から細部を深堀りしていく。

# 1. データの把握

## データの粒度
データを一意に特定できるカラムの組み合わせ。
サンプル・データストアであれば `オーダーID x 製品ID x 顧客ID`で一意になりそうだが、DB設計上の問題や、入力のミスによって一意になっていない場合があるので、その粒度で問題ないか必ずチェックを行う。
[Unity]shaderコード備忘録

#はじめに
shader書いてて「あーこれいいなー」とか「たまたま出来た」みたいなやつを忘れないようにするために
随時ここに吐き出していこうと思います．(要はちらうら)

## fragmentシェーダ系
### うねうねスライム
元々は全然違うshaderで円入れたいなーと思って色々やってたらできた副産物(ほんとは円がsin(uv.y)でゆらゆら上昇するのを考えながら作ってた)
![output-palette.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411974/000ed86f-8573-281c-b384-d99e6b7189c6.gif)

```c#

fixed4 frag (v2f i) : SV_Target
            {
                //球の生成
                float r = 0.1;
                float2 pivot = float2(0.5,0.0);
                pivot.x += 0.2*sin(i.uv.y * 10);
                pivot.y += (fmod(_Time.x*3, 1) / 1);
                float dist = distance(i.uv, pivot);
                float isSphere = step(r,dist);

                fixed4 col = float4(1.0,1.0,1.0,1.0) * isSphere + float4(sin(i.uv.x + 0.3), sin(i.uv.x+ _Time.x *200),sin(i.uv.x + _Time.x *100), 1.0) * (1.0 - isSphere);
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
```

とりあえずこれ一個
形態素解析の結果を返すLinebot（python × MeCab × ngrok）

#概要
LINEへの入力内容をpythonのサーバで受けて、MeCabによる形態素解析の結果を応答として返すLinebotを作りました。
以前、[Linebotとpythonプログラムの中継にherokuを使う方法](https://qiita.com/shimajiroxyz/private/5e9bfba87391d9af9756)を書きましたが、今回はngrokを使う方法について書きます。

https://ngrok.com/

Line MessagingAPIの入力を自作サーバで受ける簡単な方法として、ngrokまたはherokuがあります。
ngrokはローカルで立てたポートにトンネルさせることができるため、プログラムの変更をすぐにアプリに反映することができます。一方、herokuは変更を反映させるために都度、デプロイをスル必要がありますが、固定のアドレスを取得することができます。ngrokは起動のたびにアドレスが代わり、本番環境には向きません。
以上から、開発はngrokでおこない、本番はherokuを使うのが効率的と考えられます。

そこで本稿ではngrokでサーバを立てて、LINEの入力を受ける方法を説明します。
#事前準備
[形態素解析の結果を返すLinebot（python × MeCab × heroku）](https://qiita.com/shimajiroxyz/private/5e9bfba87391d9af9756)の「Heroku CLIのインストール」の直前までをやっておきます。ただしデプロイするわけではないので、仮想環境は必ずしも用意しなくても構いません。フォルダ構成は、仮想環境を使わないのであれば、main.pyだけあればよいです。
#ngrokのインストール
macでbrewが使えれば、下記コマンドでインストールできます。

```
brew cask install ngrok
```
ngrok自体はこの時点で使うことができるのですが、会員登録なしだと８時間の利用制限があります。そこで、会員登録をします。

公式ページよりアカウントを作ります。
https://ngrok.com/

アカウントができたら、認証トークンをログイン後のWebページで確認し、ローカルPCで下記を実行します。~/.ngrok2/ngrok.ymlに設定ファイルが書き込まれたというメッセージが表示されたらOKです。

```
$ ngrok authtoken <auth token>
```
#ngrokの実行
main.pyを実行するディレクトリでngrokを起動します。
このあと、表示されるリンクにアクセスすることで、localhost:5000にフォワーディングすることができます。

```
$ ngrok http 5000
```

表示されるリンクとflaskのアクセス先を組み合わせたリンク（例えば https://xxxxx.ngrok.io/callback ）をLinebotのMessagingAPIのアクセス先に設定し、更新します。またローカルで、python main.pyを実行します。

```
$ python main.py
 * Serving Flask app "main" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
```

Linebotで文字を入力し、MeCabの形態素解析の結果が返ってくるか確認してください。形態素解析の結果が返ってくれば成功です。
開発中にプログラムソースを変更した場合は、ngrokは再起動せず、main.pyを再起動するだけでよいです。やむをえずngrokを再起動した場合は、LineDevelopersの設定を更新してください。

#補足：ngrokのサービス化
冒頭で開発はngrok、本番はherokuと書きましたが、herokuは容量が500MBまでなど、制限もあり、ローカルほど自由に環境構築はできないかもしれません（例えば容量の関係で、mecab-ipadic-neologdをherokuの無料枠で使うことは難しいです）。もしherokuにインストールできない機能を使いたい場合には、ngrokを本番環境で使う選択肢もありえます。

ngrokを本番で使うにはsystemdなどを使ってサービス化しておくと便利かと思います。

参考：[ngrokを用いてRaspberryPiを起動したら自動で立ち上がるTCPサーバーにする](https://qiita.com/SonedaYusuke/items/cc97248d3dace909d72f)
PupeteerでWebコンポーネントのテスト

## はじめに

一年ほど前に自分のプロジェクト向けに[Stencil](https://stenciljs.com/)を使って[Webコンポーネント](https://www.webcomponents.org/element/progress-ring-component)を作ったりしていたのですが、その頃はまだそこまでWebコンポーネントが使われている感じではありませんでした。最近ではWebコンポーネントの活用が増えてきていて、実際今入っているプロジェクトで使っている[Amazon Amplify](https://www.npmjs.com/package/@aws-amplify/ui-react)のコンポーネントもWebコンポーネントで実装されています。

今回はWebコンポーネントを含むページのE2Eテストを[Pupeteer](https://pptr.dev/)で実装する際に必要だった知識のメモです。

## PupeteerでShadow DOMにアクセス

Pupeteerのチームも[近年のWebコンポーネントの普及](https://web.dev/web-components-io-2019/)を受けて[Shadow Domのサポート](https://github.com/puppeteer/puppeteer/issues/4171)を検討しているようですが、現段階では特にまだShadow Domにアクセスするための特別な仕組みはないようです。

自分の場合、AmplifyのWebコンポーネント（Submitボタン）をクリックする必要があったのですが
![amplify-web-component.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674308/079ded9c-8dd8-86e0-05f3-66be850cbb2e.png)

Shadow DOMに対して例えば

```typescript
await page.click("button[type='submit']");
```

といった形でアクセスはできず、今回は以下の形で対応しました。

```typescript
const submitButton = (
  await page.evaluateHandle(
    `document.querySelector("amplify-sign-in").shadowRoot.querySelector("amplify-button").shadowRoot.querySelector("button[type='submit']")`
  )
).asElement();

await submitButton.click();
...
```

ただやはりもう少しスマートな形でShadow Dom要素へのアクセスがPupeteerで出来るようになってほしいですね。

## まとめ
今回はPupeteerでWebコンポーネントを含むページのE2Eテストを行った際の備忘録でした。
【Eclipse】補完機能を使いたいけど、スペースで補完を確定してしまうのをなんとかしたい

#現象
使用しているエディタ
Eclipse 4.8.0
macOS Catalina 10.15.6

Eclipseの補完機能を有効にして、トリガーには`.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`
を当てている。

```java
String str =
```
と入力したいのに、strの後に押すspaceキーで補完が確定される。つまり、自分で決める変数名でも意図しない補完が適応されてしまうので、バックスペースで毎回消去しないといけなくなる。いやだ〜

![string.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668402/85499718-a8a4-80b3-1a11-76b3bd634316.gif)


#解決
####自動有効化遅延を500に設定

![設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668402/48964455-f2f5-8a7c-9dae-8963402ede95.png)

環境設定ページはショートカット「⌘,」で開く。
上の画像のように、設定を変更します。

![string_after.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668402/a28c97ac-09ba-8cb2-d407-f02523f5ce70.gif)

補完候補が表示されるまでに遅延があるので、すばやくSpaceキーを押せば大丈夫でした。

新しいバージョンのEclipseではEnterキーだけで確定をするというチェックボックスがあるみたいですが、自分の（Eclipse4.8.0）はなかったです。
ソフトウェアテストの基本

#【ソフトウェアテストの基本】

今後の業務過程で、ソフトウェアテストを行うので予習しました。
もし何かご指摘などありましたら、よろしくお願いいたします。

##ソフトウェアテストの目的

・欠陥やバグを検出する。
・要件を満たしているかの確認
・リリース後の品質リスクを見積もる。

ソフトウェアテストで何を重視するかは目的やニーズによっても変わります。

##・ソフトウェアテストの基本、この２つ。

・同値クラステスト
・境界値テスト

##同値クラステスト

同値とは、同じ動作をする条件の集まりを指す。
同じ処理結果となる入力値、時間、出力結果の集まりなど。

上記の条件の集まりを同値クラスとして、クラスごとにテストをする。
代表値を選んでテストをし、それらがすべて正しいと証明されたら、そのクラスの他の値もすべて正しいと判断できる。

ただし１００％絶対ではない。

###・同値クラステストをする理由

ソフトウェアテストをする時の大原則として、すべての値をテストすることは不可能。
入力値や条件によって処理方法が決まるが、その数は膨大になるため、すべての条件を一つひとつテストすることはできないから、同値クラスという概念が重要とされる。

###・同値クラステストで、なぜ正しいと判断ができるのか。

代表値でテストをした結果、欠陥が見つかれば、同値クラス内の他の値でも同じ欠陥が見つかる。
その逆で、欠陥が見つからなければ、同値クラス内の他の値でも同じ欠陥は見つからないだろうと考える。

このテスト技法は、テスト効率化の1つの方法であると納得する必要がある。

###・補足

プログラムの仕様、プログラムコードの構造が異なれば、同値クラステストは適用不可である。


##境界値テスト

異なる同値クラスが隣り合っている部分が境界となるので、境界値とする。

仕様条件の境界となる値とその隣の値に対してテストする。
境界値に着目する理由は欠陥は境界に潜んでいる可能性が高いからである。

符号、不等号の誤りやタイプミスなどがよくある。
※そもそも、これらはテスト前のレビューで発見することを意識しておく。

###・境界値テストになぜ着目するのか。

ソフトウェアには「隠れた境界値」が存在することがある。
（仕様からは読み取ることができないソフトウェアの内部構造にある境界値）

暖味な仕様表現から境界値には個人の解釈の誤りが生まれやすい。
仕様の思い込みによる誤った解釈でコーディングが進み、欠陥が作り込まれることがある。

例）~より大きい(小さい)、~より多い(少ない)、~を超える　など。文書だけの冗長な表現。
※暖味な仕様表現はマトリクスや数直線等で図表化して確認することが望ましい。

###・境界値テストの手順

①境界値を見つける。
　動作の変わり目等、仕様条件の境界値を見つける。

②境界値を決める。
　境界と隣り合う条件や値を境界値とする。

③テストする値を決める。
　境界値、境界値の1つ下、境界値の1つ上を決める。

###・その他

SIerなどの受託系の会社をはじめ、急な仕様変更や仕様追加などで時間を取られてしまい、すべてのコードを見直すことなく対応をしてしまうことは多々あるそうだ。。
隠れた境界値は、仕様から読み取れないので、テストされず、後になり欠陥を引き起こす可能性がある。

※特に仕様変更が頻繁に発生した場合など、変更内容をコードに反映する際に作りこまれてしまうことが多い。

##最後に。

ソフトウェアのテストは地味で決して楽しいものではないかもしれないけど、大事なことなので今後の業務内でも理解を深めていきたい。
【Rails6】初学者向け！Ruby on Railsで簡単に音声ファイルの再生とダウンロードをする方法

音声ファイルの投稿〜再生・ダウンロードまでを実装します。

##今回のゴール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538670/54beb4cf-236a-217b-4ad1-37a7779938a1.png)


#手順

##Step0 事前準備
## アプリケーションの作成

すでにアプリケーション作成途中の場合、飛ばしていただいて大丈夫です。

```
$ rails g scaffold tweet body:text
$ rails db:migrate
```

scaffoldの説明は省きますが、つまりこれで

* tweets controller 
* tweet model
* tweets table / bodyカラム 
* tweets controller 全てのアクションのrouting

が一気に作成することができました。

##Step1 カラムの追加
```:ターミナル
$ rails generate migration AddFileToTweets file:string
```

```:ターミナル
$ rails db:migrate
```

### StrongParameterの修正
```ruby:tweets_controller.rb
# 割愛

private

def tweet_params
  params.require(:tweet).permit(:body,:file) <- ここの:fileを付け加えてください！
end
```
##Step2 音声ファイルの投稿機能

### gemの追加
```ruby:Gemfile
gem 'carrierwave'
```
```:ターミナル
$ bundle install
```

### アップローダーの作成
```:ターミナル
$ rails generate uploader Audiofile
```

### Modelの修正
```ruby:app/models/tweet.rb
class Tweet < ApplicationRecord
# ここから追記
  mount_uploader :file, AudiofileUploader
# ここまで追記
end
```

### Viewの修正

```erb:new.html.erb
<%= form_for @tweet do |f| %>
　#省略
　#追記はここから
  <%= f.label :file %>
  <%= f.file_field :file , :size => 140 %>
　#追記はここまで
　#省略
  <%= f.submit "送信" %>
<% end %>
```

##Step3 音声ファイルの再生機能とダウンロード機能

### gemの追加
```ruby:Gemfile
gem 'audiojs-rails'
```
```:ターミナル
$ bundle install
```

### audiojsの読み込み
```:app/javascript/packs/application.js
#省略
#以下追記
//= require audiojs
```

### Viewの修正

```erb:index.html.erb
  <% @tweets.each do |t| %>
    <div class="tweet">
      <%= t.body %>
      #ここから追記
　　　　<audio src= "<%= "#{t.file}" %>" controls="">
         <a src="<%= "#{t.file}" %>">ダウンロード</a>
       </audio>
　　　 #ここまで追記
    </div>
  <% end %>
```

これで完成です。
スケッチブックの場所をGoogle Driveにしてvideoライブラリを使うとエラーが出る

# 起こった事象
processing.videoライブラリを使って動画を再生しようとするとgio-2.0というライブラリがロードできない旨の以下のようなエラーメッセージが出てしまいました。
> UnsatisfiedLinkError: can't load library gio-2.0 (gio-2.0|libgio-2.0|libgio-2.0-0) with -Djna.
# 環境
Windows10
processing-3.5.4
# 対応
スケッチブックの場所をGoogle Drive上に設定していたことが原因らしいです。
[コミュニティ](https://discourse.processing.org/t/video-library-fail-on-win10/14465)でもQAがやりとりされてました。
「スケッチブックの場所」はProcessingメニューバーのファイル>設定から確認できます。
これをローカルのフォルダに変えてあげれば問題なく動作してくれます（ローカルのフォルダにはLibraries/videoライブラリが配置されてること）。
コミュニティによると64bit環境で32bit版を動かすと類似のエラーが出るっぽいけどそこは未確認。
## 検証
スケッチブックそのもの（pde含むスケッチブックフォルダ）はGoogle Drive上に配置し、設定上の「スケッチブックの場所」だけローカルにしておくことは可能でした。問題なく動作してくれます。
ただしこれもローカル側にLibrariesフォルダ（とVideoライブラリファイル）を配置しとく必要があります。
【RPi4】テザリングと家のWiFiの両方でsshで入れるようにする

これは出先でスマホのテザリング経由でRasPiとノートＰＣを接続し、かつ、普段の自宅では自宅のWiFiで
接続するために行った設定のメモです。

ハマりポイントとして、

- 単純にwpa_supplicant.conf に設定を追加するだけではダメ
- 追加した設定がＤＨＣＰでＩＰアドレスを取得するという設定も別に追加したら動いた

これは、この記事の内容を薄くしたものなのですが、今後追加事項があれば書いていきたいと思います。

[raspberry Pi3に複数のwifiへ自動接続してもらう](
https://www.kameneko.com/raspberrypi3-wifi-wpasupplicant/)

## 事前の設定作業

### /etc/wpa_supplicant/wpa_supplicant.conf

アクセスポイントの設定を書きます。SSIDとパスワードを書きます。priority で優先順位を設定します。家のWiFIのnetwork={...} が既にあると思いますが、それにテザリング用のものを追加します。

```
network={
    ssid="MySmartPhone"
    psk="1abc2def3gh"
    key_mgmt=WPA-PSK
    proto=RSN
    priority=0
    id_str="huaweip10"
}
```

ここでid_str で識別子を書いておきます。これは後で参照するので大事です。

また、パスワードは暗号化して書くこともできます。```wpa_passphrase```というコマンドが用意されています。
SSIDが ssid100、パスワードが password20 の場合、

```
$ wpa_passphrase ssid100 password20
network={
        ssid="ssid100"
        #psk="password20"
        psk=6e3e248b15adb827f0aa36c2c0cd501740c1b2f67dee01bbd8a1cf00e8c5f0cc
}
```

という出力が得られてます。psk=の行をコピーし、これまでの、psk="..." の行を削除します。
ここでdouble quatation、""を付けてはダメです。（コピペが一番）


### /etc/network/interfaces.d/wlan.conf


ここでは、どうやら各アクセスポイントに接続したときのＩＰの取り方を設定するようです。
固定ＩＰではないので、先ほどのid_str で設定した識別子がDHCPであると書きます。

```
auto lo
iface lo inet loopback
iface eth0 inet manual
auto wlan0
allow-hotplug wlan0
iface wlan0 inet manual
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf


iface huaweip10 inet dhcp
iface myroomwifi inet dhcp
iface home inet dhcp
```

## 使用例

旅行先のホテルでも無事に接続することができました。

私はHuawei P10　というスマホでテザリングしていますが、データ通信を切ってWiFiアクセスポイントとしてのみ使用しましたが、RasPiとノートＰＣをつなげることができました。

しかし、そのあとトラブルが。ホテルのWiFi接続の設定を追加してRasPi君を再起動したのですが、その後に度と接続できませんでした。
原因は分かりませんが、これに対する対応を考えます。

(2020/09/21)
GASでアプリを作ったら驚くほど英単語が覚えられるようになった話①

１年くらい前、「アメリカのYahooニュースの記事で使われている単語が全て分かるようになりたい」と思い立った私がやったのは、「昔ながらの銀のワッカのついた単語帳を作ること」。ただ、これが電車の中で使うには大人の男の手には小さすぎるし、鞄の中で行方不明になるし、なんとも収まりが悪い。それにワッカを開いて細長いカードをシャッフルしたりするのがとても面倒臭い。とにかく不便極まりなかったのです。中高生の頃は当然のようにやっていたのですが、人間横着になるものですね。。。

で、ちょうどプログラミングをかじり始めていた私は、よく記事を読んでいたDAIさんのノート https://dividable.net/ を見てスクレイピングをやってみたり、彼の本「独学プログラマーのためのAIアプリ開発がわかる本」を読んでLINEアプリを作っていたこともあって、「それならばLINEで自分用にアプリを作ればいいじゃないか」と思いついて、早速作り始めたわけです。

「①自分用にカスタマイズした単語だけが②ランダムに③決まった時間に④自動的に出題されてくる」アプリを作ることを目標に掲げ、早速作り始めました。使ったのは「独学プログラマーの〜」で使い慣れていたGoogleAppScript。悪戦苦闘すること２週間くらいで完成。

こんな感じでスプレッドシートに英単語と日本語訳を入力しておくと、、、
![F337AB73-3AC1-4111-944A-D53930654C60.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634245/e99be8ef-bfe8-d420-f210-5206c7138101.png)

毎日決まった時間（私の場合は２時間おき）に下記のようにLINEに（英語もしくは日本語の）問題が送信されてきて、"Check Answer!"のボタンを押すと答えが見れるという代物です。
![31D940B1-5317-4925-B7BC-4EE1025C1DDE.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634245/3abb9294-6724-dadf-ba05-d10ed80d2c92.png)

送信時間を設定済みなので（この英単語アプリの場合は２時間に１回、５問ずつ送信）仕事が忙しくても強制的に勉強するようになるし、スマホなら片手で操作できるし、LINEの画面から気になった単語をサクサク登録できて、自分で驚くくらい勉強の効率が上がりました。プログラミングすげえ、と心の底から思った次第です。

記事が長くなってきたので次回コードを貼り付けようと思います。
良書「ゼロから作るDeep Learning 」のGitHub

#目的

「ゼロから作るDeep Learning -- Pythonで学ぶディープラーニングの理論と実装」
（2017年7月28日　初版第10刷発行, 発行所　株式会社オライリー・ジャパン）

この書籍は、かなりいい書籍だと思います。
というような記事を1年以上前に書いた。

今回、
**なんとなく、Deep Learningを、いろんなフレームワークを使わずに、動かしてみたい**と、ネットを検索していて、
結局、
この書籍が提供するコードにたどりついた。
しかも、今時のために、GitHubで公開されていた。

#GitHub
GitHubで公開されているので、
昔の書籍のおまけのコードで、微妙に、秘密のコードでなくて、、、、
完全に公開されていると思うので、**ご紹介**。

以下です。
<https://github.com/oreilly-japan/deep-learning-from-scratch>

#動かしてみた
プロなので、ちょっと、トラブりましたが、ch08を5分で動かしました。
トラブルの内容は、↓。
[「ゼロから作るDeep Learning 」でModuleNotFoundError: No module named 'dataset.mnist'が出る理由。](https://qiita.com/enoughspacefor/items/af6aca4f885859c968fa)

（その他、詳細後報。）

#まとめ
特にありません。
書籍が横にないと使いにくい場合は、ごめんさなさい。たぶん、トータルとしては、そんなことないと思います。
Ruby on Rails バリデーションまとめ

#はじめに

主にRails Tutorialの備忘録として、例などをまとめてみます。
間違い等ありましたらご指摘いただけますと幸いです。

#バリデーションとは
オブジェクトをデータベースに保存する前に、オブジェクトの状態を検証することです。
入力された値が無効ではないことを検証します。
例えば、空のデータが保存されないようにしたり、文字数に制限を儲けたりすることができます。

#基本的な書き方
基本的な記入方法は以下です。

```ruby:model
validates :カラム名, ヘルパー

#複数のカラムに適用したい場合
validates :カラム名, :カラム名, :カラム名, ヘルパー
```

#主なバリデーションのヘルパー

###presence
指定された属性が空でないことを確認します。

```ruby:model
validates カラム名, presence: true
```

```ruby:model
validates :name, presence: true

#複数のカラムに適用したい場合
validates :name, :login, :email, presence: true
```

###length
属性の値の長さを検証します。多くのオプションがあり、さまざまな長さ制限を指定できます。

```ruby:model
validates カラム名, length: { 制限 }
```

```ruby:model
  validates :passward, length: { minimum: 5 }        #5文字以上
  validates :name, length: { maximum: 50 }           #20文字以下
  validates :passward, length: { in: 3..10  }        #3文字以上10文字以下
  validates :registration_number, length: { is: 6 }  #6文字のみ許可
```

###uniqueness
属性の値が一意（unique）であり重複していないことを検証します。

```ruby:model
validates :カラム名, uniqueness: true
```

```ruby:model
validates :name, uniqueness: true
```

###acceptance
フォームが送信された時に、チェックボックスがオンになっているかどうかを検証します。
「サービスの利用規約に同意する」にチェックする必要がある場合などに利用されます。

```ruby:model
validates :カラム名, acceptance: true
```

```ruby:model
validates :terms_of_service, acceptance: true
```

###confirmation
複数のフォームで入力された値が完全に一致するかどうかを検証します。
メールアドレスと確認用メールアドレスの値の一致などに利用されます。

```ruby:model
validates :カラム名, confirmation: true
```

```ruby:model
validates :email, confirmation: true
```

###numericality
属性に数値のみが使われていることを検証します。

```ruby:model
validates カラム名, numericality: true
```

```ruby:model
validates :points, numericality: true
```

```ruby:model
#整数のみ許可
validates :age, numericality: { only_integer: true }
```

#####主なオプション

| オプション |概要 |
|:-:|:-:|
| :only_integer  | 整数でなけえればならない  |
| :equal_to  | 指定された値と等しくなければならない  |


###format
withオプションで与えられた正規表現と属性の値がマッチするかどうかのテストによる検証を行います。

```ruby:model
validates :カラム名, format: { with: 制限 }
```

```ruby:model
#英数字のみ許可
validates :password, format: { with: /\A[a-zA-Z]+\z/ } 

#有効なメールアドレスのみ許可
 VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
 validates :email, format: { with: VALID_EMAIL_REGEX }
```

上記のような、有効なメールアドレスのみ許可するための正規表現は以下のような表に基づいています。

| 正規表現 | 概要 |
|:---:|:-:|
| z\d\-.]+\.[a-z]+\z/i  | 完全な正規表現  |
| /  | 正規表現の開始を示す  |
| \A  |  文字列の先頭 |
| [\w+\-.]+  | 英数字、アンダースコア（_）、プラス（+）、ハイフン（-）、ドット（.）のいずれかを少なくとも1文字以上繰り返す  |
| @  | アットマーク  |
| [a-z\d\-.]+  | 英小文字、数字、ハイフン、ドットのいずれかを少なくとも1文字以上繰り返す  |
| \.  | ドット  |
|  [a-z]+ | 英小文字を少なくとも1文字以上繰り返す  |
| \z  | 文字列の末尾  |
|  / | 正規表現の終わりを示す  |
|  i | 大文字小文字を無視するオプション  |

##共通のオプション

| 1 | 2 |
|:-:|:-:|
|:message   |  バリデーション失敗時に表示されるエラーメッセージを指定できます。指定しない場合、デフォルトのメッセージが表示されます。|
|:allow_nill   | 対象の値がnilの場合にバリデーションをスキップします。 |
| :allow_blank  |属性の値がblank?に該当する場合（nilや空文字など）にバリデーションがパスします。   |

```ruby:model
# メッセージを直書きする場合
validates カラム名, presence: { message: “カスタムエラーメッセージ” } 
```

```ruby:model
validates :name, presence: { message: “必須項目です” }
```


##参考
Active Record バリデーション - Railsガイド v6\.0
https://railsguides.jp/active_record_validations.html
qemuでriscv fedoraを立ち上げる


公式wiki ( https://fedoraproject.org/wiki/Architectures/RISC-V/Installing )の通りにやるだけだがメモ。
# ホスト環境
OpenSUSE Tumbleweed (x86_64)

# 手順
## イメージのダウンロード
上のwikiには手動でディスクイメージを作成する方法も載っているが、検証済みのイメージがあるのでそれをダウンロードする(現時点での最新版はfedora32/v5.5-rc5):

```bash
$ wget https://dl.fedoraproject.org/pub/alt/risc-v/repo/virt-builder-images/images/Fedora-Minimal-Rawhide-20200108.n.0-sda.raw.xz # ディスクイメージ
$ wget https://dl.fedoraproject.org/pub/alt/risc-v/repo/virt-builder-images/images/Fedora-Minimal-Rawhide-20200108.n.0-fw_payload-uboot-qemu-virt-smode.elf # firmware
$ xz -dv Fedora-Minimal-Rawhide-20200108.n.0-sda.raw.xz # 展開
```

## qemuのビルド
ディストリビューションのqemuで良いと思われるが簡単なのでqemuはビルドする:

```bash
$ git clone https://github.com/qemu/qemu
$ cd qemu
$ git checkout -b build v5.1.0-rc3
$ mkdir build && cd build
$ ../configure --target-list=riscv64-softmmu --disable-docs
$ make -j4
```

## 起動
wikiの通りに以下のようなスクリプトを使用する:

```bash
  QEMU_RISCV64=/path/to/qemu/build/riscv64-softmmu/qemu-system-riscv64

  $QEMU_RISCV64 \
   -nographic \
   -machine virt \
   -smp 2 \
   -m 4G \
   -kernel Fedora-Minimal-Rawhide-20200108.n.0-fw_payload-uboot-qemu-virt-smode.elf     \
   -object rng-random,filename=/dev/urandom,id=rng0 \
   -device virtio-rng-device,rng=rng0 \
   -device virtio-blk-device,drive=hd0 \
   -drive file=Fedora-Minimal-Rawhide-20200108.n.0-sda.raw,format=raw,id=hd0 \
   -device virtio-net-device,netdev=usernet \
   -netdev user,id=usernet,hostfwd=tcp::10000-:22
```

起動するとログインコンソールが出る直前にユーザー名/パスワードが表示される (riscv/fedora_rocks!)。

~~**コメント**: -kernelオプションにファームウェアを指定しているので、ここからlinux kernelを置き換えるのが面倒そう。~~

## (追記) kernel入れ替え
QEMUの中にfimwareが組み込まれているようで、以下のオプションでQEMUにkernelを与えて起動することができた:

```bash
 $QEMU_RISCV64 \
   -nographic \
   -machine virt \
   -smp 2 \
   -m 4G \
   -bios default \
   -kernel /path/to/linux/arch/riscv/boot/Image \
   -append "root=/dev/vda4 ro console=ttyS0 earlycon" \
   -object rng-random,filename=/dev/urandom,id=rng0 \
   -device virtio-rng-device,rng=rng0 \
   -device virtio-blk-device,drive=hd0 \
   -drive file=Fedora-Minimal-Rawhide-20200108.n.0-sda.raw,format=raw,id=hd0 \
   -device virtio-net-device,netdev=usernet \
   -netdev user,id=usernet,hostfwd=tcp::10000-:22
```
C++を使ってRubyのメソッドを書く(その2) ベンチマーク

###目次
[C++を使ってRubyのメソッドを書く(その1)](https://qiita.com/ki073/items/b35e1e0ecc4862ea3c14)
C++を使ってRubyのメソッドを書く(その2) ベンチマーク <- ここ

###ベンチマーク
配列の合計を計算する単純なプログラムです。上記のその1で書いた方法(1)と
[Cを使ってRubyのメソッドを書く(その2)Numo::NArray](https://qiita.com/ki073/items/a9a06ed5f505e763893b) (2)の速度を比較してみました。
他にも、 Numo::SFloat型のデータを渡した場合(3) (Numo::DFloatにキャスト後計算)、
NArrayをArrayに変換してから(1)と同じ方法(4)、
ArrayをNumo::DFloatに変換してから(2)と同じ方法(5)、
Rubyの組込み関数Array#sumを使う方法(6)、
Rubyの組込み関数Array#injectを使う方法(7)、
Numo::DFloatの関数sumを使う方法(8)
の速度を比較しています。

結果は最後に書いています。

その1の方法(1)でも十分な速度がありますが、(2)が最高速でした。(6)のArray#sumがかなり速く、バイナリで書かれたRubyの関数は速度で期待できそうです。Numo::DFloat#sumが意外と遅いのとArrayからNumo::DFloatへの変換も遅めのような気がします。

###使用したプログラム

```c++:test.cpp
#include "test.hpp"

double sum(const std::vector<double>& ary){
    double sum=0.0;
    for (int i=0; i<ary.size(); i++){
        sum+=ary[i];
    }
    return(sum);
}

double sum_nd(int n, double *ary){
    double sum=0.0;
    for (int i=0; i<n; i++){
        sum+=ary[i];
    }
    return(sum);
}
```

```c++:test.hpp
#include <vector>
double sum(const std::vector<double>& ary);
double sum_nd(int n, double *ary);
```

```test.i
%module testF
%{
#include "numo/narray.h"
#include "test.hpp"
%}

%include <std_vector.i>
%template(DoubleVector) std::vector<double>;
extern double sum(std::vector<double> ary);

%typemap(in) (int LENGTH, double *NARRAY_in){
  narray_t *nary;
  if (rb_obj_class($input)!=numo_cDFloat){
      $input = rb_funcall(numo_cDFloat, rb_intern("cast"), 1, $input);
  }
  GetNArray($input, nary);
  if (NA_TYPE(nary)==NARRAY_VIEW_T){
    $input = rb_funcall($input, rb_intern("dup"), 0);
    GetNArray($input, nary);
  }
  $2 = ($2_ltype)na_get_pointer_for_read($input);
  $1 = NA_SIZE(nary);
}
extern double sum_nd(int LENGTH, double *NARRAY_in);
```

```ruby:extconf.rb
require 'mkmf'
dir_config("numo/narray")
have_header("numo/narray.h")
create_makefile("testF")
```

```
swig -c++ -ruby test.i
ruby extconf.rb  -- --with-numo/narray-include=/opt/lib/ruby/gems/2.6.0/gems/numo-narray-0.9.1.8/lib/numo/
make
```

ベンチマーク用プログラム

```Ruby:benchmark.rb
require "benchmark"
require "numo/narray"
require "./testF"

data=[*1..100].map(&:to_f)
data_na=Numo::DFloat.cast(data)
data_naf=Numo::SFloat.cast(data)

puts Benchmark::CAPTION
puts Benchmark.measure{
	1000000.times{
		TestF::sum(data) # (1)
	}
}
=begin
以下
TestF::sum_nd(data_na)   # (2)
TestF::sum_nd(data_naf)  # (3)
TestF::sum(data_na.to_a) # (4)
TestF::sum_nd(Numo::DFloat.cast(data)) # (5)
data.sum                 # (6)
data.inject(:+)          # (7)
data_na.sum              # (8)
=end
```

###結果

|  |データの流れ|実行時間 (μs)|
|:-----------|:-----------|------------:|
|(1)|Array => vector<double>| 2.44|
|(2)|Numo::DFloat => double []| 0.14|
|(3)|Numo::SFloat => cast -> double []| 1.59|
|(4)|Numo::DFloat -> Array => vector<double>| 4.77|
|(5)|Array -> Numo::DFloat => double []|10.11|
|(6)|Array#sum| 0.60|
|(7)|Array#inject(:+)| 3.42|
|(8)|Numo::DFloat#sum| 1.30|

(実行時間はループ一回分に換算しています)
PHP7の設定ファイルphp.iniの保管場所の探し方

PHPの設定を変更したかったのですが、とあるPHPの教科書（PHP7対応版）の書いてある通りやってもできずに時間をロスしてしまいました。今度そんなことがにないようにメモをしておきます！

その教科書には、`アプリケーション→MAMP→conf→PHP7.x.x→php.ini`を変更せよと書いてありますが、これは必ずしも正しくありません。少なくとも私の場合は上手くいきませんでした。
自分が使っているPHPがどのphp.iniを読み込んでいるかは、phpファイルの中に下記コードを書き込んでブラウザで読み込むと、インフォメーションが開いて確認できます。

```php:index.php
<?php
phpinfo();
exit();//←こちらはお好みで
?>
```

開いたら、下記スクショのようにLoaded Configuration File確認できます。
![スクリーンショット 2020-08-11 16.49.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645077/40e2c995-7ccc-c519-80bf-81711334f506.png)

なので私の場合は`/Applications/MAMP/bin/php7.x.x/conf/php.ini`ファイルを修正すれば良いということがわかります。

その教科書もディレクトリの場所をそのまま載せるのではなく、このようにどうやって設定ファイルの格納場所を調べればいいか教えてくれた方が良かったかもしれませんね。（って偉そうにすみません...）

もしご指摘あれば遠慮なくお願いします。
Raspberry pi zero wで外付けWiFiアダプタを使用しアクセスポイント化する

Raspberry pi zero Wで内蔵のWiFiを使わずに、WiFiドングルを使用し、通信距離を伸ばそうと試みた時に苦戦したのでメモ

WiFiアダプタは、TP-link TL-WN823Nを使用した。

TL-WN823NをUSB接続し、内蔵WiFiでネットに接続し、以下のコマンドを実行する

#TL-WN823Nを使えるようにする

```
sudo wget http://downloads.fars-robotics.net/wifi-drivers/install-wifi -O /usr/bin/install-wifi
sudo chmod +x /usr/bin/install-wifi
sudo install-wifi
```

これでwlan1が追加されているはず。
###ちなみに、BuffaloのWI-U2-433DHPもこれでいけた。
###今まで、https://github.com/diederikdehaas/rtl8812AU/tree/driver-4.3.20 からダウンロードして、Makefileをどうにかこうにかしてもダメだったのに、今回ものの数分、三行のコマンドで済んでしまった......
###WI-U2-433DHPの方が通信速度や通信距離は優れていた。


気を取り直して......
##内蔵WiFiをOFFにする

```
sudo nano /etc/modprobe.d/raspi-blacklist.conf
```

```/etc/modprobe.d/raspi-blacklist.conf
blacklist brcmfmac
blacklist brcmutil
EOF
```

```
sudo reboot

```

以上を入力し、内臓のWiFiをOFFにする。

再起動後にip link showコマンドでwlan0のMACアドレスがb8:27:ebでなくなっていたら、WiFiアダプタに切り替わっている。

##アクセスポイント化
[この方の記事を参考にさせていただきました](https://qiita.com/wannabe/items/a66c4549e4a11491f9d5 "")


```
sudo systemctl stop dnsmasq
sudo systemctl stop hostapd
```

```
sudo nano /etc/dhcpcd.conf
```

```etc/dhcpcd.conf
interface wlan0
static ip_address=192.168.100.1/24
```


```
sudo service dhcpcd restart
```

```
sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.old
sudo nano /etc/dnsmasq.conf
```

```/etc/dnsmasq.conf
interface=wlan0
dhcp-range=192.168.100.2,192.168.100.40,255.255.255.0,24h
```

```
sudo nano /etc/hostapd/hostapd.conf
```

```/etc/hostapd/hostapd.conf
interface=wlan0
driver=nl80211
ssid=YOUR_SSID
hw_mode=g
channel=6
wmm_enabled=0
macaddr_acl=0
auth_algs=1
wpa=2
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
wpa_passphrase=YOUR_PASSWORD
```

```
sudo nano /etc/default/hostapd
```

```/etc/default/hostapd
# Defaults for hostapd initscript
#
# See /usr/share/doc/hostapd/README.Debian for information about alternative
# methods of managing hostapd.
#
# Uncomment and set DAEMON_CONF to the absolute path of a hostapd configuration
# file and hostapd will be started during system boot. An example configuration
# file can be found at /usr/share/doc/hostapd/examples/hostapd.conf.gz

#DAEMON_CONF=""
DAEMON_CONF="/etc/hostapd/hostapd.conf
```
**DAEMON_CONF="/etc/hostapd/hostapd.conf" ←追加**

```
sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo systemctl start hostapd
sudo systemctl start dnsmasq
```

```
sudo nano /etc/sysctl.conf
```


```/etc/sysctl.conf
net.ipv4.ip_forward=1
```
**net.ipv4.ip_forward=1　コメント外す**

```
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
```

最後にrebootすると、アクセスポイント化が完了しています。

お疲れさまでした。
【iOS】プロビジョニングプロファイル更新手順

<!--
・参考
https://qiita.com/siglab/items/c3f8560fbafd44ad7633
-->

##前書き
プロビジョニングプロファイルの有効期限（1年）が過ぎた場合は更新が必要になるので、更新手順のメモ書き🖋


## 証明書のダウンロード（すでに証明書をキーチェーンに登録している場合は不要な手順）
下記の記事の**「④ 証明書（Certificate）の作成」**手順通りに証明書を作成して登録しておく
https://qiita.com/Labi/items/3b71b8f5ef065904c1de


## プロビジョニングプロファイルの更新
1. Apple Developer Program へアクセス
https://developer.apple.com/jp/programs/

2. **Certificates, Identifiers & Profiles** を選択
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676215/baa0c588-b889-bd50-df7a-9aa89c08870a.png)

3. **Profiles**から、更新するアプリを選択して**Edit**を押下
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676215/a3983856-fc23-0369-16e5-cdf4b58d96fd.png)

4. **Edit**を押下
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676215/2a78ffbc-a104-8ef3-6fed-0f935fa931d9.png)

5. Certificatesから証明書を選択して、**Save**を押下
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676215/88494f2b-59c5-ecec-be42-2b691068e2ba.png)

6. Downloadを押下して、プロビジョニングプロファイルをダウンロード
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676215/e6b991e7-1a71-b0f4-34bf-967b9ba33bd1.png)

7. ダウンロードしたプロビジョニングプロファイルをダブルクリックして、Xcodeに登録


以上
Chromeで回転させる拡張機能作ってみた

# はじめに
動画を見ていて横向きの動画を縦長に表示された経験はありませんか？例えばこんな感じです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678160/aa80ae6c-feb8-9e2f-044f-348f5b549ab4.png" width="400">
こんな感じで（上の画像はあたりさわりのない画像をとってきてるので縦横もくそもありませんが…）横に黒い空白ができてうざいという悩みを解決する機能を、拡張機能として実装していきます。

# やること
筆者はGoogle Chromeを使っているのでChrome用の拡張機能を作っていきます。ちなみにブラウザはChromeがおススメです。なぜなら拡張機能を入れるのがすごく簡単だからです（後述）。

概要としてはctrl+矢印キーで操作をしたいと思います。右を押したら右回りに90度回転、左を押したら左に90度回転した状態になるようにする、そして上を押したら回転を戻すように書いていきます。

# 設定
まずはjsonファイルを書いていきます。これは拡張機能の全般的な設定をするところです。
名前やバージョン、実行の仕方及びファイルを書いていきます。ここでは自分用にローカルで実行するだけなので、最低限書くべきものを書きます。

```json:manifest.json

{
    "manifest_version": 2,
    "name": "rotate",
    "version": "1.0",
    
    "browser_action": {
        "default_title": "rotate"
    },
    "content_scripts": [
        {
          "matches": ["http://*/*", "https://*/*"],
          "css": ["rotate.css"],
          "js": ["rotate.js"]
        }
    ]
}
```
"content_scripts"というところにファイルを記述すると、ウェブページのhtmlに対して操作を行うcss,jsファイルを指定できます。ページはすべてのページに対して行うように設定しています。

# CSS
CSSでは回転したときに指定するクラスを書いていきます。回転角は右回りで指定します。

```css:rotate.css

.rotate-right{
	transform: rotate(90deg);
}

.rotate-left{
	transform: rotate(270deg);
}

```

# JavaScript
JSではキーが押されたときにCSSで設定したクラスを付与するようにします。キーの同時押しを認識しなければなりませんが、ctrlキーに関してはevent.ctrlKeyでT/Fが返ってくるのでそれを使います。

```javascript:rotate.js

var video = document.querySelector('video');

document.addEventListener('keydown', function(event) {
	if (event.ctrlKey){
		if (event.keyCode == 37){ //左
			video.classList.add("rotate-left")
			video.classList.remove("rotate-right")
		} else if (event.keyCode == 39){ //右
			video.classList.add("rotate-right")
			video.classList.remove("rotate-left")
		} else if (event.keyCode == 38){ //上
			video.classList.remove("rotate-left")
			video.classList.remove("rotate-right")
		}
	}
});

```
丁寧に書くならremoveの前にcontainsで有無を確かめるべきかもしれませんが、これで動くので十分でしょう。

# Chromeの設定

まずは右上の拡張機能のアイコン（？）を押して一番下の拡張機能を管理を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678160/03e7f9d4-44d7-a6c3-125a-a2ec96893309.png)

次に右上のデベロッパーモードを有効にしてパッケージ化していない拡張機能を読み込むを押します。するとフォルダを選択できるので、manifest.jsonがあるフォルダを指定すると読み込まれます。簡単でしょ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678160/6fc7448d-48b4-ef83-da13-83758219d16a.png)

拡張機能を更新したときはこのページで読み込みボタンを押してページをリロードすれば適用されます。

表示はこのようになりました。大きさについては複数のページに対応させたい関係上指定していませんし、回転中心も中心のままなので周囲に枠ができちゃっていますが、許容範囲でしょう。もしこのページだけに使いたいみたいなことであれば、ピッタリになるように設定してもよさそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678160/b9e2ba3d-981f-b921-7a79-affbbb37fabf.png)

# 参考文献
- [Chromeブラウザの拡張機能を作ってみたい初心者向けに開発方法を紹介！【サンプルあり】](https://qiita.com/guru_taka/items/37a90766f4f845e963e5#%E3%81%8A%E3%81%BE%E3%81%91%E5%88%9D%E3%82%81%E3%81%A6%E4%BD%9C%E3%81%A3%E3%81%9F%E8%A8%98%E5%BF%B5%E3%81%99%E3%81%B9%E3%81%8D%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD)
【Ruby on Rails】初心者でも頻繁に使うActive Recordメソッド

#Active Recordとは
SQLを書かずに、データベースのデータを扱えるようにすることができるRuby on Railsの機能。
これを``ORマッパー``と呼んだりする。
Active Recordを使えば、SQL文を書かずに簡単なメソッドでデータを扱うことが可能になる。

ちなみにRailsに関わらず、PHPのフレームワークでもこのORマッパーを採用している。

## User.all
```
users = User.all
```
すべてのユーザーの情報を取得する。

## User.find
```
user = User.find(1)
```
主キーが一致するユーザーのレコードを取得する。

## User.find_by
```
user = User.find_by(name: 'gorira')
```
指示した条件でカラムのデータが一致する最初の１つのレコードを取得する。

## User.first
```
user = User.first
```
ユーザーの最初の１件のレコードを取得する。

## User.where
```
user = User.where(name: 'takeshi')
```
条件が一致する全てのレコードを取得する。
 
## User.pluck
```
users_name = User.pluck(:name)
```
特定のカラムを配列で取得する。

## User.order
```
user = User.order('id DESC')
```
指定したカラムを基準に並び替える。

## User.delete_all
```
user = User.delete_all
```
ユーザーテーブルのデータをすべて削除する。

## User.eager_load
```
user = User.eager_load(:items)
```
外部結合し、全てのデータを取得する。

###　参考記事
https://railsguides.jp/active_record_basics.html
【Nuxt.js】非同期するなら、$axiosでしょ

#標準搭載のaxiosと、Nuxtモジュールのaxiosの比較

| モジュール | axiosの表記 |
|:-:|:-:|:-:|:-:|
|  axios | axios  
|@nuxtjs/axios |  $axios | 

#getと$getの違い

| メソッド | レスポンス値 | 実際の値 |
|:-:|:-:|:-:|
| get  |  レスポンスデータ / ステータスコード / ステータステキスト / ヘッダー / コンフィグ | res.data / res.status / res.statusText / res.headers / res.config
| $get  |  レスポンスデータ | res


#セットアップ

```
$ yarn add @nuxtjs/axios
```

```nuxt.config.js
modules: [
  '@nuxtjs/axios',
],
axios: {
},
```

#Usage getリクエスト

asyncData関数

```js:script
export default {
  async asyncData({ $axios }) {
    const res = await $axios.$get('URL')
    return {
      data: res
    }
  }
}
```

そのほかでの関数内

```js:script
export default {
  methods: {
    async function () {
      const res = await this.$axios.$get('URL')
      this.data = res
    }
  }
}
```

#Usage postリクエスト


```js:script
export default {
  data () {
    return {
      user: {
        name: '',
        email: '',
        password: '',
      }
    }
  },
  methods: {
    submit: async function () {
      const res = await this.$axios.$post('URL', this.user)
      console.log(res)
    }
  }
}
```

#ルーティング内のid取得に関する比較

| 関数 | /_idの取得 |
|:-:|:-:|
| async asyncData (context)  | context.params.id  |
| その他  |  this.$route.params.id |


#番外編：ES6のDestructuring(分割代入)を利用した記述法

##関数の引数の省略

```js:script
async asyncData(context) {
  const posts = await context.$axios.$get('/posts')
  return { posts }
},
```

↓

```js:script
async asyncData ({ $axios }) {
  const posts = await $axios.$get('/posts')
}
```

##関数の引数 & レスポンス値の定数の省略

```js:script
async asyncData (context) {
  const res = await axios.get('/posts/' + context.params.id)
  return { post: res.data }
}
```

↓

```js:script
async asyncData ({ params }) {
  const { data } = await axios.get('/posts/' + params.id)
  return { post: data }
}
```
Node.jsでsubmitボタンをFont Awesomeにする方法

#プログラミング勉強日記
2020年9月21日
Node.jsのejsファイルでformでデータを送るときにFont Awesomeを使おうとするときに試行錯誤したので備忘録として書いておく。

#現在と目標
　現在は以下のように「削除」ボタンになっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/0ac7c2f1-dcb3-c86e-7429-b9b1ffa67633.png)

```html:現在
<form action="/delete/<%= user.id %>/<%= users[0].id %>" method="post">
  <input type="submit" value="削除">
</form>
```

　それを以下のようにFont Awesomeを用いてアイコンにしたい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/ede76b52-2437-c1fc-3708-e6cf64d44a8f.png)

#解決方法

```html:解決方法
<form action="/delete/<%= user.id %>/<%= users[0].id %>" method="post">
  <button type="submit" class="btn"><i class="fas fa-trash-alt"></i></button>
</form>
```


　個人的にはアイコンの周りの線(ボタンの部分)を消したいが、うまくできないのでこれがうまくできたらまた記事にしようと思う。
【Java開発】第6回 コンストラクタ

#初めに

皆さん。こんにちは！

DreamHanksの254cmです。

今回はコンストラクタについて説明していきます。

Java記事のまとめは[こちら](https://qiita.com/DreamHanks/items/6b1996e1f8ed66bbd456)です。

前回の記事は[【Java開発】第5回 クラス](https://qiita.com/DreamHanks/items/bf001a3ff9290cbbaec1)です。

##コンストラクタ

###・コンストラクタとは？

コンストラクタはクラスのインスタンスを生成するために使うメソッドです。

コンストラクタは「**new**」キーワードを使って呼び出します。

####コンストラクタの呼び出し方

```java
クラス名 変数名 = new クラス名(引数);    //　newの右にコンストラクタが位置する
```

####コンストラクタの書き方

```java
アクセス制御子 クラス名(引数) {
    処理
}
```
メソッドの書き方が似ていますが、コンストラクタは戻り値が存在しません。

サンプルを見ながら説明します。

・サンプル

```java
public class メインクラス名{							
    public static void main(String[] args) {							
    							
        //インスタンスの生成							
        Cat mugi = new Cat(3, "grey");    							
    }							
}							
 							
class Cat{							
	int age;						
	String color;						
 							
    //コンストラクタ（インスタンス生成時に実行される）							
    public Cat(int age, String color){							
		this.age = age;					
		this.color = color;					
    }							
}	
```
上記のように作成するとCatクラスのインスタンスを生成したと否やmugiのageとcolorに値が設定されます。

コンストラクタはインスタンスを生成するたびに呼び出され、

インスタンス作成時に実行する処理を指定することができます。

つまり、作成者が意図した通りインスタンスを生成することができます。

####※デフォルトコンストラクタ

javaコンパイラーはコンストラクタを作成していないクラスに対して、

デフォルトコンストラクタを追加させます。

デフォルトコンストラクタは実際のソースコードでは見えないですが、

以下のようなものが追加されます。

```java
public クラス名() {

}
```
上記のような空のコンストラクタが追加され、

コンストラクタを作成しなくてもクラスのインスタンスを生成することができます。

しかし、デフォルトコンストラクタはインスタンスの生成以外の動作はしません。

・サンプル

```java
class Test { 				
    int test;			
}				
				
public void main (String args[]) {				
    Test t1 = new Test();			
}				

```
上記のようなコンストラクタが作成されていなくても、インスタンス生成ができます。


```java
class Test { 				
	int test;			
	public Test () {    //実際のソースコードでは見えないですが、このような			
			            //コンストラクタが追加されます。	
	}			
}				
				
public void main (String args[]) {				
		Test t1 = new Test();		
}				
```
					
デフォルトコンストラクタは一般のコンストラクタが作成されている場合には							
使用できません。

クラスの作成者がインスタンス生成時に意図した処理を実行させたくてコンストラクタを

作成しますが、デフォルトコンストラクタを使用すると意図した処理を

実行させることができないのでです。


##this

###・thisとは？

thisはインスタンスが自分を参照するために使われる変数です。

thisはインスタンスのアドレスを示しています。

・サンプル

```java

public class Dog {											
	public int age;										
	public String name;										
	public String species;										
											
	public Dog(int age, String name, String species) {										
		this.age = age;									
		this.name = name;									
		this.species = species;									
	}										
}
```
上記のサンプルを見ると

this変数を利用して自分(Dog)のage,name,speciesに接続して

パラメターのage,name,speciesを代入しています。

上記のサンプルのようにコンストラクタのパラメターとクラスのフィールドの名前が重複された場合

this変数を利用して区分けすることができます。

this変数は後で勉強するstaticメソッドでは使えません。

staticメソッド以外のメソッドは中でthis変数が隠されていて

this変数を使うことができます。

#終わりに

今回の記事は以上になります。

次回はJavaクラスの[継承](https://qiita.com/DreamHanks/items/d09a6d494563954780de)を学びましょう。

私たちの最新の記事は[こちら](http://blog.dreamhanks.com/java%e5%85%a5%e9%96%80%e8%ac%9b%e5%ba%a7/)で確認することができます。

ご覧いただきありがとうございます。
2020年に最も人気があるプログラミング言語 10選

元記事： [https://jp.scrapestorm.com/tutorial/10-most-popular-programming-languages-in-2020/](https://jp.scrapestorm.com/tutorial/10-most-popular-programming-languages-in-2020/)

プログラミングの初心者について、より良い見通しがある言語を選択するは非常に重要です。本文は十種類の2020年に最も人気があるプログラミング言語を紹介します。

まずTIOBEランキングを見てみます。非常に権威のあるランキングです。次の14つは長く生きているので、SQLがGOに置き換えられたことを除いて、他の9つのプログラミング言語がすべて存在し、長い間リストを支配していることがわかります。これから一つずつ紹介しましょう。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/8752ed6e-1360-9a99-edfc-00157ef8e389.png)
##1.Java
Javaは実際にはC ++の代替品です。Sunは当初、C ++よりも簡単なオブジェクト指向プログラミング言語を開発したいと考えていました。時間の経過とともに、Javaは学習とクロスプラットフォーム化が容易になるため、Javaの人気はC ++の人気をはるかに超えています。
Java仮想マシンの助けを借りて、JavaはLinux、Windows、Mac-OSなどのさまざまなオペレーティングシステムで自由に使用できるため、エンタープライズレベルの開発で非常に人気があります。
##2.C++
名前からわかるように、C ++はC言語の拡張機能であり、C言語のオブジェクト指向関数の作成を目的としています。
C ++はすべてのプラットフォームで実行でき、あらゆるタイプのハードウェアを効果的に利用できるため、リソースが限られたプラットフォームで最高のパフォーマンスを発揮できます。
##3.C
C言語は、1972年にAT&Tベル研究所のデニス・リッチーが主体となって開発した汎用プログラミング言語である。それは、システムリソースを効果的に使用できるを目指します。当時、メモリのすべてのバイトが高価だったからです。C言語は非常に早い時期に誕生しましたが、依然として最も一般的に使用されているプログラミング言語の1つです。
C ++と同様に、Cもメモリに直接アクセスしてハードウェアを制御できます。 Cはオペレーティングシステムと密接に関連しており、プログラマーはメモリ割り当ての詳細を処理する必要があるため、把握するのが困難です。
##4.Python
学習コストは非常に低いため、すべてのプログラマーはPythonを好みますが、現在の非常に深い人工知能、機械学習、データ分析などのアプリケーションレベルは非常に高くなっています。
Pythonの構文はシンプルでエレガントで、コミュニティも非常に活発です。 しかし、言うべきことの1つは、Pythonの職位には高い学歴が必要であることです。
##5.JavaScript
JavaScriptは高級なダイナミンクプログラミング言語です。非常に人気のあるフロントエンドフレームワークVue.jsはjsJavaScriptで作成しました。フロントエンド開発に従事したい場合は、JavaScriptは必須であると言えます。
##6.C#
当初、C＃はJavaのコピーと見なされていましたが、それらには著しい類似点があり、Javaとほぼ同じ構文であり、コンパイルして実行する必要があります。 時間の開発とMicrosoftによる多大な努力により、C＃は豊富なクラスライブラリとフレームワークを蓄積し、開発者はこれに基づいて.NETプラットフォームに基づくさまざまなアプリケーションをすばやく作成できます。
##7.Swift
Swiftは、Appleによって作成された強力で直感的なプログラミング言語であり、iOS、Mac、Apple TV、およびApple Watch用のアプリの開発に使用できます。 開発者に完全な自由を提供することを目的としています。 Swiftは使いやすくオープンソースであり、アイデアさえあれば、誰でも素晴らしいものを作成できます。
##8.Go
Go言語のデザインは非常に洗練されており、使用方法も非常に簡単で、開発と拡張を解決する能力も非常に優れています。 重要なのは、学習が非常に簡単であり、これらの利点がGo言語の急速な成長に貢献していることです。
Google、AWS、Cloudflare、CoreOSなどはすべて、クラウドコンピューティング関連製品の開発にGolangを大規模に使用し始めています。 未来はとても明るいと言えます。
##9.PHP
PHPがWebアプリケーションを開発したのは35年以上の歴史があります。PHPは常にWeb開発の王様でした。特に、WordPressなどのコンテンツ管理プラットフォームの人気とFacebook（PHPが開発した）の支持が相まって、業界でのPHPの地位が強化されました。
##10.Ruby
Rubyはもともとオブジェクト向けのスクリプトプログラミング言語でしたが、時間が経つにつれて、徐々に解釈された高水準の汎用プログラミング言語に発展しました。 開発者の生産性を向上させるのに非常に役立ちます。シリコンバレーでは、Rubyは非常に人気があり、クラウドコンピューティング時代のWebプログラミング言語として知られています。
AWS Network資格に合格しました

# はじめに
今日（9/21）に「AWS Certified Advanced Networking - Specialty」資格（以降ANS）に受かったので、勉強に使った教材や試験の所感を書いていきます。
最初に白状しておくと、自分は9/6に一度受けて落ちているので、2回目の受験での合格でした。
自分みたいにネットワーク回り（ルーターやスイッチなど）をまったくやっていない人や、Direct Connectの構築をやったことのない人にはちょっと頑張りが必要な試験でした。
誰かの役に立てば幸いです。

※過去の記事
[AWS SAAに受かった話](https://qiita.com/kkino1985/items/85bcfa50686fcfe69c56)
[AWS SOAに受かった話](https://qiita.com/kkino1985/items/295509d3d94c726ae56a)
[AWS DVA(とCLP)に受かった話](https://qiita.com/kkino1985/items/8f3db5e102876cca47b1)
[AWS SAPに受かった話](https://qiita.com/kkino1985/items/7ad6bcdde44a2b4e4916)
[AWS SCSに受かった話](https://qiita.com/kkino1985/items/7182ada488b60d196ec5)

# 獲得スコア
|受験日|スコア/合格点/満点|結果|
|:--|:--|:--|:--|
|2020/9/6|62%/65%/100%|不合格|
|2020/9/21|72%/65%/100%|合格|

# 勉強に使った教材
※いつものようにBlackbeltとWhizlabsは省略
※また、ANSだけは公式の模擬試験が無いです（スコアレポートの表示方法も違うので、管理している団体が違うとかそういう理由かも）

## AWS Summit 2019資料
AWS認定資格は最新情報よりちょっとだけ内容が古いので、少し前のセッション動画/資料を見るのがおすすめです。
（Blackbeltでも可）

https://aws.amazon.com/jp/summits/tokyo-osaka-2019-report/

※この中でも「ネットワークデザインパターン Deep Dive」というセッションはこれまでのアップデートの歴史から触れてくれているので、非常に参考になりました。

## AWS公式ドキュメント
後でも触れますが、Direct ConnectやVPNの設定方法はかなり詳しく問われるので、コンソールでの設定方法（手順や入力項目）や接続完了までの流れは公式ドキュメントを読み込むようにしましょう。
文字だけではわかりにくかったりするので、「Direct Connect 作成」などで検索して、コンソール画面を貼ってくれている人の記事などを読んだりしました。

## Direct Connectハンズオンセミナー
Direct Connectは実際に試すのが難しいですが、定期的にハンズオンセミナーが開催されています。
実際に手を動かす機会でもあるので試験を受ける人はなるべく参加した方が良いと思います。
（自分はタイミングが合わずに参加できませんでしたが）
https://aws.amazon.com/jp/dx_labo/

# 試験の所感
- 試験自体がTransit GatewayやDirect Connect Gateway、Route53 Resolverが出る前の世界線
    - それらが無い時はインスタンスを立ててやっていたと思うと、AWSのサービスリリース方針が見えてきて面白い
- ネットワークの話は思ったより細かく出る
    - 実際の設定手順は知らなくても良いが、それぞれの設定がどういうもので、いつ使われるかは知っておく
- Direct Connectの作成手順は細かく問われる（専用線接続もホスト接続も）
    - LOA-CFAはいつどうやってもらえるのか、もらった後はどうするのか、等々
- VPCフローログの使われる場面（できることとできないこと）
- 複数のVPCがある構成で、どことどこを何で接続するか、という問題が多い
    - VPCピアリングをするのかVPN接続をするのか。はたまたDirect Connectで繋ぐのかなど
- オンプレの名前解決をAWS側のDNSで解決する構成（もしくは逆の構成）
- Cloudformationは普段から業務で使っている人、あるいはDOP試験に受かる知識があれば準備不要
- 問題文はよく読む（重要）
    - オンプレとAWSの接続要件が具体的には「プライベート」なのか「暗号化」なのか
    - （Direct Connectはプライベートではあるものの通信の暗号化はしていない点に注意）
- 字面だけだと構成図が浮かびにくいので、（SAPほどではないものの）普通にやると結構時間がかかる
キャッシュ　cookie　セッション

#【キャッシュ　cookie　セッション】

Webサービスを使用する上で基本となるのでまとめてみました！

##キャッシュ（cache）　

一度閲覧したWebページの情報を一時的に保存しておく機能。
Webページの情報、データ（よく使うデータ）を取り出しやすいところに準備しておく。

再度、閲覧する時のページ読み込みの速度が速くなる。

##cookie（クッキー）　

一度ログインに成功したWebページのユーザー情報を保存しておく機能。
ID、パスワード、訪問回数などがユーザー情報として保存される。

ブラウザにログイン情報を残す機能ともいえる。
ユーザー情報、WebブラウザとWebサーバやりとりは、ユーザーの目には見えない。

cookie内に情報が残り続けるとセキュリティ上危険なため、セッションで安全に情報を保持する。

##セッション（session）　

ログイン後のユーザーの一連（初めから終わりまで）、固有データでなく、Web上で操作したデータ（履歴）のこと。

cookieを使用した一連の操作で、セッションIDが使われる。安全性が高い。

##さいごに

近年は、よりセキュリティの重要性が増してきていると思います。
Webの根本的な仕組みをもっと学んでいきます。
Moment.js → Day.js の移行は全置換じゃだめ。イミュータブルですので

タイトルで言いたいことがわかった人は読む必要のない話です。

## サマリ

[Day.js](https://github.com/iamkun/dayjs) は JavaScript の軽量な日付操作ライブラリで、Moment.js のAPIと互換性があるため、Moment.jsからの移行先として候補にあがることが多いです。

Moment.js との大きな違いとして、単体で Locale の情報を含んでおらず、プラグインを追加して利用する必要があります。
これについてはこの記事では割愛します。

もうひとつ、Day.js は Moment.js と違って **immutable（不変オブジェクト）** であるという特徴を持ちます。
個人的にこれは Moment.js と比べて優れた点であると思いますが、移行の際は気をつけないと、発覚の遅れるバグを生む危険性があります。

日本語の紹介記事をざっとググった限り、この点にちゃんと言及している記事が見つからず、誰かが不幸になりそうな気がしたので書いておきます。

## 検証バージョン

* Moment.js: 2.28.0
* Day.js: 1.8.36 

## 何が危険か

前述のとおり、Day.js は Moment.js となまじ互換性のある API を持つため、ソースコード内で `moment` と書いているところをガバっと `dayjs` に置換してしまえば、それでほとんど問題なく動いてしまいます。

実際そのような説明をしている日本語情報もいくらか見つかるのですが、 `add` や `subtract` といった操作関数の使い方によっては、意図しない結果を生むことがあります。

## 具体例

Moment.js を使い、日付に1日を加算してから文字列化するコードです。

```js
const m = moment("2020-12-31");
m.add(1, "days");
console.log(m.format("YYYY/MM/DD"));
```

出力結果は「2021/01/01」となります。
これを Day.js に置き換えます。

```js
const d = dayjs("2020-12-31");
d.add(1, "days");
console.log(d.format("YYYY/MM/DD"));
```

出力結果は **「2020/12/31」** となります。

## 解説

蛇足ながら解説しておきます。

Moment.js の `add` 関数は、戻り値で加算後のオブジェクトを返すと同時に、自身の値も書き換える挙動をします。

```js
const m1 = moment("2020-12-31");
const m2 = m1.add(1, "days");
console.log(m1.format("YYYY/MM/DD"));   // 2021/01/01
console.log(m2.format("YYYY/MM/DD"));   // 2021/01/01
console.log(m1 === m2); // true（実は同じオブジェクト）
```

Moment.js 単体で見た場合、この挙動はしばしばバグを生む原因でもありました。
もっと凶悪なのは、 `startOf` という、副作用を持つことが想像しにくい関数さえも内部状態を書き換えてしまうことです。

```js
const m1 = moment("2020-12-31");
const m2 = m1.startOf("month");
console.log(m1.format("YYYY/MM/DD"));   // 2020/12/01
console.log(m2.format("YYYY/MM/DD"));   // 2020/12/01
console.log(m1 === m2); // true
```

Day.js はこのような挙動を改善するため、これらの関数を内部状態を書き換えないイミュータブルな仕様に変更しています。
最初から Day.js を採用する場合は望ましい挙動ではありますが、Moment.js で動いていたものをそのまま置き換えられるわけではない点に注意が必要です。

```js
const d1 = dayjs("2020-12-31");
const d2 = d1.startOf("month");
console.log(d1.format("YYYY/MM/DD"));   // 2020/12/31
console.log(d2.format("YYYY/MM/DD"));   // 2020/12/01
console.log(d1 === d2); // false
```

## 結び

以上です。
■初心者向け　デプロイ/Capistranoの使い方

昨日初めてCapistrano（カピストラーノ）を実装したのですが
何が出来るのかいまいち分からないままだったので改めて教えてもらいました！

■出来る事
・開発環境で行った変更を本番環境へ自動的にデプロイ
・下記のコマンドで本番環境の再起動までやってくれる

■使い方
①開発環境で機能追加等を行い、リモートリポジトリ（GitHub）へプッシュ
②$ bundle exec cap production deploy　を実行
（①、②は開発環境のアプリケーションディレクトリで行います）
③自動的にデプロイ完了！

Point
・開発環境でどのブランチで変更したものが反映されるんや…と思い聞いてみたところ
どうやら「default」ブランチが本番環境には反映される模様。
なので、トピックブランチで変更したものは一度、デフォルトのブランチへ統合して
そこから「$ bundle exec cap production deploy」　を実行してみようと思います。

何か間違いがありましたらご指摘いただけると幸いです。
よろしくお願い致します。
ExcelからPython起動しよう。VBAは使わないよ。

初めての投稿です。

Excelにデータを溜めて、Python実行することありませんか？
データ変更⇔実行を繰り返す場合、ExcelからPythonを起動したくありませんか？

ネット調べるとVBAを使う方法はありますが、私は好きじゃないのでこの方法を試しました。
※マクロ実行でセキュリティがどうのこうの聞かれるのがね。。。

#対象
下の全部が当てはまっている人
・Excelに溜めたデータを、Pythonで分析したい
・Excelをフロントエンドにしたい
・VBAは使いたくない
・Windowsを使っている

#概要
Excelのハイパーリンクを使って、batを起動します。
batファイルにPython起動の文を書いておけば、Excelからリンクを押しただけでPythonが動きますよ。


#0.最初の状態
下図のように、Excelファイルと、実行したいPythonファイルがあるとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/733028/a65f7b3c-3136-6a53-50a0-6d89fa56692c.png)

# 1.batファイルの作成
下図のようなbatファイルを作成します。
保存場所は上のファイルと同じ場所です。
1行目は、cdで「%~dp0」まで移動します。「%~dp0」とは、このbatファイルが保存されたパスを示す値です。
2行目は、Pythonを起動文です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/733028/8e6d5f6c-95ea-f767-6af3-bf080dd378d7.png)

#2.Excelにハイパーリンクを作成
Excelの好きなセルを右クリックし、「リンク」で先ほど作ったbatファイルを選択しましょう。
※ちなみにバージョンは2016です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/733028/b2e0f44e-8454-3488-2a42-829c98eb9a06.png)

#3.実行
このハイパーリンクを押せば、自動的にbatが開き、そして自動的にPythonが起動します。
Pythonの中ではpandasでExcelデータを読み込むように設定しておけば良いですね。

#終わり
小技でしたが、VBAを使わなくても目的は達成できました。
宜しければお使いください。
配列の間に特定要素を挿入するコード（javascript）

## コード

```javascript
const data = [1, 2, 3];
const separater = 0;

const result = data.map((item, index)=>{
  return [index * 2, item]
}).concat(
  Array.from({length: data.length - 1})
  .map((_, index) => [index * 2 + 1, separater])
).sort()
.map(tuple=>tuple[1]);

console.log(result);
// [ 1, 0, 2, 0, 3 ]
```

## 解説

### 1. データに偶数インデックスを貼ります

```javascript
data.map((item, index)=>{
  return [index * 2, item]
})
```

### 2. 奇数インデックスを貼った挿入データの配列を作ります

```javascript
  Array.from({length: data.length - 1})
  .map((_, index) => [index * 2 + 1, separater])
```

### 3. 1-2を結合してソートをかけて値だけ抜いてきます

```javascript
const result = data.map((item, index)=>{
  return [index * 2, item]
}).concat(
  Array.from({length: data.length - 1})
  .map((_, index) => [index * 2 + 1, separater])
).sort()
.map(tuple=>tuple[1]);
```

## 用途

Reactで要素の間に`<hr/>`要素を挟み込みたかったので作りました