OmniAICreator/Qiita-1.07M huggingface dataset:
Railsチュートリアル 14章 FactoryBotでRelationshipのテストデータの作成

#はじめに
Railsチュートリアルをrspecに対応させながら取り組んでいたところ、14.2.3のリスト14.28のユーザのRelationshipテストデータをFactoryBotで作ろうとしたときにハマってしまったので、備忘録として投稿します。

#環境
- ruby 2.7.2
- rails 6.0.3
- factory_bot_rails 6.1.0
- rspec-rails 4.0.1

#やりたいこと
①下記ようにrelationshipのテストデータを作成するfixtureをFactoryBotで定義する。
②userのテストデータも同時にFactoryBotの定義内で作成する。

```ruby:test/fixtures/relationships.yml(リスト14.28)
one:
  follower: michael
  followed: lana

two:
  follower: michael
  followed: malory

three:
  follower: lana
  followed: michael

four:
  follower: archer
  followed: michael
```

#解決方法
試してみて、採用した解決方法を記載します。

##その1 Relationshipのテストデータを作成するFactoryを定義（①のみ解決）
一番素直な方法です。follower_idとfollowed_idを持つRelationshipクラスのファクトリーを作成します。ただ、この方法でassociationをうまく設定することができなかったので、userのテストデータを別途作成しました。

```ruby:spec/factories/relationships.rb
 factory :relationship, class: Relationship do
    follower_id { follower.id }
    followed_id { followed.id }
  end
```
```ruby:spec/models/relationship_spec.rb
RSpec.describe Relationship, type: :model do
  let(:follower) { create(:user) }
  let(:followed) { create(:user) }
  let(:relationship) { create(:relationship, follower: follower, followed: followed) }

  it { expect(relationship).to be_valid }
end
```

##その2 Relationshipを持つuserのテストデータを作成するFactoryBotを定義（①②の両方解決?）
2つめの方法は、Relationshipを持つuserのテストデータを作成する方法です。userのテストデータはすべてのテストでRelationshipを持っている必要はないので、traitで必要に応じて設定できるようにしています。この方法だと、userとrelationshipのテストデータをそれぞれ作成しなくても良くなりました。しかし、この方法はあくまでuserのテストデータを作成する方法で、relationshipを呼び出すにはuserを通す必要があるので、relationshipのテストには向いていなさそうです。

```ruby:spec/factories/users.rb
factory :user do
  .
  .
  .
  trait :has_followed do
    after(:create) do |user|
      followed = create(:user)
      user.follow(followed) 
    end
  end
end
```
```ruby:spec/models/relationship_spec.rb
RSpec.describe Relationship, type: :model do
  let(:user) { create(:user, :has_followed) }

  it { expect(user.actve_relationships).to be_valid }
end
```

#終わりに
結局①②を完全に達成する解決方法を見つけられなかったので、relationshipのテストはその1の方法で、relationshipを持つuserのテストはその２で書くことにしました。

#参考文献
- [FactoryBot(FactoryGirl)チートシート](https://qiita.com/morrr/items/f1d3ac46b029ccddd017#%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E3%82%92%E5%8F%97%E3%81%91%E3%82%8B)
- [factory_botでhas_many throughアソシエーションを作成](https://qiita.com/takehanKosuke/items/ae324483e7f9451bf6a7)
- [FactoryBotを使う時に覚えておきたい、たった5つのこと](https://qiita.com/piggydev/items/32717b6c382272e2134e#%E4%BE%8B-2-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E5%85%88%E3%81%AE%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E4%BD%9C%E3%82%8B)
JavaScript　DOM操作による要素へのアクセス

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/a7894647-b397-3eb7-cc05-0df7b4a63d2c.png" width="300">

#class属性、セレクタで要素にアクセスする
>class="weather"

```html:index.html
    <!DOCTYPE html>
    <html lang="ja">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>

    <body>
        <h1>JavaScript Practice</h1>
        <dl>
            <dt>今日の天気</dt>
            <dd class="weather">晴れ</dd>
        </dl>
        <script src="index.js"></script>
    </body>

    </html>
```

#1,class属性やセレクタで要素を取得する
>**document.querySelector("クラス名");**

```javascript:index.js
    // querySelectorでweatherのクラスがついている要素を取得
    let element1 = document.querySelector(".weather");
    console.log(element1);

    // querySelectorでdlセレクタ要素を取得
    let element2 = document.querySelector("dl");
    console.log(element2);

    // DOMのツリー構造を踏まえて指定が可能
    let element3 = document.querySelector("dl dt");
    console.log(element3);
```

#2,コンソール表示結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/a72d3586-d47f-9cb9-d01a-ce5f9fd6b5a6.png" width="600">

#3,主な要素取得メソッド
```javascript:index.js
    // 主な要素取得メソッド
    document.getElementById("引数");           //id名
    document.getElementsByClassName("引数");   //class名
    document.getElementsByTagName("引数");     //要素名
    document.getElementsByName("引数");        //name属性
    document.querySelector("引数");            //セレクタ
    document.querySelectorAll("引数");         //セレクタ
```
rubyでapplication/pdfのレスポンスをFileで扱う

httpレスポンスがapplication/pdfだったときとかの対応


```ruby

resp = http_client.get url
resp.headers["content-type"]
# => "application/pdf"

# シンプルに書き込めばok
file = File.open("path/to/pdf", "wb") do |f|
  f.puts resp.body
end
```

```bash
$ file path/to/pdf
# path/to/pdf: PDF document, version 1.4
```
HTTPレスポンスステータスコード メモ

調べてメモ

##HTTPレスポンスステータスコードとは
特定の**HTTPリクエスト**が正常に完了したどうかを示す

Googleの検証ツールでも見ることができる

###検証ツールでみてみる
![B9D02B9C-AFE0-491E-ADED-9D2D8ACA56F4.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431899/4b14d60e-62d9-255a-5eae-4cf3df4460d2.jpeg)
①…Network
②…それぞれのファイル
③Headersの中にある**Status Code**

##大まかな部類

大体の分類でわけていく

###100番台	
**続きの情報**があることを伝える。

例)
100 ( Continue )
続きの情報があるのでリクエストして！

### 200番台	
**成功**
Webサーバがリクエストに処理できたことを伝える。

例)
200 ( OK )
リクエストを無事に処理

###300番台	
**リダイレクト**
別のURLへリクエストし直すように要求する。

例)
301 ( Moved Permanently )

### 400番台	
**クライアントエラー**
**クライアントのリクエスト**に問題があり処理できなかった事を伝える

例)
404 ( Not Found )
指定したURLのデータは存在しない

### 500番台	
**サーバエラー**
**サーバ側に問題**があり処理できなかったことを伝える

例)
503 ( Service Unavailable )
サーバの負荷が高くて処理できない


##参考記事
https://developer.mozilla.org/ja/docs/Web/HTTP/Status
https://www.infraexpert.com/study/tcpip16.html
Rubyのネイティブ拡張でメソッド呼び出しをキャッシュさせる簡単な方法

## 概要

[RustのHashMapをRubyから使えるようにしてみたが……](https://qiita.com/irxground/items/16be01872ee88acec013) の続きです。

前回、以下のように書いた。

> ハッシュ値を取得するのに、Rubyのメソッドが動的に呼び出され、Rustのhash関数も実行されている。
さらに Eqの時もRubyのメソッドが動的に呼び出されている。
Rubyからメソッド呼び出しする場合は普通はメソッドをキャッシュしておくので次の呼び出しは速くなるが、CやRustから呼ばれる場合は毎回メソッドテーブルから探しに行く必要があって、とても遅い。

今回、メソッドをキャッシュさせることで find, insert, delete が速くなることを確認できた。

## 結果

before:

```
$ ruby benchmark.rb --rust --seed 1
Hash: Rust
Seed: 1
       user     system      total        real
values  1.896433   0.152249   2.048682 (  2.049503)
keys    1.589012   0.118299   1.707311 (  1.708012)
find   11.612382   0.002426  11.614808 ( 11.617854)
insert 15.397090   0.012138  15.409228 ( 15.413532)
delete  7.581418   0.001750   7.583168 (  7.585473)
```

after:

```
$ ruby benchmark.rb --rust --seed 1
Hash: Rust
Seed: 1
       user     system      total        real
values  1.924479   0.166750   2.091229 (  2.092445)
keys    1.514441   0.112787   1.627228 (  1.628187)
find    8.677083   0.001990   8.679073 (  8.681669)
insert 12.661791   0.010463  12.672254 ( 12.678383)
delete  5.908580   0.001670   5.910250 (  5.912530)
```

insertは標準のHashクラスより37%も速くなっている。やったね

## やったこと

これまで、hash関数は以下のように実装していた。

```rust
    fn hash<H: Hasher>(&self, state: &mut H) {
        let val = ruby::fun_call(self.0, "hash", &[]);
        val.to_raw().hash(state);
    }
```

Rustから呼び出すと毎回テーブルを引く必要があるが、Rubyから呼び出せばいい感じにキャッシュされる。
つまりRubyを経由して呼び出せばよい。というわけで

```rust
pub static mut M_HASH: Value = NIL;
// ...
    let sym_hash = module_eval(klass, "def self.value_hash(val); val.hash; end");
    M_HASH = obj_method_by_symbol(klass, sym_hash);
```
`eval` を作ってRubyの関数を定義する。

```rust
    fn hash<H: Hasher>(&self, state: &mut H) {
        let method = unsafe { crate::hashmap::M_HASH };
        let val = ruby::method_call(method, &[self.0]);
        val.to_raw().hash(state);
    }
```
hash関数では、インスタンスメソッドを呼ぶ代わりにこのキャッシュされた `Method` 呼び出しを行う。

```rust
extern "C" fn mark(ptr: *const ffi::c_void) {
   gc_mark(unsafe { M_HASH });
```
この `Method` のインスタンスがGCで回収されないように注意（これが原因で時々SEGVが出てデバッグが辛かった）
表層解析入門


# 表層解析

# サマリ（目的／ツール、コマンド類／アウトプットデータ）
- ファイル形式の特定／PPEE（Win）、pestudio（Win）、trid（Win）、file（Linux）／OS、アーキテクチャ
- ハッシュ値の取得／PPEE（Win）、pestudio（Win）、sha1sum（Linux）、ssdeep（Linux）／インジケータ
- 文字列の抽出・難読化検出／Exeinfo PE（Win）、Detect It Easy（Win）、FLOSS（Linux）、strings（Linux）／インジケータ
- PE解析／Resource Hacker（Win）／プログラムの挙動、内蔵されたコンテンツ

# 表層解析とは
解析対象となるプログラムを実行せずに情報を得る方法。
ハッシュ値やメタデータなどを取得でき短時間で情報を得られるため初動として表層解析を行い、
詳細な解析を行う上での方向性やインシデントレスポンスとしての一時措置の方針決定などの根拠として活用することができる。

# ファイル形式（実行環境OS／アーキテクチャ）の特定
ファイルのヘッダに書き込まれているマジックナンバー／シグネチャ（ファイルシグネチャ）から
ファイルの実行環境OSやアーキテクチャを特定する。

# ハッシュ値の取得
ファイル全体をハッシュ関数を用いてハッシュ値を取得する。得られたハッシュ値は
様々なソフトウェアやツールへの情報展開が容易となり、インジケータとなる。
また、インジケータとしてオンライン上から有益な情報を探すキーワードとなる。

## 類似性を用いた解析
現実的には、マルウェアはインジケータ部分が日々変化するためハッシュ値を
インジゲータとして有効活用できるライフタイムは短い。よって類似性を定量的に
算出する解析手法が有効となっている。

- ファジーハッシュ（fuzzy Hashing）
コンテンツ内のデータを対象に類似度を算出する。
算出された値は類似度が高いほど算出されたハッシュ値の文字や文字の並びが近くなる。
ファジーハッシュは概念であり、具体的な手法はツール等により違いがある。

- インポートハッシュ（Import Hash）
PEのインポート関数とその順序性からハッシュ値として算出する。
同一のマルウェアであり接続先などのみ変化している場合、類似性を算出する有効的な手段となる。
しかしながら機能追加された場合はハッシュ値が異なる特性がある。

- セクションハッシュ（Section Hash）
PEヘッダの各セクションを対象にハッシュ値を算出する手法。

- impfuzzy
インポート関数のテーブルを対象にファジーハッシュで算出する手法。
機能追加や一部変更程度にも対応できる手法であり、類似度が近くなる。
マルウェアファミリー、亜種などに対応できることが期待できる。

# 文字列の抽出
プログラムの動作に関する文字列やインジケータとなる情報を取得できる。
コーディングプログラムはASCII以外にもUnicodeを利用していることが多いため
両方を対象にデータを取得する必要がある。

FLOSS(FireEye Labs Obfuscated String Solver)を用いることにより
容易にデコードし結果を確認できる。

## 難読化対策
解析妨害を目的に難読化されていることが多い。難読化されたファイルをデコードする
手段としては、難読化方法を特定し最適な手段を選択する必要がある。
大きくパッカーやクリプターを用いた難読化が代表的である。
Exeinfo PEを用いることにより難読化方式などを容易に検出することができる。

パッカーはプログラムを圧縮することによりコンテンツの難読化を行う。
パッキングされたプログラムに解凍モジュールが同梱されており、モジュールを利用して
圧縮されたコンテンツをメモリ上に展開し、もとの実行形式に復元する。
パッカーとして有名なのはUPX形式である。

クリプターはコンテンツを暗号化し難読化を行う。
暗号化されたプログラムに復号モジュールが同梱されており、モジュールを利用して
暗号化されたコンテンツをメモリ上に展開し、もとの実行形式に復元する。

# PE解析
Windowsの実行ファイル形式であるPEファイル形式はコンパイル時にヘッダ領域に
参照するライブラリや関数、リソースなど様々な情報を付与されるため、ヘッダから
プログラムの挙動など重要な情報を取得することが可能。
通常のプログラムは難読化されることがないため、呼び出すAPIの数があまりにも
少ない場合は難読化されている可能性が高い。

また、リソース領域にはプログラムに内蔵された別のファイルなどを取得することも可能である。
Resource Hackerを用いることにより内蔵されたファイルを抽出することが可能である。
アドベントカレンダー25日目：SREを読んでみた「単純さ」編②

前回からの続きになります。前回は、単純さ
そして、特定の問題を回避することによって、本当に重要な問題に集中することができるようになります。

## 削除した行の計測
どのようなコードにおいても、何かしらの機能を追加するということは、そこに潜在的なバグを含む可能性があります。機能を追加するとなったときは、一度懐疑的になり、今のコードで無駄なコードや障害を生む可能性があるコードを削除するべきです。

## 最小限のAPI
わかりやすい最小限のAPIを書くことは、ソフトウェアが単純であるためには欠かせない要素です。
APIが小さく単純であることは、特定の問題が十分に理解されている証明になります。

## モジュラー性
モジュラー性を保つことは、システムの一部を独立して変更するためには欠かせません。コードやバイナリ、その設定を疎結合にすることで、開発のアジリティと安定性を同時に高まります。
また、APIの変更のやり方自体にモジュール性の考えを使うこともできます。
APIを一つ変更しただけでシステム全体の再ビルドが必要な状態は望ましくありません。APIにバージョンを与えることで、自分のシステムに依存しているバージョンを使うことができます。これによりシステムは安定に稼働することができます。APIのリリースはバージョンごとに異なっていても良く、またプロダクション環境への機能追加も一度に行う必要がなくなります。

## リリースの単純さ
リリースは単一のリリースを繰り返す方が優れています。
それは、仮に複数の変更を含んだリリースを行うと、もし問題が生じたときに影響範囲を特定することが難しくなるからです。
そのため、小さい単位でリリースすることにより、それがパフォーマンスにどのような影響をあたえたのかの理解がしやすくなります。

## まとめ
* 複雑はバグを生む可能性がある。
* 必要な複雑さに焦点を当てる。不必要な複雑さは回避する。
* 単純さを保つ。そのためにやり割り範囲を明確にしたものを疎結合する。

#### 参考文献
1. Betsy Seyerほか　SRE サイトリライアビリティエンジニアリング　オライリー　103-105
自作キーボード7 基盤はんだ付け

今日、Amazonで注文していた[キースイッチ](https://amzn.to/2X16d2R)が届いた。
![IMG_20201227_080641.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135714/83645a07-6c6b-42c6-75e8-f27184d5dbec.jpeg)

最終的にスイッチと、キーキャップをElecrowから届いた基盤に乗せピッチ幅が問題ないかチェックしOK！
ということでいよいよ基盤にはんだ付けしていく。

# ダイオード、抵抗の配線
マスキングテープで固定し、[ダイオード](https://amzn.to/3hn8tKN)と[抵抗](https://amzn.to/38ERBvm)をElecrowから届いた基盤に全部付けた。挿すだけなので簡単だが数が多いので指で一個ずつ曲げながら、1時間はかかった。

![IMG_20201226_120738.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135714/f1c84d87-59c7-f51e-de94-a517ae5a897a.jpeg)

# はんだづけ
初めてのプリント基板への基板はんだ付け作業だったが、うまくできたが、ニッパーが安物過ぎて大きすぎて綺麗に切れない。

![IMG_20201226_132922.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135714/f6b12a67-9e63-a9ed-c945-a97ccba6dd72.jpeg)

写真を見て気づいたが、はんだが飛び散ってて汚い。。

# 表から見るとこんな感じ
![IMG_20201226_132933.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135714/e6e2cf28-508f-ed4e-bb31-bc1f3cf81771.jpeg)

抵抗の横幅が大きくて、プリント基板のサイズが合ってない。
次回に備えてKicadの図面を修正しておく。

# 問題発生
写真に撮り忘れたが、マイコンボードの取り付け向きを間違って、全部のピンをはんだ付けしてしまい、取り外すのに1日かかった。
結局はんだ吸い取り線ではうまく吸い取れず、DIYセンターでヒートガンを購入(5990円もした）し予定外の出費。
ヒートガン一発で取れたのだけど、ピンヘッダーも一緒に溶けてしまった。

即Amazonで[ピンヘッダー発注](https://amzn.to/3hpFlTh)

熱をマイコン本体に加えたのでElite-CにUSBを挿してもLEDが光らなくなった。まあ使えるから無視。

右側用にもう一つ買ってたElite-Cを使って、もう一度基盤につける。
最初に作った基盤は、はんだはがしで汚くなってしまったので捨てる。
幸いElecrowから届いた基盤は5枚あるので、1枚失敗しても問題ない。

# 入力テスト
今度は間違えずに、取り付け終わり、いよいよPCにつないで入力できるかテスト！

![IMG_20201227_203931.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135714/75dfe26e-93d1-1998-4da8-c9099b888410.jpeg)

どや！？

![初めてのキー入力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135714/4aa6fe32-e528-c40e-a8e0-3f3cc7a977d9.png)

出たーーーーーーー。地味だけど出たーーーーーーー。
久しぶりの達成感、満足感。

満足満足。


[ピンヘッダー](https://amzn.to/3hpFlTh)がAmazonから届くまで、右側の基盤を組み立てられないが、
とりあえず配線だけ準備しておく。はんだ付けは次の休みにやって左右を4極イヤホンジャックでつないでちゃんと左右で
入力できるかチェックする。

![IMG_20201227_222943.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135714/47cd871f-9ab1-b8e6-108e-0029984c4514.jpeg)


<br><br>
<td><font size="6">
Amazon商品へのリンクは「Amazon.co.jpアソシエイト」を使用しています。
「Amazon.co.jpアソシエイト」とは、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイトプログラムである、Amazonアソシエイト・プログラムの参加者です。
</font>
</td>
slackにGo言語で、postする

# はじめに

外部ライブラリを使用しないで、Slackに投稿する方法が気になったので、自分で組んでみた。
Slackの設定は、`Bot Token Scopes`で`chat:write`と`files:write`を有効にする。
そして投稿したいチャンネルにアプリ許可を出しておくこと
test.pngという名の画像ファイルをあらかじめ用意しておくこと

# ソースについて

```go:main.go
package main

import (
	"bytes"
	"context"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"time"
)

const (
	SLACKPOSTMESSAGE = "https://slack.com/api/chat.postMessage"
	SLACKPOSTFILE    = "https://slack.com/api/files.upload"
	TOKEN            = "{表示されたトークンを記載}"
	CHANNEL          = "general"
)

}

func postSlackfile() string {
	filename := "./test.png"
	file, err := os.Open(filename)
	if err != nil {
		return ""
	}
	defer file.Close()
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)
	part, err := writer.CreateFormFile("file", filepath.Base(filename))
	if err != nil {
		return ""
	}
	_, err = io.Copy(part, file)
	if err != nil {
		return ""
	}
	err = writer.Close()
	if err != nil {
		return ""
	}

	values := url.Values{
		"token": {TOKEN},
	}
	values.Add("channels", CHANNEL)
	values.Add("filename", filepath.Base(filename))

	req, err := http.NewRequest("POST", SLACKPOSTFILE, body)
	if err != nil {
		return ""
	}
	req = req.WithContext(context.Background())
	req.URL.RawQuery = (values).Encode()
	req.Header.Add("Content-Type", writer.FormDataContentType())

	client := &http.Client{}
	// client.Timeout = time.Second * 15
	resp, err := client.Do(req)
	if err != nil {
		return ""
	}
	defer resp.Body.Close()
	body2, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return ""
	}
	return string(body2)
}

func postSlackMessage(text string) string {
	urldata := SLACKPOSTMESSAGE
	values := url.Values{}
	values.Set("token", TOKEN)
	values.Add("channel", CHANNEL)
	values.Add("text", text)

	client := &http.Client{}
	client.Timeout = time.Second * 15
	req, err := http.NewRequest("POST", urldata, strings.NewReader(values.Encode()))
	if err != nil {
		return ""
	}
	//
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	resp, err := client.Do(req)
	if err != nil {
		return ""
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return ""
	}
	return string(body)

}

func main(){
	fmt.Println(postSlackMessage("Hello World\nbbb"))
	fmt.Println(postSlackfile())
}

```
# 結果
実行すると以下の通り投稿される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425374/f68205a5-a59d-b8d2-b92e-c189659e50d7.png)


# 余談
以下のリンクのライブラリを使用するともっと簡単にできるけど、機能を確認することや理解ならば、上のソースコードだけのほうが楽かな

https://github.com/nlopes/slack
ページネーション【Vue.js/Vuetify】

#概要
・　ポートフォリオでページネーション機能を実装したので、コメントつきのソースコードを紹介
・　使用した技術はRealtimeDatabase（Firebase）とVuetify（Vue.js）
　　※ v-pagenation のページは　https://vuetifyjs.com/ja/components/paginations/
・　api経由でデータを取得し、ページネーション付きで表示する
・　開発環境はVue-Cli


```csharp:template
<v-layout>
     <v-flex>
          <v-pagination
                  v-model="currentPage"
                  :length="getPageCount">
          </v-pagination>
     </v-flex>
</v-layout>
<v-layout v-for="list in getLists" :key="list.message">
//以下省略
</v-layout>
```
:length は画面に表示できる最大限のページ数のこと。

```csharp:script
data(){
      return {
         input: '',
         parPage:3, //1ページごとに表示されるリスト数
         currentPage:1 //画面を開いた時に最初にあなたがいるページの場所
      }
    },
computed(){
  lists(){//　表示するリストのデータ
     return this.$store.state.lists
    },
  getLists(){// 表示するリストを１ページ３つにする
      let current = this.currentPage * this.parPage //全ページlistの合計数
      let start = current - this.parPage //1ページ目のlistの数
      return this.lists.slice(start, current) //リストの何番目〜何番目を今のページに表示するか
     },
  getPageCount(){
         //引数として与えた数以上の最小の整数を返す
         //ページ数になって、上の:lengthに当てはめる
       return Math.ceil(this.lists.length / this.parPage)
     }
},
watch:{
   search(){//1ページ目以外のページにいる状態で検索欄に文字入力すると、１ページ目に戻って検索
     this.currentPage = 1
  }
}

```
太陽光発電の発電量をロギングしてみた。

防災用に携行用の太陽光パネルとポータブル電源を購入。
発電特性を可視化したいと思い、いろいろ取り組んでみた。
最終的にはロギングしたデータをSalesforceにリアルタイムにアップロードし、出先からインターネットで確認できるようになった。
その経緯をまとめてみた。

[1. 電気系統の配線](https://qiita.com/takoyakiya/items/aa95143a9b832a494547)
[2. Microbitで電流・電圧測定(INA260使用)](https://qiita.com/takoyakiya/items/4bc01244786116e1b93f)
[3. Microbit間無線通信とRaspberryPi-Microbit間シリアル通信で、測定値をロギング](https://qiita.com/takoyakiya/items/009ab91425be97121c94)
[4. Salesforseでリアルタイム監視](https://qiita.com/takoyakiya/items/7adbf0282b9ce9051bb7)
5. [温度の計測(DS18B20) ＆ RaspberryPiで電流・電圧・温度をロギング](https://qiita.com/takoyakiya/items/fba82384d778d0194ed4)
6. [Salesforceの容量不足に困ったら・・・BigObjectの活用](https://qiita.com/takoyakiya/items/43e392ab423f78eb31a8)
7. [発電異常をLINEで通知](https://qiita.com/takoyakiya/items/ccb293ea15bdd47ae1d2)
ActiveHashの導入〜用法

# ActiveHash
プルダウンなどの、変更されないデータをモデルファイル内に直接記述することで、データベースへ保存せずにデータを取り扱うことができるGemです。
Active_Hashを用いることで、モデルファイルに直接記述した変更されないデータに対して、ActiveRecordのようにメソッドを用いることができます。


# 導入方法
```言語:Gemfile
% gem 'active_hash'   # 最後に記述
```
```言語:ターミナル
% bundle install
```

# ActiveHashのモデル作成
```言語:ターミナル
% rails g model "モデル名" --skip-migration
```

` --skip-migration`は、モデルファイルを作成するときに、マイグレーションファイルの生成を行わないためのオプションです。
データベースに保存しない場合は、マイグレーションファイルを作成する必要はないのでスキップしましょう。

---

#用法(一例)
**商品出品の "カテゴリー" 欄を作成**
それでは今回必要なActiveHash用の "Categoryモデル" を作成します。

```言語:ターミナル
 % rails g model category --skip-migration

Running via Spring preloader in process 16065
      invoke  active_record
      create    app/models/category.rb
      invoke    rspec
      create      spec/models/category_spec.rb
      invoke      factory_bot
      create        spec/factories/categories.rb
```
目的のapp/models/category.rbが作成されました。
それに付随してrspec, factory_bot ファイルも作成されるようですね。
すぐにテストコードが書けるので有難い。

---
# プルダウン作成

次にプルダウンの内容をcategory.rbに記述していきます。
デフォルトの
class Category < ApplicationRecord という記述を
class Category < ActiveHash::Base に変更してください。

```category.rb
class Category < ActiveHash::Base
  self.data = [
    # 内容
  ]
end
```
その後
self.data = [　　]
内に、プルダウンとして表示させたい内容を記述していきます。

---

```category.rb
class Category < ActiveHash::Base
  self.data = [
    { id: 0,  name: '---' },
    { id: 1,  name: 'レディース' },
    { id: 2,  name: 'メンズ' },
    { id: 3,  name: 'ベビー・キッズ' },
    { id: 4,  name: 'インテリア・住まい・小物' },
    { id: 5,  name: '本・音楽・ゲーム' },
    { id: 6,  name: 'おもちゃ・ホビー・グッズ' },
    { id: 7,  name: '家電・スマホ・カメラ' },
    { id: 8,  name: 'スポーツ・レジャー' },
    { id: 9,  name: 'ハンドメイド' },
    { id: 10, name: 'その他' }
  ]
end
```

ActiveHash::Baseは、モデル（クラス内）でActiveHashを用いる際に必要となるクラスです。ActiveHashのGemに定義されています。
ActiveHash::Baseを継承することで、
`ActiveRecordと同じようなメソッドを使用できるようになります。`

今回の場合、Categoryモデルに定義したオブジェクト（Categoryのデータ）に対してActiveRecordのようなメソッドが使用できるようになります。




# ActiveHashでアソシエーションを設定する
アソシエーションを設定する場合には
ActiveHashで定義されているmoduleをモデルに取り込む必要があります。

では実際に、出品する商品とカテゴリー欄の関係を書き起こしていきます。

---
ActiveHashを用いて、belongs_toを設定するには、
`extend ActiveHash::Associations::ActiveRecordExtensions`と記述してmoduleを取り込みます。

```item.rb
class Item < ApplicationRecord
  # 省略
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :category
end
```
---
ActiveHashを用いて、has_manyを設定するには、
`include ActiveHash::Associations`と記述してmoduleを取り込みます。

```category.rb
class Category < ActiveHash::Base
  self.data = [
    { id: 0,  name: '---' },
    { id: 1,  name: 'レディース' },
    { id: 2,  name: 'メンズ' },
    { id: 3,  name: 'ベビー・キッズ' },
    { id: 4,  name: 'インテリア・住まい・小物' },
    { id: 5,  name: '本・音楽・ゲーム' },
    { id: 6,  name: 'おもちゃ・ホビー・グッズ' },
    { id: 7,  name: '家電・スマホ・カメラ' },
    { id: 8,  name: 'スポーツ・レジャー' },
    { id: 9, name: 'ハンドメイド' },
    { id: 10, name: 'その他' }
  ]

  include ActiveHash::Associations
  has_many :items
end
```
---
あとは、表示ができるようにMVCを設定すれば
"カテゴリー" 欄の完成。
リアルタイム検索【Vue.js/Vuetify/Vuex】

#概要
・　ポートフォリオでリアルタイム検索機能を実装したので、コメントつきのソースコードを紹介
・　使用した技術はVue.js,Vuetify,Vuex
　※ v-text-field のページは以下URL内にあり。
https://vuetifyjs.com/en/components/text-fields/#api
・　api経由でデータを取得し、ページネーション付きで表示する
・　開発環境はVue-Cli


```csharp:template
<v-layout>
  <v-flex>
　　　//入力フォーム
     <v-text-field
     label="検索する"
     v-model="search">
     </v-text-field>
   </v-flex>
</v-layout>
<v-layout v-for="list in getLists" :key="list.index">
//以下にcomputedの「getLists」がループされて表示される
</v-layout>
```

computed内では、stateから取得したリストをgetListsで自分が入力した内容とマッチするリストになるようにフィルタリング。
フィルタリングしたリストをv-forループで表示させる。

```csharp:script
data(){
 return : {
　　　//上記入力フォームの初期値
     search: "
  }
},
computed(){
  //stateの配列listsの中のオブジェクトから、キーtitleがv-modelで入力したsearchと一致するものだけ表示
  getLists(){
    const lists = this.$store.state.lists
      return lists.filter((list) => {
        return list.title.match(this.search)
     })
   }
}
```


```csharp:store(state)
lists:
[
    {
     id: "akdddgela22nad", 
     title: "FreeTalk in NewYork",
     date: "2017-09-29",
     location: "New York"}
    { 
     id: "akdbbraa5ffggg", 
     title: "FreeTalk in Paris",
     date: "2017-10-20",
     location: "Paris"
    }
//以下省略...
],
```

下記のように" || "を使用すれば、リストの中のあらゆるワードや数字を拾って検索も可能になる。

```csharp:script

return list.title.match(this.search) || list.date.match(this.search) || 
list.location.match(this.search) 
  

```
太陽光発電の発電量をロギングしてみた。(1)電気系統の配線

[【太陽光発電の発電量をロギングしてみた。目次】](https://qiita.com/takoyakiya/items/6b318ab83bcac86c966c)
## 電気系統の配線

私が購入した機器

太陽光パネル　　Hypowell　120Wソーラーパネル(折り畳み式)
ポータブル電源　PhewMan500 

この太陽光パネルには以下の出力端子がある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627239/85a274f4-a1be-d048-ee77-262f787efe17.png)

・USB×2(1つはQC3対応)
・USB Type-C ×1
・φ2.5DCジャック

太陽光パネルの付属ケーブルは以下の通り
・DC-DCケーブル（異なる径のDCジャックへの変換コネクタ10個付属）
・DC-アンダーソンケーブル
・DC-SAEクランプ（カーバッテリー用）

アンダーソンコネクタは、アウトドア用の電気機器等でよく使用されるそうである。

ポータブル電源の入力端子は　φ2.5DCジャックのみ。
また、ポータブル電源の付属ケーブルは以下の通り

| 付属ケーブル | 写真 |
|-------|------|
| DC-シガーソケット用充電ケーブル | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627239/6e54ca2e-3973-08cf-28c3-a3e389d3ee26.png" width="30%"> |
| DC-AC用電源コード | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627239/b57659e3-1d87-dda1-e6f1-db2c0c7581c1.png" width="30%"> |
| DC-MC4ケーブル | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627239/1848a5c1-3c6b-d2cf-d47e-a8b791b212b0.png" width="30%"> |


通常、この太陽光パネルとポータブル電源を接続するには、太陽光パネルに付属するDC-DCケーブルで接続する。

DC-DCケーブルは線が1本でシンプルなため、使い回ししやすいが、電流測定を行うには最低、MC4ケーブル等を用いてプラスとマイナスのケーブルを分岐する必要がある。
流れている電流値だけ単純に知りたい場合は、
太陽光パネル側にDC-MC4コネクタを別途購入してポータブル電源とMC4コネクタで接続し、非接触式のクランプメーターで測定すればよい。

しかし、今回、測定値のロギングを行いたいため、ケーブルを分岐させて装置側に接続する必要がある。太陽光パネルは意外と高電流が流れるため、配線の仕方を誤ると取り返しのつかないことになる。機器を破損したり、場合によっては火災にもつながるので注意が必要だ。
電気の知識に自信がない場合は手を出さないほうが無難である。


Amazonやヤフオクで、下記のアイテムをゲットして、電流の外出しを試みた。

| アイテム | 写真 | 備考 |
|-------|------|---|
| uxcell DC電源 5.5mm x 2.5mm 10A 18AWG 30 cm長さ バーレルオスプラグコネクタピグテール | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627239/996fb4d0-912f-e88a-b134-b2719a21313b.png" width="30%"> |    30cmのをAmazonで購入しましたが、ちょっと短い。ギボシ端子をくっつけてケーブルを延長しました。|
| MC4-棒端子ケーブル | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627239/03242838-1c71-ed15-9971-d667b74c7655.png" width="30%"> | ヤフオクで購入 |
| 端子台 極数3 |<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627239/153ae65e-c39e-3738-5843-95985df54f59.png" width="30%"> |   うちにあるの使いました。|
| ギボシ端子 | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627239/655c2d91-2cba-7785-d2bb-ba361e4228d9.png" width="20%"> |  ダイソーで売ってます |
| ケーブル(16AWG) || うちにあるのを使いました。 |

ケーブルやパーツを購入するときは、定格電流を確認する必要がある。
太陽光パネルの出力にもよるが、最大電流はパネルの最大電力をパネル端子の出力電圧で割れば算出できる。
ここで使用するパネルでは、DC端子の電圧が18̟±1Vなので17Vで計算すると、
$120 ÷ 17 ＝ 7.1$ (A)
である。
この電流値に20%～25%程度上乗せした値が定格電流値以内である必要がある。
定格電流の小さい部品やコードを使用すると、高電流に耐え切れなくなり、発熱して焼き切れたりする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627239/619616da-66ce-689d-20c2-479ad10be96b.png)

図1．配線図(端子台の取り付け)

ここまでできれば、端子台の反対側にデジタル電流計・電圧計を接続することができる。
ここでは、電流計を太陽光パネルマイナス側に取り付ける想定で配線している。

[【太陽光発電の発電量をロギングしてみた。目次】](https://qiita.com/takoyakiya/items/6b318ab83bcac86c966c)
javascriptの++iはi++より早いのか？

C言語やjavascriptなどのプログラミング言語にはインクリメント演算子がある。

インクリメント演算子は変数の数値を1加算する動作する。

```js
i++ // 後置インクリメント
++i // 前置インクリメント
```

インクリメント演算子には前置インクリメントと後置インクリメントがあり、違いは評価値が違うこと。
前置インクリメントは1加算したあとの値、後置インクリメントは1加算する前の値を評価値として返す。

### C言語では++iはi++より早い

C言語だと++iはi++よりパフォーマンスが良い。以下の記事が参考になる。

http://daria-sieben.hatenablog.com/entry/2015/08/21/212605

この記事によると++iはi++に比べて一時的な変数を使用しないため動作が早いようだ。

### jsでも検証してみた

検証コード↓

```js
const TIMES = 1000000;
let tmp = 0;
function test1() {
    for (let i = 0; i < TIMES ; ++i) {
        ++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;
        ++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;        
        ++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;        
        ++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;
        ++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;
        ++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;
        ++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;        
        ++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;        
        ++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;
        ++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;++tmp;
    }
}

function test2() {
    for (let i = 0; i < TIMES ; ++i) {
        tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;
        tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;
        tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;
        tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;
        tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;
        tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;
        tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;
        tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;
        tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;
        tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;tmp++;
    }
}

performance.mark('test1Begin');
test1();
performance.mark('test1End');

performance.mark('test2Begin');
test2();
performance.mark('test2End');

performance.measure(
    'test1',
    'test1Begin',
    'test1End'
);

performance.measure(
    'test2',
    'test2Begin',
    'test2End'
);

console.log(performance.getEntriesByName('test1')[0]);
console.log(performance.getEntriesByName('test2')[0]);
```

### 結果

++i: 169ms
i++: 169ms

ほぼ同じだったのでjavascriptでは前置後置のパフォーマンスの違いを意識しなくて良いようだ。
JavaScript　DOM操作でHTML要素を書き換える

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/7533369e-2ef6-9b36-2243-819d852dc5dc.png" width="300">

#＜dd＞タグにidが設定されているのでid名を指定して対象のHTML要素を書き換えます！

```html:index.html
　<!DOCTYPE html>
　<html lang="ja">

　<head>
    　<meta charset="UTF-8">
   　 <meta name="viewport" content="width=device-width, initial-scale=1.0">
    　<title>Document</title>
　</head>

　<body>
   　 <h1>JavaScript Practice</h1>
   　 <dl>
        　<dt>今日の天気</dt>
        　<dd id="weather">晴れ</dd>
    　</dl>
    　<script src="index.js"></script>
　</body>

　</html>
```

#１，要素を取得し書き換える
>**document.getElementById("id名");**

```javascript:index.js
// DOM操作でHTMLを書き換える
let element = document.getElementById("weather");

// innnerHTMLは記述したテキストもHTMLとして認識
element.innerHTML="<span>曇り</span>";

// textContentは記述したテキストを文字列として認識
element.textContent="<span>曇り</span>";
```
taichiのトリセツ① ~mp4とgifで出力~

## 経緯
[taichi](https://github.com/taichi-dev/taichi)に昨日からハマっているので、色々使ってみつつ、適宜情報を共有していこうと思います。今回は、作成したグラフィックをmp4またはgifとして出力するやり方を紹介します。詳しくは公式の[ドキュメント](https://taichi.readthedocs.io/en/stable/export_results.html#export-images)をご覧ください。taichiについての初めての記事は[こちら](https://qiita.com/Hiroaki-K4/items/e8cdb8c4e79c0d1a6670)です。

## ffmpegのインストール
動画を出力する際にtaichiはffmpegを使用するので、インストールしていない場合はインストールしてください。

```
$ sudo apt update
$ sudo apt -y upgrade
$ sudo apt install ffmpeg
```

## スクリプト
今回は試しにリポジトリのexamplesの中にあるfractal.pyの実行結果を、動画として出力してみます。コメントアウトの追加の下のブロックを、デフォルトのコードに追加しています。

```fractal.py
import taichi as ti

ti.init(arch=ti.gpu)

n = 320
pixels = ti.field(dtype=float, shape=(n * 2, n))


@ti.func
def complex_sqr(z):
    return ti.Vector([z[0]**2 - z[1]**2, z[1] * z[0] * 2])


@ti.kernel
def paint(t: float):
    for i, j in pixels:  # Parallized over all pixels
        c = ti.Vector([-0.8, ti.cos(t) * 0.2])
        z = ti.Vector([i / n - 1, j / n - 0.5]) * 2
        iterations = 0
        while z.norm() < 20 and iterations < 50:
            z = complex_sqr(z) + c
            iterations += 1
        pixels[i, j] = 1 - iterations * 0.02


gui = ti.GUI("Julia Set", res=(n * 2, n))
# 追加↓
result_dir = "./results"
video_manager = ti.VideoManager(output_dir=result_dir, framerate=24, automatic_build=False)

for i in range(100):
    paint(i * 0.03)
    # gui.set_image(pixels)
    # gui.show()
    # 追加↓
    pixels_img = pixels.to_numpy()
    video_manager.write_frame(pixels_img)
    print(f'\rFrame {i+1}/100 is recorded', end='')

# 追加↓
video_manager.make_video(gif=True, mp4=True)
print(f'MP4 video is saved to {video_manager.get_output_filename(".mp4")}')
print(f'GIF video is saved to {video_manager.get_output_filename(".gif")}')
```
デフォルトではgui表示されますが、今回はfor文の中のgui表示処理の代わりに、VideoManagerを使ってframeを動画にしていきます。上のプログラムを実行するとresultsフォルダの下にmp4とgifファイルが作成されます。gifはこんな感じになります。
![video.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/dc9c4744-5a97-826d-5a18-30a13f26026f.gif)

## まとめ 
taichiは何に使えるか全くわかりませんが、面白いので色々探検してみようと思います(笑)。

**間違いや質問、ご意見等ありましたらお気軽にコメントください。頑張って答えますので(笑)。**
Qiitaで記事書きながらスクリーンショットを効率よく貼る方法

# あらすじ

「**Qiitaで**」と書きましたが、汎用的に使えるようにまとめました。
誰かから「スクショってどうやる？」って聞かれたとき用の記事です。

この記事の目玉は最後の表です。
表にすると見やすいですね。
Win・Mac両対応です。

# Windows 10

昔からある方法では、`PrintScreen`で全画面スクリーンショットでした。また、ウィンドウごとにスクリーンショットを撮りたい時には、`Alt`+`PrintScreen`です。この方法だと、ウィンドウメニューとか右クリックメニューとか消えちゃって映らないんですよね。

モダンな方法は？というと`Win`+`Shift`+`s`です。このショートカットで「スケッチ & 切り取り」アプリが起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/dad99ea6-62f2-4e1a-a7c6-60ed05a6ebbd.png)

Windows10に標準で同梱のアプリなので必ず使えます。Macで言う「スクリーンショット」アプリですね。

前は「Snipping Tool」という名称のアプリでしたが、UWPのストアアプリとなって名前が変わったようですね。見た目もカッコよくなり、丸く切り取ったりもできてステキです。

「スケッチ & 切り取り」の設定はデフォルトで下記のような設定になっています。この中で気になるものがある場合には、スタートメニューから「スケッチ & 切り取り」を探して起動し、設定を開いて変更してみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/4a2c9aa9-6f9b-3d0b-85b4-29c891fff585.png)

また、スクリーンショットの履歴を残したかったり、毎回ファイルに保存された方が都合がいいこともあります。そんな時は、OneDriveの設定を確認してみてください。下記のように「作成したスクリーンショットをOneDriveに自動的に保存する」という項目があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/da797d6c-a99a-1ebf-5e85-9bd9afa2d0a5.png)

# Mac OS

`Command`+`Shift`+`4`で矩形選択のスクリーンショットをとることができます。
また、`Command`+`Shift`+`3`だと全画面のスクリーンショットです。

これだとウィンドウのスクリーンショットの撮り方のバリエーションが少ないです。
そこで`Command`+`Shift`+`5`の出番です。これにより、「スクリーンショット」というアプリが起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/2f1fcf2c-6f8b-2638-dd05-3bede4b0efce.png)
この「スクリーンショット」はMacに標準で同梱のアプリです。Winで言う「スケッチ & 切り取り」みたいなものです。

しかし、上記のショートカットだけでは、画像ファイルが作成されるだけなので困っていました。

1. Qiita記事を編集中にスクショを貼りたいと思う
1. 他のウィンドウに移る
1. スクショを取る
1. Qiita記事に戻る
1. 画像選択ボタンを押す
1. 画像を選ぶ
1. Qiita記事の続きを書き進める

４と５を減らして、サボりたかったワケです。

いろいろ調べていると`Control`キーが重要だということがわかってきました。
どうやら、Macでは`Control`を押しながらだと、クリップボードにコピーされるみたいです。

具体的にどうするといいのか下記の表にまとめました。

# 表で整理

| OS| ターゲット | 送り先 | ショートカット |
|:-:|:-:|:-:|:-:|
| Mac | 全画面 | :clipboard: クリップボード | `Command`+`Shift`+`3`+`Ctrl` |
| Mac | 矩形 | :clipboard: クリップボード | `Command`+`Shift`+`4`→`Ctrl`+`クリック` |
| Mac | 全画面 | :file: 画像ファイル | `Command`+`Shift`+`3` |
| Mac | 矩形 | :file: 画像ファイル | `Command`+`Shift`+`4` |
| Mac | 前回指定[^前回指定] | :clipboard: クリップボード | `Command`+`Shift`+`5`→`Ctrl`+`クリック` |
| Mac | 前回指定[^前回指定] | :file: 画像ファイル | `Command`+`Shift`+`5`→`クリック` |
| Win | 全画面 | :clipboard: クリップボード | `PrintScreen` |
| Win | ウィンドウ | :clipboard: クリップボード | `Alt`+`PrintScreen` |
| Win | 前回指定[^前回指定] | :clipboard: クリップボード | `Win`+`Shift`+`s` |

[^前回指定]: 前回指定とは、「前回スクリーンショットしたときの範囲」をOSが記憶していて、それを指定するということです。

# まとめ

自分的に、記事をまとめながらOSを比較してみることで、「こういう差異が生まれるんだね。」とか知見が高まりました。自分がUIを作るときなどにも役に立つ、いい体験ですね。今後も定期的に、こういった記事を書こうかなと思います。

**Excelsior!**
pandas で Radviz を試してみよう


とりあえずColabのノートブックは[こちら](https://colab.research.google.com/drive/1eecjfmddW7wcVW4j8ODDWQ0wVj6KVDEQ?usp=sharing)。

## Radviz とは

Radvizは多次元データを低次元(自分が知る限り2Dもしくは3D)でプロットする可視化手法だ。

pandasを用いると簡単にRadvizを作ることができる。
下記は https://pandas.pydata.org/docs/reference/api/pandas.plotting.radviz.html ほぼそのまんまのコードとその結果だ。

```python
import pandas as pd

df = pd.DataFrame(
    {
        'SepalLength': [6.5, 7.7, 5.1, 5.8, 7.6, 5.0, 5.4, 4.6, 6.7, 4.6],
        'SepalWidth': [3.0, 3.8, 3.8, 2.7, 3.0, 2.3, 3.0, 3.2, 3.3, 3.6],
        'PetalLength': [5.5, 6.7, 1.9, 5.1, 6.6, 3.3, 4.5, 1.4, 5.7, 1.0],
        'PetalWidth': [1.8, 2.2, 0.4, 1.9, 2.1, 1.0, 1.5, 0.2, 2.1, 0.2],
        'Category': [
            'virginica',
            'virginica',
            'setosa',
            'virginica',
            'virginica',
            'versicolor',
            'versicolor',
            'setosa',
            'virginica',
            'setosa'
        ]
    }
)

pd.plotting.radviz(df, 'Category', color=['red','green','blue'])
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7591/b58b15c8-cee8-9d8a-da7c-b67951abde66.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7591/428a0190-f22c-b473-a5b6-fb9e21accf00.png)

SepalLength、SepalWidth、PetalLength、PetalWidth 近くに点があるがこれらはデータ点ではないので気をつけてほしい。Radvizは

- setosaのカテゴリーのirisは、SepalWidthのデータが他の列と比較して突出して大きい特徴がある
- virginicaのカテゴリーのirisは、setosaのような突出した特徴が無い

ことを示している。

## Radviz が可視化するものの確認

https://qiita.com/_likr/items/6a5630d91faeea066404

によると 「n 個の次元をアンカーとして円周上に配置する。データ点と各アンカーがバネで結ばれているとし、バネの力が釣り合う座標にデータ点を配置する。それぞれの次元において、値が大きいとバネの力を強く、値が小さいとバネの力を弱くする。」

とある。これを先のpandasを用いた例で言いかえて確認していこう。

### アンカーの配置

たしかに4次元(SepalLength、SepalWidth、PetalLength、PetalWidth)のアンカーが画像のように円周上に配置されている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7591/58edb6dc-9713-6560-3ff8-32434a689e64.png)

もし8次元のデータなら下記の点にアンカーが配置される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7591/f34cc82e-e7ac-2b51-cf55-7ae9fc2ca3c3.png)

### データ点の配置について
「値が大きいとバネの力を強く」が意味することは、アンカーの値が大きいと、アンカーに「近い」位置に点を打つ、ということである。円の中心近くに打つのではない。
ここで注意したいのは「単に」アンカーの値が大きい、ことを意味しているわけではなく「他のアンカーの値と比較して大きい」とアンカー近くに点を打つということだ。

これを確認するために行indexが1の行を抜いてRadvizを作り直してみよう。行indexが1の行のSepalWidthは、行indexが2の行と同じ値「3.8」だが PetalLength、PetalWidthの値は抜群にデカい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7591/2cf60c29-6914-c4d5-9530-a3f0a4d5aa4d.png)

行indexが1の行を抜いてRadvizを作り直すとこうなる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7591/a8f11b1d-aa02-c0dd-cf9b-07ae0db2a815.png)

SepalWidthがその列の値としては最大の「3.8」の行を抜いたにも関わらず、Radvizから抜けた点は「SepalWidthのアンカー近くの点」ではなく「円の中心近くの点」であることがわかるだろうか?

つまり「抜いた点のirisは全体的にサイズがデカく、SepalLength、SepalWidth、PetalLength、PetalWidthのどこかの特徴が突出していたわけではない」からRadvizはそういうもんを真ん中に配置する、ということがわかる。

## Radvizをさらに考える

ここであなたは「これアンカーの配置の仕方が重要では?」と思われたかと思う。
たしかにそのとおりだ。が私はその最適化方法をわかっていない。(さらに言うとバネの力についてもよくわかっていない。)
わかっていたら私にもわかる記事を書いて教えていただきたい。
(超尻切れトンボですんません!)
RDKit使用メモ

# 準備
環境とかインストールしておくべきものとか

## 環境
- Anaconda
- Ubuntu 18.04.1(on WSL2)

## インストール
condaでRDKit用の仮想環境を作成

```
$ conda create -c rdkit -n (仮想環境名) rdkit
```
そのまま`import rdkit`を使ってみると、○○のライブラリが無いとか言われるのでダウンロード (自分の場合は`libxrender1`)

```
$ sudo apt install libxrender1
```
その他`matplotlib`や`scikit-learn`を`$ conda install XXXX`でインストール
(あと記事作成用に`tabulate`)

# 試してみる
## 分子の表示
```Python
from rdkit import Chem
from rdkit.Chem import Draw

# SMILES記法で書いた分子をmolファイルと呼ばれる形式に変更
molecule_1 = Chem.MolFromSmiles('Cc1ccccc1')

# mol形式ファイルを画像に変換 (display)
Draw.MolToImage(molecule_1)
```
[出力結果] 
![001_DrawTest.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531685/6e608c68-ed78-3348-e6f4-8581d7542d6b.png)

## フィンガープリントの作成
以下の記事を参考に、化合物のSMILESと溶解度のデータを取得。
[化学情報学にRDKitとScikit-learnで入門する](https://qiita.com/maskot1977/items/2e98d76a0782a6e89bde)

|    | smile    | XXXX     |   logS |
|---:|:---------|:---------|-------:|
|  0 | O=C(C)N  | 60-35-5  |   1.58 |
|  1 | NNC      | 60-34-4  |   1.34 |
|  2 | O=C(C)O  | 64-19-7  |   1.22 |
|  3 | N1CCCC1  | 123-75-1 |   1.15 |
|  4 | O=C(N)NO | 127-07-1 |   1.12 |

SMILE形式で保存されているものをMOL形式に変換。その後にフィンガープリントを取得。
 - radius: 半径。注目する原子から何原子先までを考慮するか。

```python
smiles = df['smile']
molecules = [Chem.MolFromSmiles(smile) for smile in smiles]

# 試しに一つだけフィンガープリントを作成
from rdkit.Chem import AllChem
molecule_1 = molecules[0]

fingerprint = AllChem.GetMorganFingerprintAsBitVect(mol=molecule_1, radius=2, nBits=2048)
# -> rdkit.DataStructs.cDataStructs.ExplicitBitVectというクラスのデータが作成

fingerprint.ToBitString()
# -> 000000000000000100000000000000100のような表現に変更
# -> あとはこれを使って好きなように機械学習のモデルに突っ込めばOK


```
React Nativeでfocusできない件

# useEffectでTextInput(Searchbar)にfocusしたいがエラーが出る
React Native PaperのSearchbarをマウントする際に、focusした状態で表示したかった。
そこで、以下のようにuseRefでrefをつくり、useEffectの際にfocusしようと試みた。

```jsx
export const SearchInput = ({onChangeText, onSubmitEditing, isFocused, ...props}) => {
  const ref = useRef()
  useEffect(() => {
    isFocused && ref.current.focus()
  }, [])

  return (
    <Searchbar
      placeholder="Search"
      onChangeText={onChangeText}
      onSubmitEditing={onSubmitEditing}
      style={styles.input}
      ref={ref}
      {...props}
    />
  )
}
```

React Native PaperのSearchbarは、TextInputをforwardRefでラップしたものなので(たぶん)、
refを渡すことでfocusできると思ったが、なぜかうまくfocusできず、以下のようなWarningが出た。

```
Warning: dispatchCommand was called with a ref that isn't a native component. Use React.forwardRef to get access to the underlying native component
```


# 解決策
目的としては、fucusした状態でTextInputをマウントしたいだけだったので、
別の方法を探していると、React NativeのTextInputには[autoFocus](https://reactnative.dev/docs/textinput#autofocus)というPropsがあった。
これを使えば、以下のように一瞬で解決した。

```jsx
export const SearchInput = ({onChangeText, onSubmitEditing, isFocused=false, ...props}) => {
  return (
    <Searchbar
      placeholder="Search"
      onChangeText={onChangeText}
      onSubmitEditing={onSubmitEditing}
      style={styles.input}
      autoFocus={isFocused}
      {...props}
    />
  )
}
```

Warningの意味についてもいろいろ調べてみたが、原因についてはよくわからなかったので、ご存じの方がいらっしゃいましたら、コメントで教えて下さい。
年が明けて仕事が始まったら、先輩に聞いてみます。
不完全燃焼なのでモヤモヤするが、開発を進めなければいけないのと、
とりあえずやりたいことはできたので、今回は良しとします。
AWSでのドメイン取得からhttps化まで

# はじめに

AWSで独自ドメインを取り、証明書を発行しALBをhttps化するまでのメモ

# やり方

## ドメイン取得

1. AWSコンソールからRoute53を開き、右側の「ドメイン」をクリックします。
2. 上部にある「ドメインの登録」ボタンをクリックします。
3. 好きなドメインを検索し、「カートにいれる」→「続行」→「注文を完了」と進めます。

ドメインの購入には最大で1日ほど時間がかかるようですが、自分の場合は30分ほどで手続きが完了しました。手続きが完了すると、登録してあるメールアドレスにメールが届きます。

## 証明書の作成

1. AWSコンソールからCertificate Managerを開きます。
2. 「証明書をリクエスト」をクリックし、パブリック証明書にチェックを入れ次のページへ進みます。
3. ドメイン名に先ほど購入したドメインを入力します。この時「*.<ドメイン名>」という形式で入力してください。このようにしないと、サブドメインを切った時に、この証明書を使い回すことができなくなります。
4. 「検証方法」ではEメールにチェックを入れます。(DNSの登録では、自分はうまく行きませんでした。。。)
5. しばらく待つと、登録してあるメールアドレスに検証用のメールが届くので、案内にしたがって検証を完了します。

## ALBの作成

1. AWSコンソールからロードバランサー」のページを開き、上部の「ロードバランサーの作成」をクリックします。
2. 「Application Load Balancer」を選択し、「ロードバランサーのプロトコル」をhttpsにします。![スクリーンショット 2020-12-27 22.22.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614264/05e6931b-79c4-1eb9-41f3-cf0d8e94e3a7.png)
3. セキュリティ設定の構成で、「証明書タイプ」を「ACM から証明書を選択する」にし、「証明書の名前」で先ほど作成した証明書を選択します。


## Route53の設定

今のままでは、ALBのドメイン名と証明書のドメイン名が異なっているので、証明書のエラーが発生するので、ALBのドメインにエイリアスを貼ります。

1. AWSコンソールからRoute53を開き、左側の「ホストゾーン」
2. 先ほど取得したドメインをクリックし、「レコードを作成」ボタンをクリックします。
3. ルーティングポリシーから「シンプルルーティング」を選択し、次へ進みます。この画面にならない時は、「ウィザードへ切り替える」をクリックしてください。![スクリーンショット 2020-12-27 22.40.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614264/1f18112c-25b1-5b2c-a77e-5a40876455ef.png)
５. 「シンプルなレコードを定義」をクリックし、サブドメインを入力します。「エンドポイント」は「Application Load BalancerとClassic Load Balancerへのエイリアス」にし、先ほど作成したALBを選択して保存します。![スクリーンショット 2020-12-27 22.43.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614264/65a3b288-4d47-2f83-2c86-8fe7163f4dc5.png)


以上で作業は終わりです。
Route53に登録したレコードの値で、httpsでアクセスできます。
Ruby の attr_accessor はアクセッサーじゃない

Ruby の初心者向け記事の定番間違いの一つに，`attr_accessor` のことを「アクセッサー」と呼ぶ，というものがあります。
単に言葉の表現が間違っているだけの場合と，そもそも正しく理解していない場合とがあるように思われます。

Ruby の場合，アクセッサーというのは，

* インスタンス変数の値を読み出すためのメソッド（ゲッターと呼ぶ）
* インスタンス変数に値をセットするメソッド（セッターと呼ぶ）

の総称です。
以下の典型的な例を見ましょう

```rb
class Person
  def name
    @name
  end

  def name=(name)
    @name = name
  end
end

a_person = Person.new
a_person.name = "Kaoru"
puts a_person.name # => "Kaoru"
```

二つのメソッドを定義していますが，`name` がゲッターで，`name=` がセッターです。この二つを合わせてアクセッサーと呼ぶわけです。
慣習として，

* ゲッターのメソッド名はインスタンス変数名から `@` を除いたもの
* セッターのメソッド名はインスタンス変数名から `@` を除いたものの末尾に `=` を付加したもの

とします（ルールではなく慣習です）。

名前の末尾が `=` であるようなメソッドは「代入メソッド」と呼ばれ，Ruby の構文上，ちょっぴり特別扱いされます。
上の例で

```rb
a_person.name = "Kaoru"
```

と書いたように，メソッド呼び出しの際に `=` の前にスペースを入れても構わないのです。
上のコードは代入式の一種です[^ae]。

[^ae]: Ruby の代入式は，変数への代入だけではないってことですね。

それだけではありません。代入メソッドを使った自己代入式も書けます。
以下のコードを見ましょう（クラス定義は先ほどのとおりだとします）。

```rb
a_person = Person.new

# (1)
a_person.name ||= "Kaoru"
puts a_person.name # => "Kaoru"

# (2)
a_person.name ||= "Haruka"
puts a_person.name # => "Kaoru"
```

(1) では，インスタンス変数 `@name` にまだ値がセットされていない（読み出すと `nil` になる）状態で自己代入演算子 `||=` を使っているので，`@name` の値が `"Kaoru"` になります。

しかし，(2) では，`@name` に文字列オブジェクトが代入された状態で実行されるので代入は起こりません。そのため，`a_person.name` の返り値は `"Haruka"` ではなく `"Kaoru"` になっています。

前ふりが長くなりました。ここから本題に入りましょう。
先ほどのクラス定義を見ると，ゲッター，セッターの定義で（単純とはいえ）それぞれ 3 行も費やしています。
インスタンス変数が 5 個あって，それぞれゲッターもセッターも定義するとなると，30 行も必要になります。これは馬鹿馬鹿しいですね。

そこで，このような単純なゲッター，セッターを定義するなら[^simp]

```rb
class Person
  attr_accessor :name
end
```

と書けば済むようになっています。

[^simp]: 「単純な」と書いたのは理由があります。単純でないアクセッサーを定義したいこともあるからです。とくにセッターの場合，与えられた引数に何らかの正規化（全角／半角の統一とか余計なスペースの削除とか）を施してからインスタンス変数に代入したいことがあります。こういう場合，`attr_accessor` は使えません。

この `attr_accessor` のことを「アクセッサー」と書いている記事をよく目にします。
しかし，`attr_accessor` はアクセッサーを定義してくれるものであって，これ自体がアクセッサーなのではありません。
おそらく名前の一部に「accessor」と付いているのに引きずられて「アクセッサー」と思い込んでしまうのでしょう。

ところで，`attr_accessor` というのは一体何者でしょうか？
他言語から来た方は，Ruby のクラス定義構文の一部分と思うかもしれませんが，そんな文法はありません。
`attr_accessor` はただのメソッドです。
参考：[Module#attr_accessor (Ruby 3.0.0 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/3.0.0/method/Module/i/attr_accessor.html)

つまり，

```rb
attr_accessor :name
```

は，`:name` というシンボルを引数として，`attr_accessor` というメソッドを呼び出しているだけなのです。
こうすることで，クラスにアクセッサーが定義されます。
`attr_accessor` は**メソッドを定義するメソッド**なわけです。

少し補足すると

* クラスもまたオブジェクトである
* クラス定義式（`class Person` 〜 `end`）の中では，そのクラスが `self` となる
* つまり，クラス定義式内でレシーバーをあらわに書かないメソッド呼び出しを行うと，当該のクラスがレシーバーとなる

ということです。
最後の点を確認するコードを以下に示します。

```rb
class Hoge
  p name # => "Hoge"
end
```

このコードで，`name` はローカル変数ではありません。この箇所以前に `name` への代入式が存在しないので，ローカル変数ではありえないのです。
とすると，メソッド呼び出しのはずです。
このメソッド呼び出しにはレシーバーが書かれていません。
ここはクラス定義式の中ですから，`name` のレシーバーは `Hoge` クラスです。
`Hoge` は `Class` というクラスのインスタンスですから，`name` はクラス名・モジュール名を返すメソッドです。だから `"Hoge"` が表示されます。
参考：[Module#inspect (Ruby 3.0.0 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/3.0.0/method/Module/i/inspect.html)

以上が理解できると，

```rb
class Person
  attr_accessor :name
end
```

は

```rb
class Person
end

Person.attr_accessor(:name)
```

と書くのと同じであることが分かるでしょう。
Ruby 3でRBS、TypeProf、Steep(型注釈・型検査)を体験してみる！

Ruby3がリリースされました。
Rubyコミッターの皆さん、お疲れ様です。


待ち望んでいた、Rubyの型注釈をやってみる！！

# Ruby3をインストール！

rbenvをインストールする。

```
brew install rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
source ~/bash_profile
```

rbenvからRuby3をインストールする。
インストールできるリストを確認すると、3.0.0があるのを確認。

```
% rbenv install --list
2.5.8
2.6.6
2.7.2
3.0.0
jruby-9.2.14.0
mruby-2.1.2
rbx-5.0
truffleruby-20.3.0
truffleruby+graalvm-20.3.0

Only latest stable releases for each Ruby implementation are shown.
Use 'rbenv install --list-all / -L' to show all local versions.
```

Ruby3.0.0をいよいよインストール。

```
 rbenv install 3.0.0 
 rbenv global 3.0.0
```

やったー。

```
% ruby -v               
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
```
# Rubyの型注釈をやってみる

適当なディレクトリにRubyのコードを書いてみる。
`app.rb`というファイルに書いてみた。

```ruby
def plus(x, y)
  x + y
end

puts plus(1,1)
```

必要なツールをインストールする。
型検査をしてくれるsteepというgemを使う。

```
gem install steep
```

Steepfileという設定ファイルを自動生成してもらう。

```
steep init
```

Steepfileが生成された。

```
# target :lib do
#   signature "sig"
#
#   check "lib"                       # Directory name
#   check "Gemfile"                   # File name
#   check "app/models/**/*.rb"        # Glob
#   # ignore "lib/templates/*.rb"
#
#   # library "pathname", "set"       # Standard libraries
#   # library "strong_json"           # Gems
# end

# target :spec do
#   signature "sig", "sig-private"
#
#   check "spec"
#
#   # library "pathname", "set"       # Standard libraries
#   # library "rspec"
# end     
```

Steepfileを書き換える。

```
target :lib do
  signature "sig"
  check "app.rb"
end
```

試しに、型検査をしてみる。

```
steep check   
app.rb:5:5: NoMethodError: type=::Object, method=plus (plus(1,1))
```

まだ型注釈を書いてないので、NoMethodErrorとなる。

# 型注釈を書く
次は、`sig`ディレクトリ以下に型注釈を入れていく。
型注釈は`.rbs`という拡張子で記述する。

`TypeProf`というRuby3に付いているツールで自動で生成できる。

```
typeprof app.rb -o sig/app.rbs
```

`sig/app.rbs`が生成された。以下のようになる。

```
# Classes
class Object
  private
  def plus: (Integer x, Integer y) -> Integer
end

```

この状態で型検査してみる。

```
steep check    
```

すると、何も表示されなかったので型検査が通りました🎉

試しに、IntegerをStringにしてみる。

```
# Classes
class Object
  private
  def plus: (Integer x, Integer y) -> String
end
```

すると、このようなエラーとなる。

```
steep check
app.rb:1:0: MethodBodyTypeMismatch: method=plus, expected=::String, actual=::Integer (def plus(x, y))
  ::Integer <: ::String
   ::Numeric <: ::String
    ::Object <: ::String
     ::BasicObject <: ::String
==> ::BasicObject <: ::String does not hold
```

# まとめ
待ち望んでいた、Rubyの型を体験できてよかった。
TypeProfなどで自動で解析して型注釈を書いてくれるのは独自な機能だし、Matzさんの思想が反映されているのかなぁと感じた。

# 参考文献
https://qiita.com/scivola/items/ac83d8275ace1b4ed123
【Java ~ 真偽値 ~ 】勉強メモ（２）

Java学習中。
復習に見返せるようにメモしていきます。
ほぼ自分の勉強メモです。
過度な期待はしないでください。


真偽値
-

- 真偽値とは

真偽値とは、「true」と「false」という2つの値がある。
trueは真（正しい）、falseは偽（間違っている）を意味する。
真偽値のデータ型は`boolean型`です。
<br>

- 比較演算子

比較演算子とは、値を比較するための記号で、比較した結果は真偽値（trueかfalse）になる。
「x == y」は、xとyが同じかどうかを比較し、同じであればtrue、違っていればfalseとなる。
また「x != y」はその逆になる。
<br>

```.java:例
// ①「==」を用いて、値を比較した結果を出力
System.out.println(12 / 4==3);
    
// ②「!=」を用いて、値を比較した結果を出力
System.out.println(12 / 4!=3);
    
// boolean型の変数boolを定義し、「3 * 9 == 27」を代入
boolean bool = 3 * 9 == 27;

// ③変数boolの値を出力してください
System.out.println(bool);
```

```.text:出力結果
①true

②false

③true
```
<br>

- 比較演算子/大小比較

<, >という記号は数学でも用いる大小比較の記号です。
x < yはxがyより小さければtrue, 大きければfalseを返します。x > yはその逆となる。
<br>

```.java:例
// 8と5を比較し、falseとなるように出力
System.out.println(8 < 5);
    
// 3と2を比較し、trueとなるように出力
System.out.println(3 >= 2);
```
<br>

- 論理演算子

論理演算子は、「かつ」「または」「~でない」を表現する記号。

-「かつ」は、<b>&&</b> で表現し、「条件1 && 条件2」は「条件1がtrueかつ条件2もtrue」であれば結果もtrueになり、
どちらか一方でもfalseであれば結果はfalseになる。

```.java:例
System.out.println(8 < 5 && 3 >= 2);
// 出力結果 → false
```
<br>

-「または」は、<b>| |</b> で表現し、「条件1 || 条件2」は、「条件1または条件2のどちらか一方でもtrue」であれば
結果はtrueになる。

```.java:例
System.out.println(8 < 5 || 3 >= 2);
// 出力結果 → true
```
<br>

-「~でない」は、<b>!</b> を用いると表現できます。
例えば、!(x >= 30)は「xが30以上でない（つまり30より小さい）」ときtrueになり、「xが30以上」のときfalseになる。

```.java:例
System.out.println(!(8 < 5));
// 出力結果 → true
```
<br>
過去投稿記事
-
[【Java~変数の定義、型変換について~】勉強メモ](https://qiita.com/k-yasuhiro/items/43ef789c8be7b669046a)