OmniAICreator/Qiita-1.07M huggingface dataset:
railsアプリで使うsqlってMySQL？Postgre？

## rails newコマンド

```
>rails new [アプリ名]
```
オプションをつけずにこれで作成するとmysqlでプロジェクトが作成されます。

```
>rails new [アプリ名] -d postgresql
```
だと、postgresqlでプロジェクトが作成されます。



## PosgreとMySQLの違い
[PostgreSQLとMySQL、使うならどっち？ データベース専門家が8つの視点で徹底比較！](https://employment.en-japan.com/engineerhub/entry/2017/09/05/110000)
正直よくわからない・・・。大規模だったり多機能な方がpostgre,小規模なのがMySQLってイメージでいいのかな。


## GUIツール
DBの中身をGUIで見たりいじったりするツールが違います。

mysqlだとSequelPro。使いやすい・・・。
[Sequel Pro](https://www.sequelpro.com/)
![スクリーンショット 2018-02-11 17.32.27.png](https://qiita-image-store.s3.amazonaws.com/0/217831/c8ae8fee-1323-4b87-e288-bbaf1350e2e1.png)


postgresqlだとPG Commander。接続するのにちょっと手間取った。
[PG Commander](https://eggerapps.at/pgcommander/)
![スクリーンショット 2018-02-11 17.32.05.png](https://qiita-image-store.s3.amazonaws.com/0/217831/a105201e-1ef3-f471-1741-31da34d1a62f.png)


##デプロイ
Herokuのデフォルトはpostgresqlなので、postgreで作ってあるとHerokuへのデプロイがすごく簡単です。mysqlの場合はアドオンを追加したり、mysqlのバージョンの変更だったりをする必要があります。
[HerokuでMySQLを使おうとして詰まったところ](https://qiita.com/sseo/items/108ef1d94dcb5b227b4f)


## 結局どっち
プロジェクトによっても違うんだろうけど、これから自分が作るアプリケーションとかを考えるとmysqlの方がいいのかな。herokuでmysql使うのもそこまで手間じゃないです。早い人なら数分くらいかも。
JavaScriptで2次元配列を1次元配列に変換する今風なやり方 reduce + スプレッド演算子(...) しかも速い!!

# 背景
JavaScriptでcsvのデータを処理していて, 2次元配列を一つにつなげて1次元配列にしたかった.

# 問題
こんなデータをどやって1次元配列に格納するか.

```javascript
const data = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12],
];
```


# 対処法
## 方法1: 古典的にfor文を回して, pushする

まず, 空の配列を用意して, 2重のfor文を回して順次pushしていく方法

```javascript
var list = [];
for(var i=0;i<data.length;i=i+1){
  for(var j=0;j<data[i].length;j=j+1){
    list.push(data[i][j]);
  }
}
```

## 方法2: 今風(ES2015)な方法 reduce と スプレッド演算子

reduceとスプレッド演算子(...のこと)を使うと一行で代入できる.

```javascript
const list = data.reduce((pre,current) => {pre.push(...current);return pre},[]);
```

# 実行速度
では実行速度はどうなのだろうか.
今風な書き方の方が短く書けるから好きだけれど, 古典的for文の方が早いと思っていた.
しかし, 結果は違った.

Chrom ver. 64.0.3282.140
でconsole.time()とconsole.timeEnd()を使て計測した.

1000×1000の2次元データの1次元への変換を100回繰り返すのにかかった時間が下記

| 方法1: for文 | 方法2: reduce+スプレッド演算子 |
|:-:|:-:|
|2331 ms| 1784 ms|

なんと今風な方法2の方が速い!!

# テスト方法
jsnoteにテストコードを張り付けて実行した.

[![Imgur](https://i.imgur.com/HstpPha.png)](https://toyoharu-nishikawa.github.io/jsnote/)

jsnoteについては[こちらの記事](https://qiita.com/Toyoharu-Nishikawa/items/044d53974c42bc635f0f)

テストコード

```javascript:speedTest.js
const data = [];
for(let i=0;i<1000;i++){
  data[i]=[];
  for(let j=0;j<1000;j++){
    data[i][j]=i*10+j;
  }
}
console.log(origin);

console.time("method1");
for(var n=0;n<100;n++){
  var list = [];
  for(var i=0;i<data.length;i=i+1){
    for(var j=0;j<data[i].length;j=j+1){
      list.push(data[i][j]);
    }
  }
}
console.timeEnd("method1");

console.time("method2");
for(let n=0;n<100;n++){
  const list = data.reduce((pre,current) => {pre.push(...current);return pre},[]);
}
console.timeEnd("method2");

```

# 感想

これからは心置きなく今風なやり方でどんどん行こう.
python printを使いこなしてみる。

## '..' と ".."　の使いわけ

pythonで文字列を示す時は、'(シングルポーテーション)も"（ダブルポーテーション）も使えます。その際のに陥りやすい落とし穴をメモ。

```py3:print_lesson1.py
print('I don't know')        #エラー'
print('I don\'t know')     　#OK
print("I don't know")      　#OK
print('''I don't know''')    #OK
print("""I don't know""")    #OK

print("say "Hi Coco!"")      #エラー
print("say \"Hi Coco!\" ") 　#OK
print('say "Hi Coco!" ') 　  #OK
print("""say "Hi Coco!" """) #OK
print('''say "Hi Coco!" ''') #OK
```

文字列の中で「'」 や　「"」を使う時には、前に「\」をつければ解決する。あるいはクォート3つで囲めば解決する。
また、C言語の時は、「¥」を「\」の代わりに使ってたりしたけど、それはできないみたいなので注意です。

##改行「\n」の落とし穴
\nが改行という意味になるが、文字列内に同じものが存在する場合は、最初にrと書くことによって表示することができる。

```py3:print_lesson2.py
print('C:\name\name')      #エラー
>>
C:
ame
ame

print(r'C:\name\name')     #OK
>>
C:\name\name

```

##文章が長い場合に使える技
長い文章を書く時は、下記のような方法を取ると見やすくなる。また、前後にスペースがはいいてしまうので、それをなくすためには「\」を入れると良い。

```py3:print_lesson3.py
print("""
Line 1
Line 2
Line 3
"""
)
>>
(スペース)
Line 1
Line 2
Line 3
(スペース)


print("""\
Line 1
Line 2
Line 3\
"""
)
>>
Line 1
Line 2
Line 3
```


###Read Me
このメモについて
Udemyのアメリカシリコンバレーの世界IT産業トップのIT企業で働くソフトウェアエンジニアが、Python3の入門、応用、コードスタイルを伝授してくれる、酒井潤さんのコースからの学びメモです。
※pycharmを活用して行ってます。
SICP読書録 #10 1.3.1 引数としての手続き

[hiroshi-manabe様の日本語訳](https://github.com/hiroshi-manabe/sicp-pdf)を使わせてもらいます。
練習問題等は[Gauche](http://practical-scheme.net/gauche/index-j.html)で実行。

[前回はこちら](https://qiita.com/shuetsu@github/items/ad94232c8768ef1b1352)

# 1.3.1 引数としての手続き

指定した範囲で、何らかの集計を行う手続きを作ってみる。

```.scm
(define (sum-integers a b)
  (if (> a b)
      0
      (+ a (sum-integers (+ a 1) b))))

(define (sum-cubes a b)
  (define (cube x) (* x x x))
  (if (> a b)
      0
      (+ (cube a) (sum-cubes (+ a 1) b))))

(define (pi-sum a b) ; pi/8 に収束する
  (if (> a b)
      0
      (+ (/ 1.0 (* a (+ a 2)))
         (pi-sum (+ a 4) b))))
```

どれも似ている。というか、以下のパターンに当てはまるものばかりだ。

```.scm
(define (<name> a b)
  (if (> a b)
      0
      (+ (<term> a))
         (<name> (<next> a) b))))
```

このパターンを再利用するには？ `term`と`next`を引数として渡せるようにしてしまえばよい。

```.scm
(define (sum term a next b)
  (if (> a b)
      0
      (+ (term a)
         (sum term (next a) next b))))
```

`sum-integers`、`sum-cubes`、`pi-sum`を、これを使って定義しなおそう。

```.scm
(define (inc n) (+ n 1))
(define (identity x) x)
(define (cube x) (* x x x))

(define (sum-integers a b)
  (sum identity a inc b))

(define (sum-cubes a b)
  (sum cube a inc b))

(define (pi-sum a b)
  (define (pi-term x)
    (/ 1.0 (* x (+ x 2))))
  (define (pi-next x)
    (+ x 4))
  (sum pi-term a pi-next b))
```

このパターンを再利用すれば、積分だってできる。

```.scm
(define (integral f a b dx)
  (define (add-dx x)
    (+ x dx))
  (* (sum f (+ a (/ dx 2.0)) add-dx b) dx))
```

`cube`を0から1の範囲で積分すると、1/4になるはず。やってみよう。

```.scm
gosh> (integral cube 0 1 0.01)
0.24998750000000042
gosh> (integral cube 0 1 0.001)
0.249999875000001
```

### 練習問題 1.29

シンプソンの公式というのを利用すると、より正確な積分ができる。
nは適当な偶数、$h=(b-a)/n$で、$y_k=f(a+kh)$とすると、

```math
\int_{a}^{b}f=\frac{h}{3}(y_0+4y_1+2y_2+4y_3+2y_4+...+2y_{n-2}+4y_{n-1}+y_n)
```

実装してみよう。

```.scm
(define (integral f a b n)
  (define h (/ (- b a) n))
  (define (term k)
    (* (f (+ a (* k h)))
       (cond ((= k 0) 1.0)
             ((= k n) 1.0)
             ((= (remainder k 2) 1) 4.0)
             ((= (remainder k 2) 0) 2.0))))
  (* (/ h 3.0) (sum term 0 inc n)))
```

実行してみる。

```.scm
gosh> (integral cube 0 1 10)
0.24999999999999997
gosh> (integral cube 0 1 100)
0.24999999999999992
gosh> (integral cube 0 1 1000)
0.2500000000000002
```

### 練習問題1.30

`sum`手続きは再帰プロセスになる。反復プロセスに書き換えよう。

```.scm
(define (sum term a next b)
   (define (iter a result)
     (if (> a b)
         result
         (iter (next a) (+ (term a) result))))
   (iter a 0))
```

先ほどの`integral`を再びロードして実行してみる。

```.scm
gosh> (integral cube 0 1 10)
0.25
gosh> (integral cube 0 1 100)
0.25
gosh> (integral cube 0 1 1000)
0.25000000000000006
```
sshでpermissin deniedとなったとき

鍵を作成

```
ssh-keygen -t rsa
```

公開鍵をsshでログイン先に登録

```
ssh-copy-id -o StrictHostKeyChecking=no $HOST/.ssh/id_rsa.pub [ログイン先]
```

すると以下のエラー

```
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
```

パスワードでのsshログインを許可する為に、
ログイン先のサーバーで以下を設定


```
# vi /etc/ssh/sshd_config
...
PasswordAuthentication yes	 ←yesにする
...
remote# systemctl restart sshd

```

これでssh-copy-id実行時パスワードを入力することにより、.ssh/authorized_keysに公開鍵を設定できる
Mastodonで異なるインスタンスにマルチポストする

#はじめに
前回、[GithubでのアクティビティをMastodonへとTootする](https://qiita.com/S_H_/items/ab4d1e53f78f75a5080e#_reference-58d2baa9e24427a30317)という記事でGitHubでのアクティビティをIFTTTとWebHookを使ってTootするという記事を書きました。

その後、色々とIFTTTやWebHookに関して調べていくなかで「本アカウントでTootした内容を他なMastodonインスタンスへTootできそう？」だということが分かりました。
そこで試してみた時の備忘録が、本記事になります。

#必要なもの
今回、必要なものは下記の通り
- Mastodon のアカウント × 2
- IFTTT のアカウント

#手順
## Tootを転送したいMastodonインスタンスのアクセストークンを取得。

IFTTTで転送するにあたって、転送先のアクセストークンを取得する必要があります。
[こちらの記事](https://qiita.com/S_H_/items/ab4d1e53f78f75a5080e#_reference-58d2baa9e24427a30317)を参考にアクセストークンを取得してください。

~~正直、同じものをもう一回書くのはつらいので……~~

## IFTTTでToot転送の設定

まず、 [IFTTT](https://ifttt.com/) へ アクセスして Sign in します。

次に、「My Applet」　をクリックし、「New Applet」をクリックして転送用のアプレットを作成します。

「+this」をクリックし、「RSS Feed」を選択します。
「New Feed Item」という項目があるので、それを選択してください。
選択すると、「Feed URL」という項目が表示されます。そこへ下記のように自分のアカウントのあるインスタンス名とアカウント明を入力してください

```
https://mastodon-instance-name/@account-name.atom
```
「mastodon-instance-name」にはインスタンス名を、「account-name」にはアカウント名を入力してください。

入力後、「Create Trigger」をクリックします。

次に、「+that」を選択肢、「WebHook」を選びます。
その後、表示された「Make a web request」をクリックし、下記の項目に必要な情報を入力していきます。

|項目|内容|
|:-:|:-:|
|URL|https://mastodon-instance-name/api/v1/statuses|
|Method|POST|
|Content Type|application/x-www-form-urlencoded|
|Body|access_token=[転送先のMastodonアクセストークン]&status={{EntryContent}}&visibility=public|

入力後、「Create Action」ボタンをクリックします。
その後に表示される「Finish」をクリックすれば転送の設定は完了です。

## 最後にテストToot

最後に、適当な内容でTootしてテストをしてみてください。
転送には時間がかかるので、少し様子を見てください。

無事に転送されていれば、マルチポストの設定は完了です。

#おわりに

これで、別のインスタンスにTootした内容が転送されるようになります。
マルチポスト厳禁なところでの使用はしないでください。何が起こってもこちらは責任を負いませんので。

それと、現状では```<p></p>```タグが含まれたままTootされてます。
そのあたりも今後の課題として調べておこうかと思います。

#参考

また、下記の記事を参考にさせていただきました。
誠にありがとうございます。

[Twitter の投稿を IFTTT で Mastodon へ転送する。](https://qiita.com/yukimochi/items/f80a50a4486d0cb770dc)

[Swarm のチェックインを IFTTT で Mastodon へ転送する](https://qiita.com/koogawa/items/b17494bea1c13ad0b9ff)

[Raspberry PiでIFTTTのMaker WebhooksにPOSTする](https://qiita.com/undo0530/items/95dc85e3b58380ea359a)

[ノンプログラマーがMastodon BotをIFTTTとかRSSあたりで作ったドン](https://qiita.com/fujii_yuji/items/3507aa9f3d1c6258bb7b)
vagrantなど


vagrant document

```
https://app.vagrantup.com/boxes/search
```



vagrant box

```
https://app.vagrantup.com/boxes/search
```

guest側に自動でguestadditionをインストールする

```
vagrant plugin install vagrant-vbguest
```


vagran box 更新

```
vagrant box update --box [box名]
```
boxファイルをupdateすると古いバージョンと新しいバージョンが混在する

boxファイルが新しいバージョンでないとguestにguestaddtionがインストールできないようだ。
CentOSやRedHatで、Nginxがインストール出来ない場合の対処法

CentOSやRedHatで、「yumで、nginxがインストール出来ない！」「他のインストール方法は分からないしどうしよう・・・」と、お困りの方はご覧下さい。

yumでインストール出来ない原因としては、リポジトリが原因の場合が多いです。
今回は、yumリポジトリにnginxの設定を記述し、yumでインストール可能にする方法を紹介します。

手順は以下のようになります。

**■リポジトリの追加方法**
ファイルがなければ新規作成し、以下の内容を書き込みます。
`# vi /etc/yum.repos.d/nginx.repo`

```
[nginx]
name=nginx repo
baseurl = http://nginx.org/packages/mainline/centos/6/$basearch/
gpgcheck = 0
enabled=1
```

※上記の例では、対象がcentos6.9であった為、baseurl =に`http://nginx.org/packages/mainline/centos/6/$basearch/`となっています。`/centos/6`の部分は、対象に合わせて変更して下さい。
例）RetHat7.2の場合
`http://nginx.org/packages/mainline/rhel/7/$basearch/`

これで、yumを使用してnginxがインストール出来るようになります

参考資料：http://nginx.org/en/linux_packages.html#stable
テストデータとfixtureとseed

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">circleciとかでdb:resetしてからテストしてるんだけど、seedがある前提でテスト書くのは普通なのかな？（seedの使い方間違ってる気がしてきた）</p>&mdash; naichi (@naichilab) <a href="https://twitter.com/naichilab/status/962579470191230978?ref_src=twsrc%5Etfw">2018年2月11日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

twitterで説明するのは辛くなってきたのでqiitaで書いてみます。

# テストに必要なデータは、fixtureで用意する

{project}/spec/factories/category.rb みたいなファイルに、fixtureを用意する。

```rb
FactoryGirl.define do
  factory :category do
    sequence(:name) { |n| "category#{n}" }
    is_open true
  end
end

```

ここでは、とりあえず普通のデータを作れるようになっていればOK。異常系のテストデータとかそんなややこしいことまでは書かない。

# テストで使う

たとえばmodel specだと、 {project}/spec/models/category_spec.rb みたいなファイルに書く。
たとえばCategoryクラスに、そのカテゴリをWEBで見るURLを取得するurlメソッドがあったとすると。

```rb
RSpec.describe Category, type: :model do
  context 'URL normal case' do
    before do
      let(:category_a) { create :category }
    end
    it 'returns url' do
      expect(category_a.url).to eq Category::BASE_URL + URI.encode(category.name)
    end
  
:
```

異常系とかのテストデータはこうやって用意する

```rb
RSpec.describe Category, type: :model do
  context 'URL abnormal case' do
    before do
      let(:category_a) { create :category, name:'//<!-- -->' }
    end
    it 'URLに不適切な文字列が出力されないこと' do
      expect(category_a.url).not_to include('!')
      expect(category_a.url).not_to include('-')
      expect(category_a.url).not_to include(' ')
    end 
:
```

こんな感じでテストできる。

fixtureには汎用的な例だけが書いてあって、テストに固有のデータ(異常系の文字列とか、境界の値とか)はspecファイルに書くのがポイント。こうしておくと、specファイルを見るだけでmodelやcontrollerの使い方をだいたい理解できるようになる。


# seeds.rbは何に使うの？

よくあるのは、カテゴリやタグのデフォルトデータを入れておく。

```
Category.delete_all
Category.find_or_create_by!({
  id: 1,
  name: "ファストフード",
  importance: 5,
})
Category.find_or_create_by!({
  id: 2,
  name: "喫茶店",
  importance: 5,
})

```

こうしておくことで、立ち上げ後にカテゴリを一個一個管理画面から作らなくて済むようになる。


※ とはいえ、そんなまっさらなデータを用意しなきゃいけない場面なんてプロジェクト立ち上げのごく一時期で、本番運用が始まればseeds.rbなんて怖くて走らせられないので、seeds.rbはあまり顧みられなくなることが多い気がする.
で、新人さんが入ってきて環境立ち上げすると、seeds.rbがメンテされてなくて「あれ？」みたいなことになる😅

# seeds.rbにテストデータを入れちゃだめな理由

本番に必要なデータが入ってるのだから、これでテストすれば楽なんじゃないか？という誘惑はわかるのですが。

テストに必要なデータは多種多様だし、テストはどんどん増えてくものだから、その全てのデータをseeds.rb一個にいれようとすると、いずれ破綻します。
(新しいテストのためにseeds.rbを編集したら既存のテストが通らない！みたいなことになります)

seeds.rbはそういう用途に使うファイルじゃないので、テストに必要なデータはfixtureに入れましょう。specテストに必要なデータは全部spec内で生成するので、テストのときにseeds.rbは使いません。
直線(線分)の交点判定

直線（線分）の交点判定をプログラムで求めてみます。

#0.計算したいこと
二つの一次関数で描かれる直線（線分）が交差するか判定してみます。
y = 2x + 3
y = x + 9

#1.Rubyで計算式をプログラムしてみる
プログラム名は、math02.rbとします。
交差したら、座標とともにtrueを表示します。

```ruby
def f1(x)
     2 * x + 3
end

def f2(x)
     x + 9
end

puts "x,y1,y2,cross"
-10.upto(10) do |x|
    y1 = f1(x)
    y2 = f2(x)
    cross = ( y1 == y2 )
    puts "#{x},#{y1},#{y2}, #{cross}"
end
```

#2.実行してみる
```
ruby math02.rb
```

#3.結果
```
x,y1,y2,cross
-10,-17,-1, false
-9,-15,0, false
-8,-13,1, false
-7,-11,2, false
-6,-9,3, false
-5,-7,4, false
-4,-5,5, false
-3,-3,6, false
-2,-1,7, false
-1,1,8, false
0,3,9, false
1,5,10, false
2,7,11, false
3,9,12, false
4,11,13, false
5,13,14, false
6,15,15, true
7,17,16, false
8,19,17, false
9,21,18, false
10,23,19, false
```
どうやら、x=6で2つの直線（線分）は交差するようです。

#4.表計算ソフトで確認してみる
計算結果をファイルに保存します。

```
ruby math02.rb > math02.csv
```

エクセルかLibreOfficeを呼び出して、ファイルに保存した結果を開きます。ファイルの種類をテキストファイルやCSVに切り替えないとうまく見つけられないかも知れません。結果の値をカンマ(,)で区切ったので、表計算ソフトで開くときも区切りにカンマ（コンマ）を指定しないと、うまくxとyの値が分かれてくれないので注意します。エクセルはファイルをダブルクリックして開くだけでうまく分けてくれるハズです。

表計算ソフトでうまく値が表示されたら、2行目以降のxとy1,y2の値の部分だけを範囲選択します。

エクセルの場合は、メニューの挿入から、散布図（直線）か散布図（平滑線）を選択します。
LibreOffceの場合は、メニューのグラフボタンでグラフウィザードを開いて、散布図の線のみを選択して、種類で直線か平滑化曲線を選択して完了ボタンをクリックします。

ちょっとわかりにくいかも知れませんが、x=6の時、交差する2本の線分が表示されます。
Pythonで混合行列からF値を算出する

機械学習のモデル評価で使う「混合行列」から、「F値（F1値）」を算出するスクリプトです。
>F値計算モデルの参考サイト:
>・[機械学習で使う指標総まとめ - 多クラス分類](http://www.procrasist.com/entry/ml-metrics#%E5%A4%9A%E3%82%AF%E3%83%A9%E3%82%B9%E5%88%86%E9%A1%9E)

####ソースコード

```Python:calculation_f1.py
import numpy as np

input_matrix = [ [2, 1, 0],[1, 6, 2],[0, 0, 3] ]

# input_matrix = [ [2, 1, 0], 
#                  [1, 6, 2], 
#                　 　[0, 0, 3] ]


def calculation_f1(input_matrix):

    confusion_matrix = np.array(input_matrix, dtype = 'float')

    matrix_len = len(confusion_matrix)
    col_sum = np.sum(confusion_matrix, axis=1)
    row_sum = np.sum(confusion_matrix, axis=0)

    F1_list = []

    for i in range(0, matrix_len):        
        Precision = confusion_matrix[i][i] / (confusion_matrix[i][i] + (col_sum[i] - confusion_matrix[i][i]))
        Recall = confusion_matrix[i][i] / (confusion_matrix[i][i] + (row_sum[i] - confusion_matrix[i][i]))
        F1 = (2*Precision*Recall) / (Precision+Recall)
        F1_list.append(F1)

    return sum(F1_list)/matrix_len

print("F value: " + str(calculation_f1(input_matrix)))
```

####実行結果

```
F value: 0.7222222222222222
```

scikit-learnでF値のログを取り忘れた為に書きました。
皆さんもログの収集漏れには、くれぐれもお気をつけください...
scikit-learn使用まとめ

scikit-learnの使い方について、使用したものを整理する。

#ロジスティック回帰
参考は[このページ](http://noumenon-th.net/programming/2016/04/27/logisticregression/)。

```python:sample
from sklearn.linear_model import LogisticRegression

#モデルの生成
clf = LogisticRegression()
#訓練データで学習 Xは説明変数のデータフレーム yは答え
clf.fit(X, y)
#学習したモデルの精度
clf.score(X,y)
#モデルの変数ごとの係数を表示
coeff_df = DataFrame([X.columns, clf.coef_[0]]).T
coeff_df
#テストデータから予測する test_dfはテストデータの説明変数のデータフレーム
clf.predict(test_df)
```

#シリアライズ
モデルをpklファイルに出力する

```python:sample
from sklearn.externals import joblib

joblib.dump(モデル, '〜.pkl') 
```

pklファイルから読み込む

```python:sample
from sklearn.externals import joblib

モデル = joblib.load('〜.pkl') 
```
ローカルにインストールしたバイナリファイルを優先的に使いたい。

# Linux コマンド名の競合があるときに，ローカルディレクトリにインストールしてあるバイナリをデフォルトで参照したい。

> バージョン違いのアプリケーションをインストールした場合、PATHの先頭に書かれているディレクトリを順番に検索するため、意図したバージョンで動作しない可能性がある。

http://rh7.hateblo.jp/entry/20100324/1269409310

ということで，~/.bashrcの中に

```bash
export PATH=/home/hnishi/local/bin:$PATH
```

- `PATH=$PATH:/home/hnishi/local/bin`ではないことに注意


と書いておくことで，先にユーザのディレクトに置いてあるバイナリファイルを先に参照してくれる。
こうすれば，スーパーユーザになってリンクを貼り直す必要がない。
【Twitter】GASで自分のツイートを定期RT/引用するbotを作った

投票機能などを使っているときに自分のツイートを定期RTしたい場合があると思います。

「**特定のツイートを定期的にRTする**」というbotに関して、自動作成ツールや知見があまりなかったので共有します。

また、TwitterBot作成方法2018年2月版としてもお使いください。

## やりたいこと
GoogleAppsScript(GAS)を使って、Twitterで定期的にRTまたは引用RTを行う。

## 手順
### 1. プロジェクトを作成する
Googleドライブを開き、GoogleAppsScriptでプロジェクトを適当に作成してください。

### 2. Twitterでアプリケーション登録を行う
[Twitter Application Management](https://apps.twitter.com/)を開き、[Create New App]からアプリケーションを作成してください。

Name, Description, URLは適当で大丈夫です。CallbackURLを以下のように設定してください。

```
https://script.google.com/macros/d/[GASのプロジェクトキー]/usercallback
```

GASのプロジェクトキーは、画面上部のメニューから``[ファイル]→[プロジェクトのプロパティ]→[情報]``とたどると取得できます（「サポート終了」と書かれていますが、現状は使って問題ありません）。


ちなみに、アプリケーション登録には電話番号必須なんですが、登録の際ハマってしまった人は以下を参照。
[Google Apps Script (GAS) でTwitterへ投稿するだけの機能を実装してみる - Qiita](https://qiita.com/akkey2475/items/ad190a507b4a7b7dc17c)

### 3. ライブラリを導入する
GASの上部メニューから``[リソース]→[ライブラリ]``と辿り、「ライブラリを追加」に以下を入力して追加してください。

```
Mb2Vpd5nfD3Pz-_a-39Q4VfxhMjh3Sh48
```

プルダウンからバージョンの指定ができますが、**最新版では次に紹介するヘルパーが上手く動作しない**ため、バージョンは7を選んでおいてください[^1]。

[^1]: 本当は最新版に合わせて訂正すべきとこだったんですが、力尽きましたすみません

### 4. ヘルパーを導入する
GASで``twitter.gs``などの名前でファイルを作成し、以下のヘルパーを丸ごとコピペしてください。

[https://gist.github.com/kijtra/f4cdd8775277372d42f7](https://gist.github.com/kijtra/f4cdd8775277372d42f7)

### 5. 認証する
先ほど作成した``twitter.gs``の18-21行目を訂正します。

```JavaScript
  projectKey: "...", // GASのプロジェクトキー
  
  consumerKey: "...", // Twitterでアプリケーション登録したときに発行されるConsumer Key
  consumerSecret: "...", // 同じく発行されるConsumer Secret
```

ここを訂正した後、GASから``twitterAuthorizeUrl``を実行して認証を行います。
``twitter.gs``を開き、画面上部の「関数を選択」のプルダウンから選んで実行してください。

エラーなく実行が終わったら、**[Ctrl]+[Enter]**でログを開いてください。

![rtbot_1.png](https://qiita-image-store.s3.amazonaws.com/0/70437/c069bc6b-381b-9725-dcea-945c00d8f4ee.png)


そこに記載されているURLにアクセスすれば、認証を行うことができます。

### 6. ツイートするためのコードを書く
それぞれ、``function tweet()``などの名前で関数にしておきます。

#### 引用RT
ありがたいことに、先ほどコピペしたヘルパーにツイート用のメソッドが用意されています。

```javascript
function tweet(){
  Twitter.tweet({ status: "投票お願いします", attachment_url: "引用したいツイートのURL"})
}
```

が、このままやると**全く同じ内容のツイートは2度できない制限に引っかかってしまいます**。

回避策は「文字列の末尾に日付などの値を足す」「前回のツイートをいちいち消す」などが考えられますが、どれも一長一短です。

自分の場合は短期間に数回ツイートするだけだったので、「ツイートの文中にあるスペースをランダムかつ不自然でない範囲で増やす」という一時しのぎ的な回避策を取りました。

（どなたか良いアイデアのあるかた、お願いします。。。）

#### RT
一度手動でRTしておく必要がありますが、これは何度でも実行できます。

```javascript
function tweet(){
  Twitter.oauth.service().fetch("https://api.twitter.com/1.1/statuses/unretweet/[ツイートID].json", { method: "POST" });
  Twitter.oauth.service().fetch("https://api.twitter.com/1.1/statuses/retweet/[ツイートID].json", { method: "POST" });
}
```

ヘルパーの``Twitter.api(path, data)``から任意のAPIを叩けるようにはしてあるのですが、最近RTのAPIが変わったのか上手く動きませんでした。

### 7. 定時実行を設定する
GASの機能で決まった関数を定時実行することができます。

画面左上の時計マークをクリックし、お好みの間隔で設定してください。

**毎分とかにするときっと嫌われます**のでフォロワーさんのTLに迷惑をかけないように。

## 参考文献
以下、参考にさせていただきました。

* [API reference index — Twitter Developers](https://developer.twitter.com/en/docs/api-reference-index)
* [Google Apps ScriptでOAuthConfigのサポートが終了してTwitter botが危険そうだったので変更 - きじとら](https://kijtra.com/article/twitter-api-for-google-apps-script-without-oauthconfig/)
* [Google Apps Script (GAS) でTwitterへ投稿するだけの機能を実装してみる - Qiita](https://qiita.com/akkey2475/items/ad190a507b4a7b7dc17c)
Pepperに推定年齢を喋らせるアプリ

#概要

PepperをPythonだけで開発できる(PythonSDK)と、IBM社のwatsonの"visual_recognition"を連携させて、性別と顔年齢を推定するアプリケーションです。
###PythonSDK
PythonSDKについて詳しく知りたい方は、以下のページを参照してください。

1. https://qiita.com/kyohara/items/ae0dd0f57413caa90674 (PythonSDKの導入方法)
2. https://qiita.com/Atelier-Akihabara/items/3289e60985586b8da709 (Python SDKによるsay hello)
3. http://naoqi.memo.wiki/d/Python%20SDK (PythonSDKリファレンス)

#ソースコード詳細

```python:face_age.py
#coding:utf8
from naoqi import ALProxy#peperのライブラリを使うためにimport
import sys
import paramiko#ssh通信をするためのライブラリ
import scp#scp通信するためのライブラリ
import time
import json
from os.path import join, dirname
from os import environ
from watson_developer_cloud import VisualRecognitionV3#watsonのAPIを使うための


def face_judge(api_key,img_path):
    visual_recognition = VisualRecognitionV3(
    '2016-05-20',
    api_key=api_key)

    with open(img_path, 'rb') as images_file:
        classes = visual_recognition.detect_faces(
            images_file,
            parameters=json.dumps({
                'threshold': 0.4
            }))
    return classes

def main():
    api_key = 'your api key'#ワトソンのAPIキーを取得して、ここに入力してください。
    pepperIP = "your pepper ip adress"#pepperのIPアドレスを入力してください。
    local_path = ""#作業するディレクトリまでのpathを指定
    tts = ALProxy("ALTextToSpeech",pepperIP, 9559);
    tts.say("写真撮影しちゃうよー")
    time.sleep(1)
    tts.say("さん")
    time.sleep(0.3)
    tts.say("にー")
    time.sleep(0.3)
    tts.say("いち")
    time.sleep(0.3)
    tts.say("かしゃ")
    photoCapture = ALProxy("ALPhotoCapture",pepperIP,9559)
    recordFolder = "/home/nao/recordings/cameras/"#pepperは写真をとったときに、このディレクトリに保存される。
    fileName = "test.jpg"
    photoCapture.takePicture(recordFolder, fileName)
    with paramiko.SSHClient() as ssh:
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(hostname= pepperIP, port=22, username='nao', password='nao')
        with scp.SCPClient(ssh.get_transport()) as SCP:
       # scpに対してgetするだけでファイルが取得できる
            SCP.get(recordFolder+fileName,local_path+fileName)
    tts.say("今あなたのことを解析中だよ。ちょっとまってね")
    classes = face_judge(api_key,fileName)

    min_age = classes['images'][0]['faces'][0]['age']['min']#年齢の最大値を取得
    max_age = classes['images'][0]['faces'][0]['age']['max']#年齢の最小値を取得
    gender = classes['images'][0]['faces'][0]['gender']['gender']#性別を取得

    if gender =='FEMALE':
        tts.say("あなたは女性ですね。あなたの年齢を当てますよーー,"+str(min_age)+"さいから"+str(max_age)+"さいくらいの年齢ですね。")
    elif gender == 'MALE':
        tts.say("あなたは男性ですね。あなたの年齢を当てますよーー,"+str(min_age)+"さいから"+str(max_age)+"さいくらいの年齢ですね。")

if __name__ == "__main__":
    main()
```

まず、pepperの写真を撮る機能を使うと、pepperの頭の中のOS(naokiOS)上の、`/home/nao/recordings/cameras/`に`test.jpg`という名前で保存されます。この画像をscpを用いて、ローカル環境(自分のパソコン)に落とし込みます。その後、watsonの"visual_recognition"を用いて、画像から年齢、性別を判別します。判別結果をペッパーに喋らせます。
#結果
私(22)は、メガネをつけない場合は18歳から24歳と診断されましたが、メガネをつけると35歳から44歳と判断されました。悲しいです。ただ、Pepperと連携することで、データの収集などできるかも？？

by アトリエスタッフ
mswin.vim

#概要
　やっぱり、cntl+cとvは普通に使いたいんだが、なかなかmswin.vimにはくせがあるのでそんな話

#設定
 とりあえず、windowsで動かしてます。
　_vimrcに
　source $VIMRUNTIME/mswin.vim

 っで、shiftで選択して、cntl+cでコピーして、cntl+vでペーストすることができます。
 cntl+aで全部選択も、cntl+z,atl+f4で終了もついてきます。
　ああ、便利

#セレクトモード
　shiftで選択するときは、いつもの「visualモード」でなく、「セレクトモード」になります。
　「visualモード」のつもりで、:で選択範囲に対するコマンドを入れようとすると、選択したものが:になってしまって、意図と違います。

　こんなときには、「cntl+g」とすると、選択されたままで、「visualモード」になってくれます。
　ここで、:を押してokです。

#未だに解明できないこと
　nnoremap \<C-Up> \<C-w>-\<CR>

 が、mswin.vimを設定すると、変になります。
　vimはおかしいのですが、gvimは大丈夫です。
　ここさえ、クリアできれば、いいんですけどねえ・・
Javaのfinal修飾子


Javaのfinal修飾子はクラス、メソッド、変数全てにつけることができますが、
それぞれ意味が異なります。

# クラスに付ける場合 [継承の禁止]
クラスにfinal修飾子を付けた場合は、そのクラスは継承することが出来なくなります。コンパイルの段階でエラーとなります。

```java
// final修飾子のクラス
final class FinalDemo {
    String name = "final付きのクラス";
    public final void getInfo() {
        System.out.println(this.name);
    }
}

// 小クラス
class FinalDemoChild extends FinalDemo {

}

class MyApp {
    public static void main(String[] args) {
        FinalDemoChild demo = new FinalDemoChild();
    }
}

```

実行結果

```bash
$ java Myapp
Error:(8, 21) java: final final_demoからは継承できません
```



# メソッドに付ける場合 [オーバーライドの禁止]
クラスのメソッドにfinalを付けた場合、そのメソッド子クラスでのオーバーライドが不可となります。

```java
// final付きのクラス
class FinalDemo {
    String name = "final付きのクラス";
    public final void getInfo() {
        System.out.println(this.name);
    }
}

// 小クラス
class FinalDemoChild extends FinalDemo {
    @Override
    public void getInfo() {
        System.out.println(this.name + "の小クラス");
    }
}

class MyApp {
    public static void main(String[] args) {
        FinalDemoChild demo = new FinalDemoChild();
    }
}
```

実行結果

```
$ java MyApp
Error:(11, 17) java: FinalDemoChildのgetInfo()はFinalDemoのgetInfo()をオーバーライドできません
  オーバーライドされたメソッドはfinalです
```



# 変数に付ける場合 [再代入の禁止（定数）]
変数（フィールド）にfinalを付けると再代入ができなくなります。つまり定数です。instanceで変更する必要がないのでstaticを付けてクラス変数で宣言することが多いそうです。また、他の言語と同様、定数は全て大文字で記述します。

```java
// final付きのクラス
class FinalDemo {
    public static final String NAME = "final付きの変数";
}


class MyApp {
    public static void main(String[] args) {
        // 定数の変更
        FinalDemo.NAME = "再代入";
    }
}
```

実行結果

```bash
$ java MyApp 
Error:(9, 18) java: final変数NAMEに値を代入することはできません
```
直線(線分)の座標計算

わざわざ、コンピュータを使うまでもないのですが、一次関数のグラフを描くときに必要な座標を計算してみます。

#0.計算したいこと
一次関数
y = 2x + b
で描かれる直線(線分)の座標を求める

#1.Rubyで計算式をプログラムしてみる
プログラム名はmath01.rbとします。

```rb
def f(x)
     2 * x + 3
end

puts "x,y"
-10.upto(10) do |x|
    y = f(x)
    puts "#{x},#{y}"
end
```
#2.実行してみる
```
ruby math01.rb
```

#3.結果
```
x,y
-10,-17
-9,-15
-8,-13
-7,-11
-6,-9
-5,-7
-4,-5
-3,-3
-2,-1
-1,1
0,3
1,5
2,7
3,9
4,11
5,13
6,15
7,17
8,19
9,21
10,23
```
#4.図形を描く
結果のxとyを使って方眼紙に鉛筆と定規で描きます。完成！！
え？面倒？では、表計算ソフトで描いてみましょう。結果を入力するのも面倒なので、結果をファイルに保存します。ここでは、仮にmath01.csvとします。

```
ruby math01.rb > math01.csv
```
エクセルかLibreOfficeを呼び出して、ファイルに保存した結果を開きます。ファイルの種類をテキストファイルやCSVに切り替えないとうまく見つけられないかも知れません。結果の値をカンマ(,)で区切ったので、表計算ソフトで開くときも区切りにカンマ（コンマ）を指定しないと、うまくxとyの値が分かれてくれないので注意します。エクセルはファイルをダブルクリックして開くだけでうまく分けてくれるハズです。

表計算ソフトでうまく値が表示されたら、2行目からのxとy値の部分だけを範囲選択します。

エクセルの場合は、メニューの挿入から、散布図（直線）か散布図（平滑線）を選択します。
LibreOffceの場合は、メニューのグラフボタンでグラフウィザードを開いて、散布図の線のみを選択して、種類で直線か平滑化曲線を選択して完了ボタンをクリックします。
LinearRegression クラスについてメモ


sklearn の LinearRegression クラスについての個人メモ。

## LinearRegression とは
線形回帰モデルの一つ。説明変数の値から目的変数の値を予測する。

## 導入
import sklearn.linear_model.LinearRegression

## アトリビュート
### coef_
回帰変数。
### intercept_
切片。

## メソッド
### fit(x, y)
線形回帰モデルの当てはめを実行。訓練の開始。
xが対象データで、yが正解データ ※教師あり学習が前提
### get_params()
推定に用いたパラメータを取得。
### predict(x)
モデルを使用して、xに対して予測を実行し予測値を算出する。
###score(x, y)
決定係数を出力。予測値xと正解値yの相関を測る。

## 実践
```python:training
import pandas as pd 
from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split

dataset = load_breast_cancer()

data_x = pd.DataFrame(dataset.data,columns=dataset.feature_names)
data_y = pd.DataFrame(dataset.target, columns = ['y'])

train_x,test_x,train_y,test_y = train_test_split(data_x,data_y)

model = LinearRegression()  #線形回帰モデルの呼び出し
model.fit(train_x, train_y)  #モデルの訓練


print(model.coef_)  #回帰変数の表示
print(model.intercept_)  #回帰直線の切片
print(model.get_params())  #パラメータの取得

print(model.predict(test_x))  #予測値の表示
print(model.score(test_x,test_y))  #決定係数の表示
```


以上。
NanoPi NEOのルートファイルシステムをBuildrootで作る(2)


前回[NanoPi NEOのルートファイルシステムをBuildrootで作る(1)](https://qiita.com/tetsu_koba/items/9a64042ddc26845a507c)の続き。

#カーネルをベンダー提供の4.11.2に入れ替える

前回はBuildrootにすでに用意されているdefconfigを使ってNanoPi NEO用のブートイメージをビルドしました。これにはメインラインのソースコードが使用されていました。
NanoPi NEOの機能のうちのいくつかはまだメインラインにマージされていません。EthernetのMACアドレスを取得する機能もまだでした。これがないとEthernetが使用できないわけではないのですが、MACアドレスが起動するたびに異なるランダム値になります。
今回はMACアドレスをユニークな個体識別のIDとして使用したいので、ベンダーの提供するカーネルに入れ替えたいと思います。

ベンダー提供のソースコードはここにあるものを使いました。
https://www.mediafire.com/folder/n5o8ihvqhnf6s/Nanopi-NEO

## 苦労話

カーネルを差し替えるくらいすぐにできるだろうと思ったのですが、実際にやってみるとカーネルが正しく起動できません。
通常はmmc0として認識されるマイクロSDカードのデバイスがなぜかmmc1となり、そのためにmmcblk0p2 にあるrootfsを見つけることができません。
なぜそうなるかわからないけど、それに合わせてブートパラメータの root=/dev/mmcblk0p2  の部分を mmcblk1p2 に変更して試してみました。
するとrootfsを見つけて先まで進むようになるのですが、途中でハングアップしてプロンプトが出るとこまで到達しません。
カーネルが正しくビルドできていないのか確認するために、それをベンダー提供のブートイメージのものと入れ替えてみるとそっちでは正しく起動しました。なのでカーネルは正しくビルドできていそう。
ubootのスクリプトファイルやinitrdなど、いろいろ差し替えて切り分けをして1日つぶしてしまいました。

結局わかったことは、「ベンダー提供のLinuxカーネルを使うときには、ubootもベンダー提供のものにしなければいけない。」
こんな依存性があるとは。

## 変更点

kernelはcustom tarballを使用する。

```
BR2_LINUX_KERNEL_CUSTOM_TARBALL=y
BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION="http://www.mediafire.com/file/57urrfmb7irxlbb/linux_4.11.2_20170707.tar.gz"
```

それに合わせて使用するLinuxヘッダーファイルも4.11.x にする

```
BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_11=y
```
ubootもcustom tarball を使用する

```
BR2_TARGET_UBOOT_CUSTOM_TARBALL=y
BR2_TARGET_UBOOT_CUSTOM_TARBALL_LOCATION="http://www.mediafire.com/file/wessj3k3974nep1/u-boot_2017.05_20170707.tar.gz"
```

rootfsのサイズが32MBで足りなかったので、128MBに変更する

```
BR2_TARGET_ROOTFS_EXT2_SIZE="128M"
```

それに合わせて、`board/friendlyarm/nanopi-neo/genimage.cfg` に書かれているパーテションサイズも32MB -> 128MB に変更する

Ubootのスクリプトファイル `board/friendlyarm/nanopi-neo/boot.cmd` はベンダー提供のものをベースにramdiskを使用しないように修正する

ついでに、`board/friendlyarm/nanopi-neo/post-image.sh`　でsdcard.img を作成した後にそれをzipで圧縮する

これらの修正したファイルはgistに貼っておきました。
https://gist.github.com/tetsu-koba/0123aeda3298fc07fb79128dbb889f44
log4j#FileAppenderでログファイルの生成/オープンをフックしたい

需要あるのかしらん(´・ω・｀) `FileAppender`においてログファイルが生成あるいはopenされるタイミングをフックしたい場合、`FileAppender`を継承し`setFile`をオーバライドしたクラスを`log4j.Appender`に指定します。

たとえば日付ごとにログファイルを切り替えたいという場合、より具体的には2018年02月11日のログであれば`sample.log.20180211`、2018年02月12日のログであれば`sample.log.20180212`に記録したいという場合は以下のような独自ファイルと`log4j.properties`を用意します。

```properties:log4j.properties
log4j.logger.sample=DEBUG, SAMPLE
log4j.appender.SAMPLE=sample.logger.SampleFileAppender
log4j.appender.SAMPLE.File=C:\\logging\\sample.log
log4j.appender.SAMPLE.Append=true
log4j.appender.SAMPLE.layout=org.apache.log4j.PatternLayout
log4j.appender.SAMPLE.layout.ConversionPattern=%d %p %m %n
```


```java:SampleFileAppender.java
package sample.logger;

import org.apache.log4j.FileAppender;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class SampleFileAppender extends FileAppender {

    @Override
    synchronized public void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize) throws IOException {
        Path path = Paths.get(fileName);
        String baseName = path.getFileName() + "." + DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDate.now());
        super.setFile(Paths.get(path.getParent().toString(), baseName).toString(), append, bufferedIO, bufferSize);
    }

}
```

よくよく考えると、この用途であれば`DailyRollingFileAppender`で十分ですね(´・ω・｀) 良いサンプルではなくてごめんなさい(´・ω・｀)
複数パッケージに分けた記載方法　JavaAPI クラスが読み込まれる仕組み

#複数クラスに分けた記載方法
**（考え方）**
メソッド数が多くなりすぎて、プログラムが複雑になってしまうため、クラス（記載ファイル）を分割することで、より簡潔にプログラムを作成する。
　
**（方法）**
メソッドの呼出時に`クラス名 メソッド名`と記載する

**（例）**
mainクラスの４行目で、keisanクラスのtasuメソッドを呼び出している

<dd><strong>mainクラス</strong></dd>

```java

public class Main {
    public static void main(String[] args){
      int a = 10; int b = 20;
      int total =  keisan tasu(a,b);//クラス名　メソッド名　指定
      System.out.println(total);
    }
}
```


<dd><strong>keisanクラス</strong></dd>

```java

public class keisan {//クラス名 keisan
    public static int tasu(int a, int b){//メソッド名 tasu
      return (a + b);
    }
}
```
**（補足）**
必ず最初は<strong>メインクラスから呼び出す必要がある</strong>

#複数パッケージに分けた記載方法
**（考え方）**
クラス数が多くなりすぎて、プログラムが複雑になってしまうため、パッケージ（フォルダ）を分割することで、より簡潔にプログラムを作成する。
また、**異なるパッケージであれば、同じクラス名を使用出来る。**
　
**（方法）**
メソッドの呼出時に`パッケージ名 クラス名 メソッド名`と記載する

(例〜pkg図〜)

　　　<img width="122" alt="スクリーンショット 2018-02-11 15.31.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/229025/761b3756-4be7-342e-84f5-b2844ec7eba4.png">

**(例)**
<dd><strong>pkg1</strong></dd>

```java

package pkg1;

public class Main {
    public static void main(String[] args){
      int a = 10;
      int b = 20;
      int total =  pkg2.keisan.tasu(a,b);//パッケージ名 クラス名　メソッド名 指定
      System.out.println("足したら"+total);
    }
}



```


**(補足)**
`パッケージ名 クラス名 メソッド名`と記載しているクラスのことを、**完全限定クラス（FQCN）**という。

<dd><strong>pkg2</strong></dd>

```java

package pkg2;//自分の所属するパッケージ名 pkg2

public class keisan {//クラス名 keisan
    public static int tasu(int a,int b){//メソッド名 tasu
      return (a + b);
    }
}
```

#パッケージ名作成時のルール
**（考え方）**
世界中で開発が行われているため、被らない様に以下のルールがある。
　
**（ルール）**
**保有するインターネットドメインを前後逆にしたもの**

**（例）**
メールドメイン：abcd.co.jp
**パッケージ名**：jp.co.abcd

#完全限定クラス名の省略
**（考え方）**
異なるパッケージのクラスを使用する場合、パッケージ名の入力を省略出来る。

**（方法）**
`import`パッケージ名.クラス名;

**（例）**※`pkg2`は複数パッケージに分けた記載方法と同じ内容のため、省略。

```java

package pkg1;

import pkg2.keisan;//importするパッケージ名の指定

public class Main {
	public static void main(String[] args) {
		int a = 10;
		int b = 20;
		int total = keisan.tasu(a, b);//pkg2の記載が不要になる

		System.out.println("足したら" + total);
	}
}

```
**（補足）**

そのパッケージの全てのクラスをimportしたい場合は、`import パッケージ名.*;`と記載する。

#Java APIについて

**（考え方）**
・Javaには、API（アプリケーションプログラムインターフェイス）というのが元々あって、200以上のパッケージや３,500以上のクラスがある。
・`java.lang`パッケージは、使用頻度が多いため`import`しなくても、デフォルトで使用可能。
・`java.lang`パッケージに所属する代表的なメソッドに、`System.out.println`などがある。


#クラスが読み込まれる仕組み
・JVMがクラスローディングを実行し、クラスファイルを読み込む。
・クラスローディングは<strong>必要な時に、必要な分だけ読み込む</strong>という仕組みに基づいている。
・JVMの中で、<strong>クラスローダー</strong>という部分が、ファイルを探している。
・この時、JVMは使いたいクラス名は指定するが<strong>保存場所は指定しない。</strong>
・クラスローダーは<strong>クラスパス</strong>という、あらかじめ指定された場所を探す事で、高速検索を実現している。
Win10 AutoHotKeyで、右Ctrl+矢印キーでPageUp/PageDown/Home/Endする

# 右手だけでカーソルキーと組み合わせて押したい

以前はMacを使っていて MacはFnキーがカーソルキーのすぐ左にあるので Fnキーとカーソルキーの同時押しで PageUp/PageDown/Home/End にしていました。

![macbook key layout](https://images-na.ssl-images-amazon.com/images/I/71gZWY2%2BnbL._SL1000_.jpg)
※画像は適当な借り物です。

デフォルトでそうなっていたのか、カラビナーというソフトを使っていたか、あるいは、パラレルデスクトップ上のWindowsばかり使っていたので、パラレルの設定だったか、どうだったか忘れました。

ともかく、ブラウザ閲覧中とかの場面では、右手だけでPageUp/PageDown/Home/Endを押せるのは便利なのです。


WindowsPCに買い替えたのですが、WindowsノートPCは左下の方にFnキーがあり、カーソルキーの左には右Ctrlキーがあるものが、多いですよね。

![vaio key layout](https://pc.watch.impress.co.jp/img/pcw/docs/1101/583/21_o.jpg)
※画像は適当な借り物です。

以前は東芝が右下(カーソルキーの左)にFnキーを配置していた機種を出していたような気もします。

ということで、右Ctrlキー+カーソルキーの機能をAutoHotkeyを使って変更してみました。

書き方さえわかれば簡単だったのですが、その書き方を知るために調べたのが多かったので、完結にまとめておきます。

# AutoHotkey の設定ファイル

Windows10でAutoHotKeyをインストールするのは、とても簡単なので省略します。すべてデフォルト設定でよかったと思います。

自分がインストールしたのは、
AutoHotkey 
Version 1.1.28.00
です。

インストール後は ahkファイルをダブルクリックすると、AutoHotkeyプログラムが動作するようになるので、
あとは、SJISでahkファイルに設定を書き込み、そのahkファイルをダブルクリックしたり、スタートアップに入れるだけで、その機能が使えます。

今回の件での、設定ファイルは次の通りです。ご参考にどうぞ。

```CtrlArrow.ahk
/*
    RightCtrl+ArrowUp    >>  PageUp
    RightCtrl+ArrowDown  >>  PageDown
    RightCtrl+ArrowLeft  >>  Home
    RightCtrl+ArrowRight >>  End
*/

>^Up::Send {PgUp}
<^>^Up::Send ^{PgUp}
>^+Up::Send +{PgUp}
<^>^+Up::Send ^+{PgUp}

>^Down::Send {PgDn}
<^>^Down::Send ^{PgDn}
>^+Down::Send +{PgDn}
<^>^+Down::Send ^+{PgDn}

>^Left::Send {Home}
<^>^Left::Send ^{Home}
>^+Left::Send +{Home}
<^>^+Left::Send ^+{Home}

>^Right::Send {End}
<^>^Right::Send ^{End}
>^+Right::Send +{End}
<^>^+Right::Send ^+{End}

```

/* ～ */ は、コメント
\>^ は、右コントロールキー
+ は、Shiftキー
Up などは、矢印キー
:: は、なんか設定方法
Send は、送るときにつける。
PgUp とかは、そのまま、そのキー

これで、右Ctrlキーと矢印キーの組み合わせが、Fnキーと矢印キーとの組み合わせと同じように使えます。
Ctrl+矢印キーの機能よりかは、Fn+矢印キーの機能の方が便利ですよ。ブラウザのスクロールとか右手だけでもできるから。

※なぜか、上記設定では、左右Ctrl同時押し↑は、Ctrl + PgUp として動きますが、左右Ctrl同時押し↓は、動きません。よくわからないです。


# おまけ
追記です。

Mac では Fn + Delete キー で、Windows の Delete キーの機能と同じなので、Windows でも同じ位置にある 右Ctrl + Backspace キー で Delete キーの動きをさせるためには、次のように記述します。 

```
/*
    RightCtrl+Backspace >>  Delete
*/

>^Backspace::Send {Delete} 
```



# 参考ページ

キーリスト - AutoHotkey Wiki
http://ahkwiki.net/KeyList#Key_Right

ホットキー - AutoHotkey Wiki
http://ahkwiki.net/Hotkeys

リマップ | AutoHotKey
https://so-zou.jp/software/tool/system/auto-hot-key/hotkeys/remap.htm
KiCAD 入門 コンポーネントライブラリに部品を追加する手順

# KiCAD 入門 コンポーネントライブラリに部品を追加する手順
自分用のメモ たまにしか使わないのでメニューの場所などをわすれてしまい、毎回使い方を検索するはめになるので...。

今回は コンポーネントライブラリに新規で部品を追加する手順のメモ

## コンポーネントライブラリエディタ
1. 起動方法 Eeschemaから，ライブラリエディタを開く
 ![スクリーンショット 2018-02-11 13.47.40.png](https://qiita-image-store.s3.amazonaws.com/0/100147/0ecfc7f3-7b16-82a3-4d29-0ad0dde1af0a.png)

1. コンポーネントライブラリエディタが開いたら 新規コンポーネント作成 を選ぶ  
![スクリーンショット 2018-02-11 13.49.05.png](https://qiita-image-store.s3.amazonaws.com/0/100147/5b4896a0-003f-55ff-32d4-801f84a694cb.png)

1. コンポーネント名,リファレンス記号を入力する  
![スクリーンショット 2018-02-11 13.52.12.png](https://qiita-image-store.s3.amazonaws.com/0/100147/272206f2-c490-696b-f370-451861a3ee35.png)
コンポーネント名とリファレンス名 が重なって表示されるので適当に移動させる (マウスカーソルをあわせて Mキー)
![スクリーンショット 2018-02-11 13.56.34.png](https://qiita-image-store.s3.amazonaws.com/0/100147/740d9ae0-9a4a-da9c-f301-6f25928fe722.png)

1. 矩形などでコンポーネントボディを描く
![スクリーンショット 2018-02-11 14.08.20.png](https://qiita-image-store.s3.amazonaws.com/0/100147/b8031504-d020-fecd-4457-3ae51488bfa9.png)  
![スクリーンショット 2018-02-11 14.02.10.png](https://qiita-image-store.s3.amazonaws.com/0/100147/33617469-d639-ff99-d981-bb1c29a00b3c.png)

1. 新しいライブラリに現在のコンポーネントを保存
![スクリーンショット 2018-02-11 14.10.12.png](https://qiita-image-store.s3.amazonaws.com/0/100147/d1ce772a-9279-86c2-a878-e4f187859428.png)

## ライブラリを読み込む
コンポーネントを利用するにはコンポーネントライブラリに追加する必要がある。

1. コンポーネントライブラリ設定をひらく
![スクリーンショット 2018-02-11 14.24.37.png](https://qiita-image-store.s3.amazonaws.com/0/100147/1b77e54f-c6e9-76a4-fa79-29d72b8cedf3.png)

1. コンポーネントライブラリ設定で追加を選択して .lib ファイルを選択する   
![スクリーンショット 2018-02-11 14.33.38.png](https://qiita-image-store.s3.amazonaws.com/0/100147/fbf2cb67-67da-192f-520b-a080dbbd77ad.png)

1. コンポーネントを配置を選択して作ったコンポーネントを検索 
![スクリーンショット 2018-02-11 14.38.36.png](https://qiita-image-store.s3.amazonaws.com/0/100147/37cb62e7-2b7c-87a9-25fb-c6d28c3cad29.png)  
![スクリーンショット 2018-02-11 14.47.24.png](https://qiita-image-store.s3.amazonaws.com/0/100147/c88c03ea-2eb1-ee19-33fd-f8cdd6180df5.png)


## 参考リンク
[KiCAD用ライブラリへの部品の追加](http://freeplanets.ship.jp/PCB/KiCAD%E3%83%BC%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%B8%E3%81%AE%E9%83%A8%E5%93%81%E3%81%AE%E8%BF%BD%E5%8A%A0.html#NewLib)
Plotlyで散布図

### Plotlyで散布図
```
この記事では plotly 2.3.0を利用しています。
```
### はじめに
***
Plotlyは大変便利です。
実際に業務で利用する上で設定している項目などまとめてみました。ここでは散布図。
なお、チャートは静止画です。

### 普通の散布図
***

```py
# coding:utf-8

import pandas as pd
import numpy as np

import plotly.plotly as py
import plotly.graph_objs as go
import datetime

import plotly.offline as offline
offline.init_notebook_mode()

# データの作成
X = np.random.randint(0,100,10) 
Y = np.random.randint(0,100,10)

trace = go.Scatter(x = X, y = Y, mode = 'markers') 

# レイアウトの指定
layout = go.Layout(
    xaxis = dict(title="X", range = [0,101], dtick=10),   # rangeで範囲、dtick で区間幅
    yaxis = dict(title="Y", range = [0,101], dtick=10))


fig = dict(data = [trace], layout = layout)

```
![Unknown.png](https://qiita-image-store.s3.amazonaws.com/0/50110/1a473e9e-c65a-c816-e1a8-9bd1a35a0d6c.png)


### 散布図　ラベルつき
***

```py

X = np.random.randint(0,100,10) 
Y = np.random.randint(0,100,10) 
LABEL = [chr(i) for i in range(65,65+10)] # ラベル。アルファベットのリスト

trace = go.Scatter(x = X, y = Y,mode='markers+text', text =LABEL, textposition='top') # mode='markers+text' でラベルも表示

layout = go.Layout(
    xaxis = dict(title="X", range = [0,110], dtick=10),   # rangeで範囲、dtick で区間幅
    yaxis = dict(title="Y", range = [0,110], dtick=10),
    font = dict(size = 15)) # フォントサイズ

fig = dict(data = [trace], layout = layout)
offline.iplot(fig)

```
![Unknown-2.png](https://qiita-image-store.s3.amazonaws.com/0/50110/de2205e8-950b-ec72-ae06-c45de8e3eeeb.png)


### バブルチャート
***

```py

X = np.random.randint(0,100,10) 
Y = np.random.randint(0,100,10) 
LABEL = [chr(i) for i in range(65,65+10)] # ラベル。アルファベットのリスト
SIZE = [ i * 5 for i in range(1,11)]             # サイズのデータ

trace = go.Scatter(x = X, y = Y,mode='markers+text', text =LABEL, textposition='top',
                  marker = dict(size = SIZE)) # マーカーサイズ

layout = go.Layout(
    xaxis = dict(title="X", range = [0,100], dtick=10),   
    yaxis = dict(title="Y", range = [0,100], dtick=10),
    font = dict(size = 15)) 

fig = dict(data = [trace], layout = layout)
offline.iplot(fig)

```
![newplot-10.png](https://qiita-image-store.s3.amazonaws.com/0/50110/9b6310de-841a-b8eb-457a-b510137610d4.png)


### 要素によって色分けるような散布図
***

```py

df = pd.DataFrame({
    'X':[10,12,17,20,21,40,45,47,50,60,70], 
    'Y':[10,12,15,17,20,35,40,41,52,55,60], 
    'area':['A','A','A','A','A', 'B','B','B','B','B','B']})


trace0 = go.Scatter(x = df['X'][df['area'] == 'A'], y = df['Y'][df['area'] == 'A'], mode='markers', name ='A')
trace1 = go.Scatter(x = df['X'][df['area'] == 'B'], y = df['Y'][df['area'] == 'B'], mode='markers', name ='B')


layout = go.Layout(xaxis = dict(title="X", range = [0,80], dtick=10),   
                   yaxis = dict(title="Y", range = [0,80], dtick=10))

fig = dict(data = [trace0, trace1], layout = layout)
offline.iplot(fig)

```

![Unknown-3.png](https://qiita-image-store.s3.amazonaws.com/0/50110/0f459ea4-619b-9622-e414-478036344d8d.png)
Javaのイニシャライザーの話


# イニシャライザーとは？
クラス・インスタンスを使う前に一度実行される処理。
クラス変数を初期化するときなどに使う。

```java
class initializer_demo {
	// クラスイニシャライザー
	static {
		// 処理
	}
	// インスタンスイニシャライザー
	{
		// 処理
	}
}
```




# インスタンスイニシャライザーとコンストラクタとの違いは？
インスタンス化する時の処理といえばコンストラクタが思い浮かびますが、
インスタンスイニシャライザーはコンストラクタの前に実行され、コンストラクトはインスタンス化した後に実行されるという違いがあるそうです。
コンストラクタがオーバーロードされて複数ある場合、イニシャライザーは共通処理をまとめ先に実行するなどして使うらしいです。

以下参考コード

```java
class User {
    private String name;
    public static int count;

    // クラスイニシャライザー
    static {
       User.count = 0;
       System.out.println("クラスイニシャライザー実行\n↓");
    }

    // インスタンスイニシャライザー
    {
        System.out.println("インスタンスイニシャライザー実行\n↓");
    }

    // コンストラクター
    public User(String name) {
        this.name = name;
        User.count++;
        System.out.println("コンストラクター実行\n↓");
    }

    // クラス・メソッド
    public static void getInfo() {
        System.out.println(User.count + "回インスタンス化されました\n↓");
    }
}

public class MyApp {
    public static void main(String[] args) {
        User.getInfo();
        User ryo = new User("ryo");
        User.getInfo();
        User yu = new User("yu");
        User.getInfo();
    }
}
```

実行結果

```bash
$ java Myapp

クラスイニシャライザー実行
↓
0回インスタンス化されました
↓
インスタンスイニシャライザー実行
↓
コンストラクター実行
↓
1回インスタンス化されました
↓
インスタンスイニシャライザー実行
↓
コンストラクター実行
↓
2回インスタンス化されました
↓
```
Debian 9 に MariaDB 10.4 をインストール

MariaDB 公式にあるように、Debian 9 から MariaDB 10.1 がデフォルトの RDBMS になりました。

[Moving from MySQL to MariaDB in Debian 9](https://mariadb.com/kb/en/library/moving-from-mysql-to-mariadb-in-debian-9/)

今回は MariaDB Corporation(mariadb.com)のレポジトリから 10.4 をインストールします。

# 標準の MariaDB 10.1 を削除

標準の MariaDB 10.1 がインストールされているのであれば、削除しておきます。

```
apt-get remove mariadb*
```

# MariaDB 公式レポジトリを登録

次に 10.4 レポジトリを登録します。

```
apt-get install software-properties-common dirmngr
curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash
```

/etc/apt/sources.list.d/mariadb.list がレポジトリが設定されます。異なるバージョンの MariaDB Server をインストールする場合は，バージョン番号(10.4)を変更します。 

```/etc/apt/sources.list.d/mariadb.list
# MariaDB Server
deb http://downloads.mariadb.com/MariaDB/mariadb-10.4/repo/debian stretch main

# MariaDB MaxScale
deb http://downloads.mariadb.com/MaxScale/2.3/debian stretch main

# MariaDB Tools
deb http://downloads.mariadb.com/Tools/debian stretch main
```




# MariaDB 10.4 をインストール

```
apt-get update
apt-get install mariadb-server
```

systemctl で MariaDB サーバを起動します。

```
systemctl enable mariadb
systemctl start  mariadb
```

root ユーザで MariaDB monitor(mariadbコマンド)を実行すると，MariaDB サーバに接続できました。

```
#  mariadb
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 10
Server version: 10.4.8-MariaDB-1:10.4.8+maria~stretch-log mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> 
```
自作ゲームでWebAssemblyを試してみた

# はじめに
私はEmscriptenを使って趣味でゲームを作っています。
WebAssemblyは興味はあったのですが、難しそうでかつあまり意味がないと思っていたのですが、思ったより簡単で明確な違いが数値で現れました。

# やったこと
過去作に`emcc`にコンパイルオプションをつけて`emcc -s WASM=1`にしました。

# 結果比較1 ホッピンパペット

[ホッピンパペット](http://totetero.com/project/hoppingpuppet/index.html)([git](https://github.com/totetero/hopping_puppet))

普通にビルドしたらファイルサイズは以下のようになりました。

| emcc | .js |
| :--- | ---: |
| 最適化無し | 2045027 |
| -O3 | 473131 |
| -Os | 394081 |
| -Oz | 391771 |

一方WebAssemblyオプションをつけてビルドしたらファイルサイズは以下のようになりました。

| emcc -s WASM=1 | .js | .wasm | 通常ビルドとの比較 |
| :--- | ---: | ---: | ---: |
| 最適化無し | 246537 | 451004 | 34% |
| -O3 | 128515 | 247115 | 79% |
| -Os | 128515 | 196081 | 82% |
| -Oz | 128515 | 194180 | 82% |

# 結果比較2 グルリンダッシュ

[グルリンダッシュ](http://gururin-dash.appspot.com)([git](https://github.com/totetero/gururin2))

普通にビルドしたらファイルサイズは以下のようになりました。

| emcc | .js |
| :--- | ---: |
| 最適化無し | 2117354 |
| -O3 | 487930 |
| -Os | 445771 |
| -Oz | 442939 |

一方WebAssemblyオプションをつけてビルドしたらファイルサイズは以下のようになりました。

| emcc -s WASM=1 | .js | .wasm | 通常ビルドとの比較 |
| :--- | ---: | ---: | ---: |
| 最適化無し | 258114 | 452756 | 34% |
| -O3 | 136099 | 240600 | 77% |
| -Os | 136099 | 203777 | 76% |
| -Oz | 136099 | 201701 | 76% |

# ファイルサイズが減った

WebAssembly化することにより2割ほどファイルサイズが減りました。
最適化無しの場合にものすごくファイルサイズが減っているのは改行やコメントなどの余計なコードの影響なのでしょうか。

# 速度はどうか
小規模なゲームでもともと速度も重くなく、比較のしようがありません。
ゲームの場合は描画が処理のボトルネックになることが多く、
行列演算を多用しない場合は速度的なメリットはなさそうです。

# 最後に
特に手こずることもなく、目に見えてファイルサイズが減りました。
最新のブラウザであればWebAssemblyに対応しているそうなのでこれからは使っていきたいと思います。
上記リンクを貼っている私のサイトで、それぞれのコンパイルオプションでビルドしたものを公開しています。触っていただけるとありがたいです。
【超初学者向け】近所の小学生のために九九勉強アプリをつくろう


※この記事は「FizzBuzz・・・聞いたことあるけどよくわからんぞ」「とりあえず繰り返しとかifとかはなんとなくやったやで」「プロゲートの初級編は一応一周したけど自信全く無いやで」というあたりのガチ初学者向けです。

***



こんにちは。以前も初学者の分際で初学者向け記事を書きましたが、大器晩成型なのでまた初学者向けの記事を書いています。


せっかくプログラミングを始めたなら、やっぱ人の役に立ちたい！日本社会の発展に貢献したい！



ということで九九の勉強に四苦八苦してる子のために超シンプルプル九九勉強アプリケーションを作りました。

***


```kuku.rb
puts "九九のおべんきょうをはじめよー！！"
puts "一桁の掛け算の問題を10問出すよ"
puts "答えの数字を入力してエンターキーを押してね！"
puts "じゃあいくよー！"
sleep(0.5)
puts "3"
sleep(1)
puts "2"
sleep(1)
puts "1"
sleep(1)

count = 0
wrong_questions = Array.new
10.times do
  x = rand(9) + 1
  y = rand(9) + 1
  puts "#{x} ×  #{y} = "
  user_answer = gets.chomp.to_i
  true_answer = x*y

  if user_answer == true_answer
    puts "正解！"
    count += 1
    puts ""
  else
    puts "ちがうよ！"
    puts "正解は#{true_answer}"
    wrong_questions << [x, y, true_answer]
    puts ""
  end
end

puts "おつかれさまー！"
puts ""
puts "正解数：#{count}"
puts "間違えた問題は・・・"
if count == 10
  puts "なし！全問正解！すごい！！天才！！！！！！"
else
  wrong_questions.each do |w|
    puts "#{w[0]} ×  #{w[1]} = #{w[2]}"
  end
end
```



できる人から見たらこれをアプリと呼ぶのか・・？というレベルだと思いますが、勉強始めたてのころの僕が見たらわけがわからなさすぎて白目むく程度には複雑だと思うので簡単に解説していきます！

***

【解説】


流れとしては
①1~9からランダムに数字を一つ選んで、`x`と`y`とする
②内部で`x × y`を計算して、答えを`true_answer`とする
③ユーザーが入力した数字を`user_answer`として、`user_answer`と`true_answer`が一致しているかを確認する
④一致してたら正解とし、`count` を１増やす。この`count`が最後にそのまま正解数になる
⑤一致してなかったらその時の`x`と`y`と`true_answer`を配列`wrong_questions`に追加、つまり保存して、最初に戻る
⑥10回繰り返したらループが終わり、正解数`count`を表示。全問正解ならそのまま終わり、間違えていたら`wrond_questions`に値が残ってるのでそれを九九の問題になるように表示

こんな感じです。

***

`10.times do`
これは「10回以下の内容を繰り返してね」というコマンドです。使いやすいのでサクッとググったら覚えちゃいましょう。

```
  x = rand(9) + 1
  y = rand(9) + 1
```
ここでは「0~8からランダムな数字をひとつ得る」という`rand()`に1を足すことで、「1~9からランダムな数字をひとつ得る」ようにしています。


`answer = gets.chomp.to_i`
これは「ユーザーから入力（標準入力）を受け付ける」という`gets.chomp`に、得た値をinteger（整数型）に変換するという`to_i`をくっつけたものです。
ユーザーから整数の入力を受付ける時のテンプレです。詳しくはググれば出てくると思いますが、この部分は全体のロジックには全然関わらないので、まずは「こういうもの」と覚えてしまった方がいいと思います。

***

```
if user_answer == true_answer
    puts "正解！"
    count += 1
    puts ""
  else
    puts "ちがうよ！"
    puts "正解は#{x*y}"
    wrong_questions << [x, y, true_answer]
    puts ""
  end
```

ここが九九アプリのキモになっている部分、つまり「答えが合ってるか否かの判断」と「正解数のカウント」と「間違えた問題の保存」をやってます。

まず
`if user_answer == true_answer`
で一致しているかを確認し・・・

もし一致してる、つまりユーザーの入力が合ってたら
"正解！"と表示し、`count`を１増やします。
この`count`はこのループの外側にあるので、この`10.times do`のループが最初に戻っても`count`はリセットされません。
こうやって「正解数」を`count`という変数に「保存」と言えます。


また、`wrong_questions`も同じです。間違えた問題のx, y, true_answerの組み合わせを、ループの外側にある配列`wrong_questinos`に入れておくことで「保存」してます。


***

あとは、ループが終わったら正解数`count`をそのまま表示し、`wrong_questions`に保存されている間違えた問題をいい感じに表示するだけです。



`wrond_questions`は二重配列で入っています。
例えば`2 x 3 = 6`という問題と`5 x 8 = 40`という問題を間違えたならば
`wrong_questions = [[2, 3, 6], [5, 8, 40]]`という形で入っているはずです。

これを順番に取り出していきたいので・・・
`wrong_questions.each do |w|`
とすることで「配列から配列を順番に取り出して」、wに入れています。
x, y, true_answerの順番は決まっているので、あとは普通に配列から取り出すように
`x = w[0]``y = w[1]``true_answer = w[2]`
として表示していくだけです。

***


以上です！Qiitaはデキるプログラマの方が多いので、ほんとうに初学者向けの記事が少ないように感じます。
僕も詰まったことがあるし、ほんとうに初学者の人が詰まりそうなところを解説できれば・・・！と思って書きました。

ではでは、ちょうど春休みですし、さっそく九九アプリを作って近所の小学生相手にイキり倒し、ご近所の算数力向上に貢献しましょう！！！！！！！