OmniAICreator/Qiita-1.07M huggingface dataset:
スライドショー

今回のスライドショーでは、次へ、前へボタンをクリックせれたら配列に登録されているimgを切り替える。今何枚目の画像をみているのかわかるようにする。

```index.html
<div class="slide">
        <div class="image_box">
            <img id="main_image" src="images/image1.jpg">
        </div>
        <div class="toolbar">
            <div class="nav">
                <div id="prev"></div>
                <div id="page"></div>
                <div id="next"></div>
            </div>
        </div>
    </div>
```
image_boxにimgの id=main_iamdeをセットします。これは、スライドの一番最初の画像になります。
さらに、ツールバーの中は今回はスライドショーを操作するためのツールです。上から前へ、ページ数、次へのボタンになります。

```index.js
const images = ['images/image1.jpg', 'images/image2.jpg', 'images/image3.jpg', 'images/image4.jpg', 'images/image5.jpg'];
let current = 0;

function changeImage(num) {
    if(current + num >= 0 && current + num < images.length) {
        current += num;
        document.getElementById('main_image').src = images[current];
        pageNum();
    }
};

function pageNum() {
    document.getElementById('page').textContent = `${current + 1}/${images.length}`;
}

pageNum();

document.getElementById('prev').onclick = function() {
    changeImage(-1);
};
document.getElementById('next').onclick = function() {
    changeImage(1);
};
```
まず、プログラムの冒頭で、配列を定数imagesに代入します。
変数currentに０を代入します。なぜ代入するかというと、今何枚目の画像にいるのかをを保存するために使います。ボタンクリックのときに

呼び出されるchangeImage関数についてみていきます。　ボタンをクリックされたときに渡される値をパラメータとしてnumを渡します。パラメータの名前は自由にセットすることができます。
次のif文では、最初の条件式にcurent + num があります。これは、前の変数currentで0を保存していました。
次へボタンの1がパラメータとして入ってきた場合、0+1で1になります。　&&(かつ)　current + numよりもimages.length(データの項目数)　&&（かつ）の場合は、どちらか一方でもtrueならプログラムは読み進められます。
読み進められた後の処理は、current += num;▶0+1になります。(a+bしてaに代入)
そして、次の行ではHTMLでid main_imageを設定したので、取得します。document.getElementByIdで取得。.属性(src)= 値、配列imagesのcurrent番目のデータ(images[current])

pageNumの関数処理
id pageを取得します。＝の右側のソースは、テンプレート文字列を使用します。
{current + 1}▶現在表示しているページになります。currentには、配列imagesから特定の項目を読み取るために使用していました。
なので、0~4が入るはずですが、感覚的に気持ち悪いので今回は+1にします。{images.length}は画像の点数になります。

それでは、最後の次へクリックされたときの関数です。
HTMLがわでセットしたid属性prev,nextを取得します。
changeImageを呼び出してパラメータとして(-1,+1)をそれぞれパラメータとしてセットします。

> 出典
> https://www.amazon.co.jp/%E7%A2%BA%E3%81%8B%E3%81%AA%E5%8A%9B%E3%81%8C%E8%BA%AB%E3%81%AB%E3%81%A4%E3%81%8FJavaScript%E3%80%8C%E8%B6%85%E3%80%8D%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E7%8B%A9%E9%87%8E-%E7%A5%90%E6%9D%B1/dp/4815601577
deviseで標準装備されているカラムにはバリデーションが必要。

deviseを導入して、ビュー等も整えたところで早速ユーザー登録をしてみることに。
そしたら以下のエラーが出てきました。


```ActiveRecord::NotNullViolation in Devise::RegistrationsController#create
```

ググって調べて解決策が乗ってたんですけど、エラー文のままですね。

devise標準装備のカラムには、バリデーションを設けてやる必要があったとのことです。

```user.rb
validates :name, :email,  presence: true
```

上記を記述し解決しました。
print

```py
print('Hi','Mike') #デフォルトではスペースで区切られる
print('Hi', 'Mike', sep=',')
print('Hi','Mike', sep=',', end='\n') #デフォルトでは改行される
print('Hi','Mike', sep=',', end='')
print('Hi','Mike', sep=',', end='')
```
出力結果：

```txt
Hi Mike
Hi,Mike
Hi,Mike
Hi,MikeHi,Mike
```
一日でReact(Next.js)でポートフォリオを作ってみた話

<h1>完成品</h1>
<p>こちらが完成した<a href="https://portfolio-eight-sigma-68.vercel.app/">ポートフォリオサイト</a>です。</p>

<h1>お問い合わせフォーム</h1>
<p>microCMSを使いました。とても簡単にReactでお問い合わせフォームを作ることができます。</p>
<a href="https://code-log.hatenablog.com/entry/2020/02/10/221738">参考：microCMSのPOST APIでNext.jsにお問い合わせ機能を実装してみた</a>
Error: A cross-origin error was thrown. React doesn't have access to the actual error object in development.

### 事象

Reactのアプリケーションで以下のエラーが出ました。

```
Error: A cross-origin error was thrown. React doesn't have access to the actual error object in development. See https://fb.me/react-crossorigin-error for more information
```

![スクリーンショット 2021-04-21 11.46.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255852/5729e283-513a-4968-d8e1-bb7294e9cb25.png)

### 原因

- エラーメッセージ通りですが、[CORSエラー](https://reactjs.org/docs/cross-origin-errors.html)でした。
    - 空のlocalStorageを参照しようとしていたのが原因でした。
    - [localStorage周りの原因](https://stackoverflow.com/questions/48611310/uncaught-error-a-cross-origin-error-was-thrown-react-doesnt-have-access-to-th)が多そうです。

```sample.js
// localStorageに"hogehoge"はない
const hoge = localStorage.getItem("hogehoge")
```

### 対応

- localStorageの"hogehoge"を参照する前に条件分岐を入れることで対応しました。
関数の中に関数を定義する

Rubyのバージョン　2.6.5
# 目次

- 関数の中に関数を定義する方法
- 関数の上書き
- まとめ
- 今回の気づき

## 関数の中に関数を定義する方法
以下のようにして関数の中に関数を定義します。

```Ruby:ruby
def a
  def b
    puts "b"
  end
end
```

ここで、関数bをよびだすと以下のようなエラーが起こります。

```ruby:
def a
  def b
    puts "b"
  end
end

b  #関数を呼び出す

↓↓↓↓↓ターミナル

Traceback (most recent call last):
test.rb:7:in `<main>': undefined local variable or method `b' for main:Object (NameError)
```
bという関数が定義されていないようです。
b関数を定義するには、最初にa関数を呼び出しておく必要があります。

```ruby:
def a
  def b
    puts "b"
  end
end

a  #初めにa関数を呼び出しておく→ここでb関数が定義される
b  #関数を呼び出す

↓↓↓↓↓ターミナル

b
```


## 関数の上書き
クラスに定義されているインスタンスメソッドの上書きはオーバーライドというらしい。
以下のようにして上書きすることができる。

```ruby:ruby
def a
  puts "abc"
end

a  #a関数を呼び出す

def a
  puts "123"
end

a  #a関数を呼び出す

↓↓↓↓↓ターミナル

abc
123
```

a関数やc関数を呼び出すたびにb関数を上書きしてみる。

```ruby:ruby
def a
  def b
    puts "abc"
  end
end

def c
  def b
    puts "123"
  end
end

a  #a関数を呼び出す→b関数が定義される
b  #b関数を呼び出す
c  #c関数を呼び出す→b関数が上書きされる
b  #b関数を呼び出す
a  #a関数を呼び出す→b関数が上書きされる
b  #b関数を呼び出す

↓↓↓↓↓ターミナル

abc
123
abc
```

Rubyはオブジェクト指向のプログラミング言語です。なので、オーバーライド以外に使い道がないような気もしますが、オーバーライドはとても重要な要素なので覚えていて損はないと思います。

## まとめ
関数の中に関数を定義することができます。使い道はよくわかりません。ので、できることだけ頭に入れておけばいいと思います。やり方はその都度調べればいいと思います。

## 今回の気づき
関数の中に関数を定義するという、使うタイミングがわからないものを紹介したこともあり、深い話ができなかった。実装に悩んで、調べて解決したものを載せる方がいいかもしれない。
エイリアス登録しておくと便利なGitコマンドまとめ

わりとよく使うGitのコマンドはエイリアスに登録しておくと便利なので、普段使う頻度が多いコマンドをまとめる
今回はmacのshell(zsh)に登録する方法を使う。
git ailiasに登録したい人はこちらの記事がおすすめ。
https://qiita.com/peccul/items/90dd469e2f72babbc106

# エイリアス登録方法
```
vi ~/.zshrc
```
でviで開いて、

```
alias g-c="git clone"
```
と登録したいエイリアス名と実際に動くコマンドを設定する。

## 引数を持ったエイリアスを作る
```
alias g-c="(){git clone $1}"
```
このようにすれば引数を持ったエイリアスも可能

### ailiasを使うとき
```
g-c https://github.com/hogehoge/fugafuga.git
```


# 本題のよく使うエイリアスに登録しているgitコマンド

## git stash系
ローカルで開発してたけどまだコミットするまでソース綺麗にかけてない。でもバグ修正の依頼来ちゃった。一度どっかに今の状態避難させたい。
そんな時使う。
https://qiita.com/chihiro/items/f373873d5c2dfbd03250

```
alias g-s="git stash" //一時退避
alias g-s-l="git stash list" //一時退避中のリスト
alias g-s-a="git stash apply stash@{0}" //一時退避している最新のものに戻す
```

## git log系
過去のcommitを探したい時。期間で絞ったり、キーワード検索したり。
他にもgit logはオプションが豊富なので興味ある人は色々検索するとよい。

```
alias g-l-s='(){git log --since="$1"}' //日付以降で絞る 
alias g-l-u='(){git log --until="$1"}' //日付以前で絞る
alias g-l-su='(){git log --since="$1" --until="$2"}' //期間指定で絞る
alias g-l-g='(){git log --grep="$1"}' //キーワードで絞る
alias g-l-a="git log --all" //全てのブランチのログを表示
```

## git branch系
マージ済のブランチを一括削除したい。まだmasterにもdevelopにもマージされていない謎ブランチを洗い出したい。

```
//ローカルでマージ済のブランチを表示
alias g-b-m="git branch --merged master | grep -vE '^\*|master$|develop$'"
//ローカルでマージ未のブランチを表示
alias g-b-nm="git branch --no-merged master | grep -vE '^\*|master$|develop$'"
//ローカルでマージ済のブランチを削除
alias g-bd-m="git branch --merged master | grep -vE '^\*|master$|develop$' | xargs -I % git branch -d %" 
//リモートでマージ済のブランチを表示
alias g-rb-m="git branch -r --merged master | grep -v -e master -e develop"
//リモートでマージ未のブランチを表示
alias g-rb-nm="git branch -r --no-merged master | grep -v -e master -e develop"
//リモートでマージ済のブランチを削除
alias g-rbd-m="git branch -r --merged master | grep -v -e master -e develop | sed -e 's% *origin/%%' | xargs -I% git push --delete origin %"
```
テストの勘所

#■はじめに
下記の内容については、
参考記事（[プログラミングとテストの要点](https://techfun.cc/devbase/devbase4.html)）を主に参考に基本的な内容を私個人の独断と偏見でまとめてみた内容となっています。
賛否両論、過不足のある内容とは思いますが、１つの意見（見解）として参考にして頂ければと思います。
※上記の参考記事は、簡潔に要点をおさえた内容と感じましたので、参考記事としてお勧めいたします。

#■不具合の原因/要因について（個人見解）
　開発者は担当する機能が正しく動作するように完璧に仕上げることは念頭に開発を行っていると思いますが、それでも「想定できなかった部分」や「想定しきれない部分」など、いわゆる想定外による不具合（バグ）を完全になくすことはできないと思います（※開発規模が極めて小さければ可能な場合もある）
　不具合（想定外）の原因は、設計や定義などの考慮不足や漏れ、仕様確認や仕様変更などの情報共有が遅延した場合、又は、開発者のケアレスミス、仕様や設計の誤認、修正（作業）による影響範囲の誤認、外部要因など様々な要因があると思います。
　テスト実施者は、テスト項目と各項目の期待する結果も含めて客観的な視点で「腑におちない点」がないかも併せて確認できることが望ましいと考えます。
「腑におちない点」とは単純に「ん？」って感じる違和感です。「あれ？これ何かおかしくない」とか「これ大丈夫？」って感じる点です。
「腑におちない点」があるということは、お客様（運用者）から見ても腑におちない点である可能性が高く、それに対して設計者又は開発者が十分な説明ができないのであれば、要件の誤認、設計不備や考慮漏れなどの問題が潜在している可能性が高いと思うからです。

#■テストの考え方
　「テスト対象機能が予め定められている要件や仕様／設計通りに正しく動作することを確認することが大前提」となります。
設計者や開発者が当初「想定できなかった部分」が開発／テスト工程を進めていく過程で、顕在化することもあると思いますので、設計書に記載がない仕様だからといってそれがイコールで不要／問題ないと決めつけるようなことは避けてほしいと思います。
※「テスト仕様書を作成する際に抑えるべきポイント」を記載しておりますが、正直、難しいですね。。。経験上で不具合が発生しやすいと思わる点をあげさせて頂きます。
　原則としては案件の開発ルールやテスト観点／方針を必ず確認し、それらに準ずるかたちで作成するようにしてください。

#■単体テスト（プログラムテスト）
　単体テストとは、プログラムが設計書通り要求される機能を満たし正しく動作するかどうかをチェックすることです。
基本的にテストケースはプログラム構造設計書に記述されている、全処理パターンが対象となります。
すなわち、記述されたプログラムの全ルー トをテストすることがテストの目的となります。

**＜テスト仕様書を作成する際に抑えるべきポイント（例）＞**
　・境界値の判定（以下、未満、以上、超過、イコール）
　・関数パラメータの組み合わせ（全処理パターン、共通系除く機能固有の実装関数）
　・入力値などの各種バリデーション、又は、入力値とDB登録値の差異
　　⇒ 型、定義値、必須性、文字数、大文字／小文字、全角／半角、空白（NULL）
　・空値（未入力=''）、空白（半角／全角）、空白含む文字列値の判定や加工（trimなど）
　・エラーハンドリング（Exception）
　　⇒ エラー発生の検知可否、エラー原因の通知、エラーの判定ログ出力、ロールバック処理など
　　※設定や定義されていない値などがバグなどによって渡された場合、それに対するチェックおよび適切にエラー処理されることなど。

#■結合テスト
　結合テストは、プログラムテストの後に行われるテストで、いくつかのプログラムを組み合わせて、1つの機能として正しく動いているかを確認します。
例えば、プログラム間のデータの受け渡しや、画面遷移が正しく行われているかなどを確認します。

**＜テスト仕様書を作成する際に抑えるべきポイント（例）＞**
（※Webアプリの場合）
　・異なる複数ブラウザにて並行操作した場合の動作
　・複数タブにて並行操作した場合の動作
　・ブラウザバック（前画面へ）、ダブルクリックした場合の動作
　・GET／POSTパラメータを不正値に変更した場合の動作（hidden含む）
　　⇒ 不正値（定義値外）への考慮、セキリティテスト的な観点
　　　（ブラウザの開発ツールなどで編集可能な範囲）
　・入力値とDB登録値の差異（空白とNULLの差異、余白の有無、文字化け、桁落ち）
　・セッション制御がある場合、有効期限切れ時の動作
　・システム間連携時の通信障害時などの動作（レスポンスなし、タイムアウト時の考慮）

#■システムテスト（総合テスト）
　システムテストは、結合テストの後に行われるテストで、全ての機能を組み合わせて、1つのシステムとして、正しく動いているかを確認します。
ユーザの要件どおりに動いているか、機能間の連携はとれているか、性能（処理の速さなど）は問題ないかなどを確認します。

**＜テスト仕様書を作成する際に抑えるべきポイント（例）＞**
　・機能要件を満たしているか
　・性能要件を満たしているか
　・セキリティ要件を満たしているか（個人情報の扱いなども含む）
　・障害対策（メンテナンスモード、冗長化構成の切替可否(Web障害、DB障害)、バックアップからのシステム復元）

#■運用テスト（シナリオテスト／受入れテスト）
　運用テストは、開発が完了（システムテストが終了）したシステムに対し、実際のシステム利用者がテストを行い、業務運用上の支障がないかを確認するテスト。
基本的なテストの観点は、前述した通り、**「実際の業務に沿ってシステム動作を確認する」**ことだ。
通常業務シナリオに沿ったテストはもちろん、レアケース業務だったり、異常対応業務だったりと、様々なシナリオを業務視点で作成する。

**＜テスト仕様書を作成する際に抑えるべきポイント（例）＞**
　・運用者の誤操作によるデータ削除してしまった場合（復元可否、操作対象者の特定、など）
　・何らかの定義値（種別、区分など）を変更（追加、削除(無効化)、変更）した場合（機能要件に含む）

#■参考記事
+ [プログラミングとテストの要点](https://techfun.cc/devbase/devbase4.html])
+ [単体テストとは－テスト工程全体における位置づけとその役割－](https://engineer-club.jp/what-is-unit-test)
+ [テスト観点～概要と具体的な観点～](https://webrage.jp/techblog/software_testing_point_of_view/)
+ [単体テストで必要な観点とは何か？項目抽出の考え方を学ぶ](http://ackynonichijou.com/syskai/テスト/単体テストで必要な観点とは何か？項目抽出の考.html)
+ [システムテストとは？開発段階のテストの流れと主な種類](https://hnavi.co.jp/knowledge/blog/system_test/)
ソフトウェアアーキテクトの「形」

# 形 
武道の「形」の事。

**[日本剣道型](https://ja.wikipedia.org/wiki/%E6%97%A5%E6%9C%AC%E5%89%A3%E9%81%93%E5%BD%A2)より。**
> 剣道のおける稽古形。


# Architectural Katas（ソフトウェアアーキテクチャ形）
Ted Newardさんが構築したソフトウェアーキテクチャの練習。
[公式Home Page](https://archkatas.herokuapp.com/)

**公式Home Page「About」より**
> Architectural Katasは、少人数（3～5人）での練習を目的としていますが、通常はより大きなグループ（4～10グループが理想的）の一員として、それぞれが異なる形を行います。
> 司会者は、時間を管理し、形を割り当て（または、このサイトがランダムに選ぶことも可能）、エクササイズの進行役を務めます。
>
> 各グループには、開発が必要なプロジェクト（いろいろな意味でのRFP（Request For Proposal））が与えられます。
プロジェクトチームはしばらくミーティングを行い、「顧客」（モデレーター）に質問することで当初の提案書にはない要件を発見し、うまくいく可能性のあるテクノロジーのオプションを議論し、ソリューションがどのようなものになるかの大まかなビジョンを描き出す。
> そして、しばらく議論した後、プロジェクトチームは部屋にいる他のプロジェクトチームに自分たちのソリューションをプレゼンし、他のプロジェクトチームからのチャレンジ（難しいけど公平な質問）に答えなければなりません。挑戦の段階が終わると、部屋の中でその結果を投票し、次のプロジェクトチームが登壇する。

書籍「Fundamentals of Software Architecture」（ソフトウェアーキテクチャの基本）で知りました。
[書籍「Fundamentals of Software Architecture」Home Page](http://fundamentalsofsoftwarearchitecture.com)
[書籍「Fundamentals of Software Architecture」のArchitectural Katas Home Page](http://fundamentalsofsoftwarearchitecture.com/katas/)
[形リスト](http://fundamentalsofsoftwarearchitecture.com/katas/list.html)


# CodeKata（コード形）
Architectural Katasの歴史を読んでCode Katasがある事を知りました。
さまざまな言語で挑戦できる一連の練習です。
[公式Home Page](http://codekata.com/)
形は21種類あります。
Java Wordページの背景に色と画像を設定

<p><strong>今回はSpire.Doc for Javaというライブラリを使ってWordページの背景に色と画像を設定する方法を紹介していきます。</strong></p>
<p><strong> </strong><strong>下準備</strong></p>
<p><strong>1.E-iceblueの公式サイトから<a href="https://www.e-iceblue.com/Download/doc-for-java-free.html">Free Spire.doc for Java</a>無料版をダウンロードしてください。</strong></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210421/20210421110028.png" alt="f:id:lendoris:20210421110028p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<p><strong>2.IDEを起動して新規プロジェクトを作成してから、インストールされたファイルにあった相応しいSpire.doc.jarを参照に追加してください。</strong></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210421/20210421110044.png" alt="f:id:lendoris:20210421110044p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<h4><strong>背景に画像</strong></h4>
```JAVA
import com.spire.doc.*;
import com.spire.doc.documents.BackgroundType;
import java.awt.*;
import java.io.*;

public class WordBackground {
    public static void main(String[] args) throws IOException {

        String inputFile="Sample.docx";
        String backgroundImg="background.png";
        String outputFile="out/result.docx";

        //ファイルを読み込みます。
        Document document= new Document(inputFile);
　
        //背景のタイプを画像にします。
        document.getBackground().setType(BackgroundType.Picture);

        //背景に画像を設定します。
        document.getBackground().setPicture(backgroundImg);

        //保存します。
        document.saveToFile(outputFile, FileFormat.Docx);
    }
}
```
<h4><strong>実行結果</strong></h4>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210421/20210421110125.png" alt="f:id:lendoris:20210421110125p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<h4><strong>背景に色</strong></h4>
```JAVA
import com.spire.doc.*;
import com.spire.doc.documents.BackgroundType;
import com.spire.doc.documents.GradientShadingStyle;
import com.spire.doc.documents.GradientShadingVariant;
import java.awt.*;
import java.io.*;

public class WordBackground {
    public static void main(String[] args) throws IOException {

        String inputFile="Sample.docx";
        String outputFile="out/result3.docx";

        //ファイルを設定します。
        Document document= new Document(inputFile);
　　　　
//色を設定します。
        document.getBackground().setType(BackgroundType.Gradient);
        document.getBackground().getGradient().setColor1(Color.white);
        document.getBackground().getGradient().setColor2(Color.red);
        document.getBackground().getGradient().setShadingVariant(GradientShadingVariant.Shading_Down);
        document.getBackground().getGradient().setShadingStyle(GradientShadingStyle.Horizontal);

        //保存します。
        document.saveToFile(outputFile, FileFormat.Docx_2013);
    }
}

```
<h4><strong>実行結果</strong></h4>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210421/20210421110213.png" alt="f:id:lendoris:20210421110213p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<p> </p>
イメージの切り替え


```index.html
<div class="center">
        <div>
            <img src="img1.jpg" id="bigimg">
        </div>
        <ul>
            <li><img src="thumb-img1.jpg" class="thumb" data-image="img1.jpg"></li>
            <li><img src="thumb-img2.jpg" class="thumb" data-image="img2.jpg"></li>
            <li><img src="thumb-img3.jpg" class="thumb" data-image="img3.jpg"></li>
            <li><img src="thumb-img4.jpg" class="thumb" data-image="img4.jpg"></li>
        </ul>
    </div>
```
大きな画像（メイン）をdivタグで囲みます。
そして、その他のサブ写真をulタグで囲み、liタグでリスト化をします。
そして、それらをcenterで囲みます。

```index.js
const thumbs = document.querySelectorAll('.thumb');
thumbs.forEach(function(item, index) {
    item.onclick = function() {
        console.log(this.dataset.image);
    }
});
```
前回の記事で、querySelectorメソッドを使用しましたが、今回使用するquerySelectorAllは(cssセレクター)内で指定された値をすべて取得してくれます。
今回は、thumbを指定しているので、ulの中にある全てを取得してくれます。

今回、配列の繰り返し処理でfoeEachを使います。

文法は以下のようになります。
配列.forEach(function (item, index){
 処理内容
});

パラメータitemに配列の項目o番目の項目が入ります。二番目のパラメータでは、index番号が代入されます。
具体的な処理内容に入ります。
console.logのthisは、イベントが発生した要素を指します。今回では、data-image="img1.jpgになります。
htmlをみてみるとdata-imageとなっています。
これは、data-何でも好きな名前を付けても良いとなっています。
よって、(取得した要素(今回はonclick).dataset.何でも属性で付けた名前)になります。

このままでは、画像の切り替えができないのでJS側を書き換えて行きたいと思います。

```index.html
 document.getElementById('bigimg').src = this.dataset.image;
```

取得した要素（id▶bigimage).属性（src）（ここまでで読み取り） = 値(this.dataset.image)（ここまでで書き換え）になります。

>　出典
> https://www.amazon.co.jp/%E7%A2%BA%E3%81%8B%E3%81%AA%E5%8A%9B%E3%81%8C%E8%BA%AB%E3%81%AB%E3%81%A4%E3%81%8FJavaScript%E3%80%8C%E8%B6%85%E3%80%8D%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E7%8B%A9%E9%87%8E-%E7%A5%90%E6%9D%B1/dp/4815601577
Angular勉強会 #9 パイプ、DI導入

## Pipeとは
- Template構文の中で用いる、データ変換を行う仕組み
- Linux の パイプ処理 に概念的には近い
    - `ps | grep node` みたいなやつ

---


## Pipeの利用例
- i18n対応用にカスタムの言語辞書変換をPipeを使って実現する
  - http://www.ngx-translate.com/

```html
<div>{{ 'HELLO' | translate }}</div>
```

---
## 組み込みのPipe
- AsyncPipe
- CurrencyPipe
- UpperCasePipe/LowerCasePipe

他、以下のようなものがある。
https://angular.io/api/common#pipes

---
## 自作のPipe
`@Pipe` デコレータを利用したクラスを作成することで実現する。また、Componentと同様に`app.module.ts`の`declerarions` に追加が必要

```typescript
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({name: 'exponentialStrength'})
export class ExponentialStrengthPipe implements PipeTransform {
  transform(value: number, exponent?: number): number {
    return Math.pow(value, isNaN(exponent) ? 1 : exponent);
  }
}
```

---
## これまでのおさらい / Angularのポイント
- 依存関係や定義を明確に定義することで、パーツごとの管理をやりやすくする `module` 機構
- UIをページごと、部品ごとに分割し、再利用しやすくする `component` 機構
- UIとコードとのデータのやり取りを実現する `binding` 機構
- 異なるUI部品に対して共通的な処理を追加できる `directive` 機構
- 文字列や数値などのデータの変換処理を簡便に記述できる `pipe` 機構

--- 
## 最後は設計の話 / 依存性注入（Dependency Injection）について

---
## DIとは何か（再掲）
DIとはもともとはJavaなどのサーバーサイドの分野でよく用いられてきた、**疎結合を保ったまま依存関係を構築する**手法である。

DIを実現する仕組みをDIコンテナといい、Angularにもその仕組は組み込まれている。主な挙動としては以下のようになる。

1. サービスを利用するクラス側が、どのサービスが必要かを記述する。
2. DIコンテナにサービスを登録する
3. DIコンテナが起動時に依存性を解決し、生成したサービスをクラスに注入する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447106/841c6217-fd90-fd82-dc91-1c68c759e5c3.png)

---
## なんでそんなややこしいことするんですか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447106/91831565-41a1-ef91-e4f8-15792ba95176.png)

---
## DIのポイント
- 実クラスではなく、抽象クラス/インタフェースを参照することで、クラス間を疎結合に保つ
  - 変更の影響範囲の限定
  - テスタビリティの向上（モックの導入）
- 依存性を逆転させることで、モジュールの可搬性を上げる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447106/9525c57e-675f-38ca-7de5-fcb576bbcf8f.png)

---
## そして、Clean Architectureへ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447106/3c3ec050-6bf8-4a4c-1241-3c0424dff158.png)
Laravel+vueでなんか作る(Laravel基礎編①)

[Vue 3 and Laravel: A Practical Guide with Docker](https://www.udemy.com/course/vue-laravel-admin/)の備忘録

今回はアプリを作る～Dockerでmysqlと繋げるまでをやる

#Laravelでアプリを作る
1. Composerを入れる
2. 以下のコマンドを打つ

```bash
composer create-project --prefer-dist laravel/laravel 任意のアプリ名
```
3.作られたファイル内に``cd``し、``php artisan serve``して動くか確認


#Dockerでlaravelとmysqlを起動
1.``Dockerfile``と``docker-compose.yml``を``touch``する

```bash:Dockerfile
FROM php:7.4-fpm-alpine

RUN docker-php-ext-install pdo pdo_mysql
RUN curl -sS https://getcomposer.org/installer | php -- \
        --install-dir=/usr/local/bin --filename=composer

WORKDIR /app
COPY . .
RUN composer install

CMD php artisan serve --host=0.0.0.0
```
```yml:docker-compose
version: '3.8'
services:
  backend:
    container_name: backend
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 8000:8000
    volumes:
      - .:/app
    depends_on:
      - db

  db:
    container_name: db
    image: mysql:5.7.22
    environment:
      MYSQL_DATABASE: admin
      MYSQL_USER: root
      MYSQL_PASSWORD: root
      MYSQL_ROOT_PASSWORD: root
    volumes:
      - ./storage/dbdata:/var/lib/mysql
```
DBの設定に合わせて``.env``を変更

```:.env
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=admin
DB_USERNAME=root
DB_PASSWORD=root
```
``sudo service docker start``でDockerを立ち上げ、
``sudo docker-compose up``すれば起動
CROSS JOIN（交差結合）って何？

# はじめに
SQLには`CROSS JOIN`という結合構文がありますが、「これ使ったことないな。なんだろう？」と思ったので調べたことをメモしておきます。

# CROSS JOINとは？
`CROSS JOIN`は、各テーブルのレコードの全ての組み合わせを返します。別の言い方をすると、各レコードを要素とするテーブルという集合同士の直積です。

具体的には、以下のような結果を返します。

```
mysql> SELECT * FROM books;
+----+--------------------+----------+
| id | name               | owner_id |
+----+--------------------+----------+
|  1 | Clean Code         |        1 |
|  2 | Clean Architecture |        1 |
|  3 | SQL Antipatterns   |        2 |
+----+--------------------+----------+

mysql> SELECT * FROM users;
+----+-------+
| id | name  |
+----+-------+
|  1 | Alice |
|  2 | Bob   |
|  3 | Mike  |
+----+-------+


mysql> SELECT 
             u.id AS user_id,
             u.name AS user_name,
             b.name AS book_name
       FROM users AS u CROSS JOIN books AS b;
+---------+-----------+--------------------+
| user_id | user_name | book_name          |
+---------+-----------+--------------------+
|       3 | Mike      | Clean Code         |
|       2 | Bob       | Clean Code         |
|       1 | Alice     | Clean Code         |
|       3 | Mike      | Clean Architecture |
|       2 | Bob       | Clean Architecture |
|       1 | Alice     | Clean Architecture |
|       3 | Mike      | SQL Antipatterns   |
|       2 | Bob       | SQL Antipatterns   |
|       1 | Alice     | SQL Antipatterns   |
+---------+-----------+--------------------+
```
3 × 3 = 9個の結果が帰ってきますね。

ユーザーと所有している本の一覧は以下のように取得できます。

```
mysql> SELECT 
             u.id AS user_id,
             u.name AS user_name,
             b.name AS book_name
       FROM users AS u CROSS JOIN books AS b 
       WHERE u.id = b.owner_id;
+---------+-----------+--------------------+
| user_id | user_name | book_name          |
+---------+-----------+--------------------+
|       1 | Alice     | Clean Code         |
|       1 | Alice     | Clean Architecture |
|       2 | Bob       | SQL Antipatterns   |
+---------+-----------+--------------------+
```

これは`INNER JOIN`を使う一般的な方法と結果は同じです。

```
mysql> SELECT 
             u.id AS user_id,
             u.name AS user_name,
             b.name AS book_name
       FROM users AS u JOIN books AS b 
       ON u.id = b.owner_id;
+---------+-----------+--------------------+
| user_id | user_name | book_name          |
+---------+-----------+--------------------+
|       1 | Alice     | Clean Code         |
|       1 | Alice     | Clean Architecture |
|       2 | Bob       | SQL Antipatterns   |
+---------+-----------+--------------------+
```

# 最後に
今のところ`CROSS JOIN`が必要になるケースは思いつきませんが、とりあえずどういう結果が帰ってくる構文なのかは理解できました。
使う機会あるのかな〜笑

# 参考
[「Feedforce Developer Blog」cross join を知ると join が書きやすくなるよ、という話](https://developer.feedforce.jp/entry/2019/03/19/170000)
memcachedをflushしたあと最大１秒間データは追加できなくなる

# はじめに

古いPHPのコードのテストでmemcacheのflushまわりで変な挙動をしているので調べていたのですが、PHPのMemcache::flushのマニュアルのUser Contributed Notesに気になる[記述](https://www.php.net/manual/ja/memcache.flush.php#76364)を見つけました。

> Please note that after flushing, you have to wait a certain amount of time (in my case < 1s) to be able to write to Memcached again. If you don't, Memcached::set() will return 1, although your data is in fact not saved.

flushしたあと1秒待たないと、`set`が成功するけど実際にはデータが保存されないと言っているのですが、ソースを見たら本当にそうだったので仕組みを説明します。

# 仕組み

memcached の expire の仕組みはアイテムごとに期限を持っていて、データを取り出すときに期限が現在時刻より過去なら期限切れ判定してデータを開放する、という感じだというのはうっすらと知っていたのですが、flushのために追加で以下のようなことをしています。

* flushを実行すると、この時刻までのタイムスタンプを持っているアイテムはflushされたと判定するよという` settings.oldest_live`に現在の時刻(+与えられていればオフセット)を設定します。

* itemがflushされたか判定する関数`item_is_flushed()`ではitemのタイムスタンプ <=  settings.oldest_live ならflushされていると判定します

```C
int item_is_flushed(item *it) {
    rel_time_t oldest_live = settings.oldest_live;
    uint64_t cas = ITEM_get_cas(it);
    uint64_t oldest_cas = settings.oldest_cas;
    if (oldest_live == 0 || oldest_live > current_time)
        return 0;
    if ((it->time <= oldest_live)
            || (oldest_cas != 0 && cas != 0 && cas < oldest_cas)) {
        return 1;
    }
    return 0;
}
```

時刻の精度は秒なので、flushを実行したのと同じ秒の間は新しいアイテムを追加してもタイムスタンプが同じになるのでflushされたアイテムであるという判定になってしまいます。これがデータが保存されない仕組みです。(正確には保存されるけどflushされていると扱われるので取り出すことができません)
プライバシーポリシー承認パネル

![IMG_1187.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/75137354-6389-2e93-50d2-7c3b03032974.jpeg)

#cookieとは
クッキーとは、ブラウザに保存される小さなデータです。クッキーので保存されたデータは、ブラウザとサーバー（ミドルウェア）の間で送受信されます。
JSからクッキーのデータを扱う場合は、以下のようなときです。
①簡易的なアンケートなどで過去に回答したことがあるか
②過去にボタンをクリックしたことがあるか
③そのWebサイトに何度訪問したことがあるか
④文字や背景色、使用言語などを変更できるサイトの設定情報

クッキーには、変数名＝値という形で、データが保存されています。これをクッキーデータといいます。

```index.js
const agree = Cookies.get('cookie-agree');
const panel = document.getElementById('privacy-panel');
if(agree === 'yes') {
    document.body.removeChild(panel);
} else {
    document.getElementById('agreebtn').onclick = function() {
        Cookies.set('cookie-agree', 'yes', {expires: 7});
        document.body.removeChild(panel);
    };
}

// クッキー削除（テスト用）
document.getElementById('testbtn').onclick = function() {
    Cookies.remove('cookie-agree');
};
```
```index.html
<div id="privacy-panel">
    <p>当サイトではユーザーエクスペリエンス向上のためクッキーを使用しています。また、匿名でアクセス状況のデータを収集しています。詳しい情報は当サイトのプライバシーポリシーをご覧ください。</p>
    <button id="agreebtn">承認する</button>
</div>
```

定数agreeにcookies-agreeという値を代入しています。
ここで、Cookies.getというメソッドが出てきます。これはjs-cookieライブラリが提供するものです。
*ライブラリとは、JSで複雑化する処理が複雑化するので、それを防ぐための補助プログラムです。今回つかうクッキーライブラリはオープンソースとして公開せれています。

この時点でのクッキーは、まだ定義されていない状態です。

定数panelに定数agreeの内容を代入しています。更に、privacy-panelに紐づけています。つまり、html側のprivacy-panelが代入されたことになります。

定数agreeの値がyesの場合は、定数panelの値を削除していきます。

ここで、document.body.removeChild(panel);を使用します。
bodyは取得した要素.removeChild(削除する要素)となります。
documentオブジェクトのプロパティーはbodyになります。

承認ボタンのイベントも設定していきます。agreebtnを取得します。そして、イベント設定を行います。
cookie-agreeに値yesを設定します。
{}内は、expires: 有効期限（今回は７日）に設定します。
このクッキーは設定しなかったな場合、ブラウザを閉じた時点で消えてしまいます。

また削除処理を行った後に、パネルをすぐに非表示にする必要があるので、
document.body.removeChild(panel);を追加します。

> 出典
> https://www.amazon.co.jp/%E7%A2%BA%E3%81%8B%E3%81%AA%E5%8A%9B%E3%81%8C%E8%BA%AB%E3%81%AB%E3%81%A4%E3%81%8FJavaScript%E3%80%8C%E8%B6%85%E3%80%8D%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E7%8B%A9%E9%87%8E-%E7%A5%90%E6%9D%B1/dp/4815601577
amplifyチュートリアル行ってみた

#はじめに

こんにちは。ふじむーです。
2021年4月より、未経験からフロントエンドエンジニアとして働きだしました。

先日、社内で使用している技術について調べてLTすることになりました。
今回は、AWSの「Amplify」です！

本記事は、その時発表したものをアウトプットすることを目的としています！
もし誤りなどございましたら、コメントいただけると幸いです！！

#もくじ

1. Amplifyとは
2. Amplifyチュートリアルやってみました
2. 今後必要そうな学習
2. 参考にした記事

#Amplifyとは

![aws-amplify.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697823/1c83eaf8-b7a0-4f37-f310-a7a0dbca3f79.png)
結論、AWSが提供しているアプリ開発するためのプラットフォームです。
アプリ開発のために必要なものがすべて含まれている！と個人的には理解しました。

Amplifyでは、アプリ開発のために以下の２つが用意されています。

- Amplify framework
- Amplify Developer Tools

開発を速度を高めるためにAmplify独自の以下のようなframeworkが用意されております。

- クライアントライブラリ
- UIコンポーネント
- DataStore
- CLI

なかでも、CLIは導入することで、amplifyコマンドが使用できるようになります。
このおかげで、とても直感的に操作しやすくなる印象でした。


#Amplifyチュートリアルやってみました

現在弊社ではvueを使用して開発をしているため、
[こちら](https://docs.amplify.aws/start/getting-started/installation/q/integration/vue)のチュートリアルを行ってみました。

内容は簡単なtodoアプリを作成し、web常に公開するものです。

![amplify.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697823/d66a0f96-43a5-6d2e-8672-566a5fe96fec.gif)

### 感想その１　公開まで早い！

30分くらいでweb上に公開できました。
もちろん、手軽な内容のアプリかつチュートリアルということもありますが、
EC2にRailsアプリをデプロイするときと比べて全然早かった印象です。

早かった理由として、個人的には環境構築系がほとんどなかったことが大きいのかなと思いました。

EC2の時は、rubyをインストールすることから始まります。
amplifyではframeworkのおかげもあり、
何かインストールする作業はありませんでした。

amplifyでは最低限以下の手順でweb上に公開できました。

1. amplify initする
1. graphQLの設定をする
1. amplify pushする
1. amplify hosting　amplify publishする

git操作のような感覚で行えます。

### 感想その2 CLIのおかげで直感的に操作できる。

amplifyを使用する場合、はじめにcliをインストールします。

```
$ $ npm install -g @aws-amplify/cli
```

こちらをいれることで、amplifyコマンドを使用できるようになります。
amplifyコマンドによって直感的に操作しやすくなります。

例えば、、、

- 認証機能をつけたい！ 
👉　amplify add auth

- 機能を追加したい！
👉amplify add api

- ファイルを保存できるようにしたい！！
👉amplify add storage

これらのコマンドを入力するだけで、勝手に必要なファイルを生成してくれます。

#今後必要そうな学習

amplifyはモダンなフレームワークのみ対応しているので、
Reactやvueといったモダンなフレームワークを学ぶ必要があると思います。

また、バックエンド側のやりとりはGraphQLが行っているので、
GraphQLを学ぶ必要があると思います。

# 最後に

これはもしかしたら私だけかもしれないのですが、
amplify initを行っていた時に、カーネルパニックを起こすことがありました。

OSが最新でないとカーネルパニックを起こすことがあるということなので、
BigSurにあげてみたところ、問題なく動作しました。

ちなみに、その時（2021/04/04）はCatalina OSでした。

#参考にした記事

 - [これから始めるAmplify](https://d1.awsstatic.com/ja_JP/startupday/sudo2020/SUD_Online_2020_Tech06.pdf)
 - [チュートリアル](https://docs.amplify.aws/start/getting-started/installation/q/integration/vue)
 - [Amplifyで始める、サクッとアプリ開発](https://aws.amazon.com/jp/builders-flash/202103/amplify-app-development/?awsf.filter-name=*all)
この＜Link>タグで囲むと文字が青色になってしまうのを防ぎたい

Reactなどでアプリを作成していると、ページの切り替えをしたい時にLinkを用いる事があると思います。
例えば、ヘッダーの要素を別の色で設定していたのにリンクで囲ったら青になってしまった。これだけで「バグか？」などと初心者の私は思ってしまいます。しかし、リンク自体は機能していて、ページ遷移は出来るのでちょっと調べてみました。

>参考リンク: [stack overflow](https://stackoverflow.com/questions/46102586/change-default-color-of-link-from-blue-to-white)


##症状##
![Screen Shot 2021-04-20 at 15.29.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825163/70bbe757-e789-9b5a-6f9c-0abdd71267e1.png)

こちらの例ではヘッダーの右側部分にある４つのタブになります。
本来であれば違う色にしたかったのですが、それぞれをLinkタグで囲むと謎のブルー？紫？になってしまいました。

リンク自体は機能しているので試しにProjectsをクリックしてみると、、、
![Screen Shot 2021-04-20 at 15.31.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825163/a8d9e3fe-2f1f-9b94-bd99-8da8793d3067.png)

赤い。
どこかで見た事のある動きだと思ったら、aタグの挙動と同じですね。
確かに、LinkってHTMLでいうところのaタグにあたります。
つまり、Linkタグで要素を囲むと要素のカラーはaタグのデフォルト値であるブルーに適応されてしまいます。
これを直す為にはいくつか方法がありますが、今回は要素が４つあるのでまとめて設定できるmodule.scss(css)で見ていきましょう。まずはそれぞれ４つのLinkタグに対して divタグで囲ってClassNameを割り振っておきます。それをcssファイルの方でいじくります。

aタグのデフォルトカラーを直したいので、aに対してスタイルを当てます。
![Screen Shot 2021-04-20 at 15.42.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825163/fbda08c4-9c3d-bb3e-d7d2-5057fd1dde81.png)

カラーはピンクで、hover効果に適当な水色を当ててみました。
すると、![Screen Shot 2021-04-20 at 15.27.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825163/45b5cd4c-31ba-7bec-3407-1f8b214b57f6.png)

このようにローリーポップなカラーにする事ができました。カワイイですね。
（（注）こちらの記事は182センチ88キロの元体育会系男子によって書かれています。）

##最後に##
私と同じような初学者はみんな一旦ここでつまづくだろうと思い記事にしてみました。
英語記事にはなりますが、cssファイルからではなく直接Linkタグにスタイルを当てる別の方法も[「こちら」](https://stackoverflow.com/questions/46102586/change-default-color-of-link-from-blue-to-white)に記載されていますので参考になさってみてください。
Salesforce ユーザの基本 ⇒ Salesforce システム管理者との連携

１．Salesforce システム管理者は何を行いますか?
２．標準プロセスでパスワードをリセットするには何をする必要がありますか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/c8412c70-ec8b-2089-4215-450369f562e9.png)
Jetson Nano 初期設定手順 

#はじめに
Jetson Nanoに関する初期設定の手順を纏めておきます。
2021年4月時点での情報です。

#設置の流れ
1.Jetpackの設置 (Jetson Nano用 Ubuntu + その他のプログラム)
2.TensorFlowの設置
3.Python IDE(PyCharm)の設置
4.OpenCVビルド
5.空冷ファンの購入
6.AI推論

#各設置に関する情報
###1.Jetpackの設置 (Jetson Nano用 Ubuntu + その他のプログラム)
下記のリンクのページに入り、Jetson Nano用のJetpackを設置します。2021年4月時点でVersionは4.5です。
https://developer.nvidia.com/embedded/learn/get-started-jetson-nano-devkit
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/54fd5a4e-268a-b661-5413-4357445b28b0.png)

###2.TensorFlowの設置
下記のリンクのページに入り、Jetson Nano用のTensorflowを設置します。2021年4月時点でVersionは2.xxです。
https://docs.nvidia.com/deeplearning/frameworks/install-tf-jetson-platform/index.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/db496c17-256e-2702-21ed-4f6a0f19e133.png)

###3.Python IDE(PyCharm)の設置
下記のリンクのページに入り、Jetson NanoにPyCharmを設置します。
https://kokensha.xyz/linux/jetson-nano-pycharm/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/85c5b31b-d541-c025-9a71-a972c1b05c67.png)

###4.OpenCVビルド
下記のリンクのページに入り、OpenCVをビルドします。これによりOpenCVでCUDAが使えるようになります。
install_opencv4.5.0_Jetson.sh　をダウンロードし、実行してください。ビルドが終わるまで約3時間程度かかります。
https://github.com/AastaNV/JEP/tree/master/script
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/89580abf-bc67-881a-ebb4-7d0b4f8f1609.png)

###5.空冷ファンの購入
PWM制御ができる4pinの空冷ファンの購入をお勧めします。Noctua社のNF-A4x20が有名ですが、ケーブルが太い問題と色がJetsonに合わない短所があります。（個人的な意見ですが）
そこで、私のおすすめはこちらの製品です。中華製のファンですが、ケーブルが細く、色も黒でJetsonと合うと思います。そして、価格がNoctua社半分程度で、実際に付けてみたら音も静かで問題はありませんでした。

https://amzn.to/32tUBIi
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/0b503b4c-3e1c-049e-f2ac-3ba89fcc628b.png)

###6. AI推論
まず、Hello AI World　NVIDIA JETSONを実行することをお勧めします。
画像認識、物体検出、セグメンテーションの3兄弟をPython, C++で実行するといいと思います。
処理速度が速くて驚きました。
https://github.com/dusty-nv/jetson-inference/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/1fd9fe67-a8ef-b1c1-814f-dc9efa40e344.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/06a575f0-fde2-bc69-60da-a3bbfb0f0041.png)
EC2インスタンスのリージョンを超えてのコピーをしてみる

## 概要

EC2インスタンスを東京リージョン→大阪リージョンにコピーしてみようと思います。

## AMIの作成

- (コピーしたことがわかるように)ファイルを作成

これは、別にしなくて良い作業です。
データが移ってうことがわかりやすいようにしているだけです。

```
$ cat << EOF > /home/ec2-user/hello.txt
Hello World!
EOF

$ cat /home/ec2-user/hello.txt
Hello World!
```

- EC2インスタンスのシャットダウン

マネジメントコンソールからインスタンスの停止を行います。
起動していてもAMIは作成できますが、ここでは落とします。

![2021-04-201インスタンス _ EC2 Management Console - Google Chrome 20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/aa88f2e9-2aff-e8b3-38fd-d0d11eee8b8e.png)


- AMIの作成

インスタンスにチェックを入れ、
アクション > イメージとテンプレート > イメージを作成 でAMIを作成していきます。

![2021-04-20 2# EC2インスタンスのリージョンを超えてのコピーをしてみる • (めも) - Sublime Te.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/e44435c7-71b0-b1c0-e9e7-540701c17feb.png)


- イメージを作成

イメージの設定を記載していきます。
イメージ名とイメージの説明だけ記載し、タグなどは特に変更しません。

![2イメージを作成 _ EC2 Management Console - Google Chrome 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/6237dcf4-2794-238d-36a1-e7e907561831.png)


- AMI作成確認

イメージ > AMI から作成されていることを確認します。

![2021-04-20 4AMI _ EC2 Management Console - Google Chrome 2021-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/1aa163df-92f9-4c4a-3a6f-8b4ab91caa68.png)


## AMIのリージョンコピー

- AMIのリージョンコピーを行う

AMIの作成が完了したらリージョンのコピーを行います。
AMIを指定し、 アクション > AMIのコピーへ進みます

![2021-04-20 5AMI _ EC2 Management Console - Google Chrome 2021-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/10b6016a-af68-1aee-9988-eefb2ed42ce8.png)


- コピー先のリージョンを指定

AMIのコピー先などを指定します。
送信先リージョン以外はすでに入っているので、そのままコピーに進むと完了画面が出ます。

![2021-04-20 6AMI _ EC2 Management Console - Google Chrome 2021-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/5f4299fa-c6b1-4228-eabb-f70c3a210edb.png)


- 大阪リージョンにコピーされていることを確認

大阪リージョンのAMIを確認するとコピー中であることが確認できます。

![2021-04-20 7AMI _ EC2 Management Console - Google Chrome 2021-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/73362a15-a17b-2e81-9c2c-fc81a07e27eb.png)


## AMIからEC2インスタンスの起動

- AMIからEC2インスタンスの作成

AMIからEC2インスタンスを作成していきます。

![2021-04-20 8AMI _ EC2 Management Console - Google Chrome 2021-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/97e8c944-13ae-e732-943b-34b80aa1444b.png)


- EC2の設定を行う

EC2インスタンスの設定はほぼ初期状態なので、[こちら](https://qiita.com/miyuki_samitani/items/61e1548cb61f4053e78d) をごらんください

- インスタンスの作成完了

大阪リージョンにEC2インスタンスが作成されました

![2021-04-20 9インスタンス _ EC2 Management Console - Google Chrome 20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/10216b95-9c1d-161f-e851-3fc69991d558.png)


- ログイン

以下のコマンドでログインします。

```
ssh -i [pemファイル] ec2-user@XXXXXX
```

- 元のインスタンスのデータが残ってるか確認

AMIを作成する前にテキストファイルをおいてましたが、データが残っていたので表示されました。

```
$ cat /home/ec2-user/hello.txt
Hello World!
```

## 勉強後イメージ

やり方とかは知ってたけど、実際どうやってコピーするとかは知らなかったから
やっててよかったと思います。
pysptk で numpy.dtype のサイズエラーが出た場合の対処法

## 背景
pytest で pysptk で実行時に 

```
ValueError: numpy.dtype has the wrong size, try recompiling. Expected 88, got 80 出た場合 
```
が出る。

## 前提
以下の場合に発生する可能性あり

- tensorflow==2.4.1
- numpy==1.19.5

## 解決策
以下で解決

```
pip install pysptk --no-binary :all:   
```
EKSでPodとNodeの水平スケーリング

## はじめに
執筆開始日は2021年2月8日です。
環境はAmazon EKS(v1.18),Istio 1.7の環境で確認した内容です。

### 採用技術
この記事では下記技術の動作概要や取り組んだポイントについて記載します。

- Horizontal Pod Autoscaler
- Cluster-Autoscaler
- AWS Node Termination Handler

### Horizontal Pod Autoscaler (HPA) は何をしてくれる？

Podの負荷（CPU使用率・Memory使用率）によって水平スケーリングを自動で行ってくれます。
HPA単体では動作せず、Metrics-Serverによって行われるリソース監視の結果と連携し動作します。
負荷がしきい値を上回ればスケールアウトし、下回った状態が続けばスケールインしてくれるいい感じのやつです。

HPAのKubernetes APIとして`autoscaling/v2beta2`がKubernetes 1.18で導入され、新しく追加された機能もあります。
例えば「スケールインを行わない」といった設定を加えることができます。

```yaml
spec:
  behavior:
    scaleDown:
      selectPolicy: Disabled
```
Kubernetes - Horizontal Pod Autoscalerより

"トラフィックの急増を繰り返すことが予期されていて、サービス提供時間内はスケールインを行わない”といった
ポリシーでの運用であればこのようなスケールイン自体を無効にすることも有効と思えます。

### Cluster-Autoscaler(CA)は何をしてくれる？

Nodeの水平スケールまたは垂直スケールを自動で行ってくれます。
例えば、上述のHPAでPodのスケールアウトが行われますが、無限にスケールアウトできるわけではありませんよね。
Nodeのリソースを使い切った状態から、さらにもう一つのPodを起動しようとしたとき
Pod分のリソースが確保されるまでPodのステータスはPendingとなり起動できません。
`Cluster-Autoscaler`では、そのPendingを検知することでAWSの`Autoscaling API`を叩いて新規にNodeを立ち上げてくれます。

一つ注意しておきたいのは、`AutoScaling グループで指定した最大キャパシティを超えるスケールアウトはできない`点です。
予め幅を持たせた最大値を設定することで、トラフィックが集中したときに対応可能になると思います。
また、`最小キャパシティを下回るNode数へのスケールインもできません。`

### AWS NodeTerminationHandler(NTH)は何をしてくれる？
EKSクラスタのスケールインの際、AutoScalingグループがNodeを終了させる動作が発生します。
終了するNode上で起動されたPodも当然のことながら巻き添えを食らい、別のNodeで起動しなければならなくなり
ダウンタイムが発生することに繋がります。

`NodeTerminationHandler(NTH)`を導入することによりPodのダウンタイムを大幅に減少させることが可能となります。
もう少し丁寧に言うと、Nodeが終了状態(Teminated)になる前に、別のNodeへPodを移動させてくれるのがNTHの主な動作です。

k8s-Node-Drainerも候補に挙がり、どちらを採用するか実際に動かしてみましたが、大きな違いは無いように見えました。
Amazon EKSに導入するのであればスポットインスタンスとオンデマンドインスタンス両方に対応してくれるNTHのほうが良いかなとも思えます。

NTH導入時には次の設定をAWSリソースに追加する必要があります。
- Autoscalingグループのライフサイクルフック
- Amazon EventBridgeのトリガーとターゲット
- Amazon Simple Queue Service

処理フローとしては、

```
1. NodeのTeminatingをEventBridgeで検知。
2. EventBridgeはSQSキューへ連携。
3. NTHがSQSキューを確認していて、インスタンスIDなどの情報を受け取る。
4. NTHがSQSキューのメッセージを削除。
```

もっと突っ込んだ話をすると、NTHが処理3で受け取った情報を元に、
終了するNodeに対して`drain`と`cordon`を行います。
そうすることで、`終了するNodeへの新規スケジューリングをできないようマーク(cordon)`し、
`別NodeへのPodの退去(drain)`が行われます。

このように、NTHは各リソースと連携しながらダウンタイムを減少させてくれます。

### 少しだけ気をつけたいポイント
#### PodDisruptionBudget
Nodeのスケールインが行われる時に、サービス提供Podが全て落ちてしまう場合があります。
この事象を回避するには`kind: PodDisraptionBudget` で
minAvailableや maxUnavailableをサービス提供Podへ適用し、
`EKSクラスタとして「最低N個のPodは生かしておかなければならない」といった制約を持たせ、
全断を防いであげるような設定`も必要になります。

#### コネクションのDraining
istioのingressgatewayの振る舞いをログから見ると、Pod終了前に5秒間だけ待機してくれているようなのですが
コネクションを切断せずに落ちてしまい、クライアントから見るとタイムアウトを引き起こすことがありました。

ingressgatewayのDeploymentではgracefulTerminationPeriodが30秒で設定されているのですが、
どうにも効いているようには見えません。istioの開発コミュニティを覗くと似たようなissueがボロボロと出てきたので既知のバグかもしれません。

### おわりに
スケーリング機能をEKSクラスタへ追加することはAWSでELBやターゲットグループを使用するのと同じくらい重要なことであると思っています。
それほど重要な部分について触れることができたことや、EKSの周辺リソースにも触れることができ、濃厚な時間を過ごせました。
正直に楽しかったと言えます。

また何か触って楽しくなっちゃった時に、このような記事を書きたいと思います。
誰かの参考になりましたら幸いです。
Gravio Zigbeeレシーバーのファームウェアをバージョンアップする

新しいGravio LEDマトリックスを使っていて、どうも不調な状況が続いていたのでよくよく調べたら、Gravioレシーバーのファームウェアが 0.9.2.0と古いことが分かったので 4.2で追加された方法でアップデートしてみた。
ちなみに、Gravio 4.2ではWindows版もしくはmacOS版のHubKitがインストールされたPCでしかGravioレシーバーのファームウェアバージョンアップはできないので、今回はWindows版のHubKitが入ったPCを使います。

# 使用環境

* Windows 10 Pro 20H2
* Gravio HubKit v4.2.5566.0
* Gravioレシーバー

# 手順
## GravioTools 4を起動
スタートメニューからGravioTools 4を起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/7e636473-cf08-1e6c-cf88-58172a107c2d.png)

起動するとタスクトレイにGravioアイコンが表示されます。

## HubKitの停止
HubKitが実行中であれば、停止しておきます。停止しないとGravioレシーバーがHubKitから使用中となるため、ファームウェアのバージョンアップはできません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/5924d688-53ef-4f14-c432-521107953310.png)

## GravioToolsの設定画面を起動
GravioTools 4から設定画面を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/bf6cb7e2-b7ed-307a-ded8-8a89c789fe1a.png)

するとこんなダイアログが開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/b2af1151-fa59-736a-943a-158dff3e2067.png)

## ファームウェアのバージョンアップ
ファームウェアタブに移動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/bb761dec-801f-6245-6eae-5045f12f2736.png)

現在のバージョンが表示されていないと思いおますので、「確認する」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/4ca68855-adbd-f943-ada1-468d0258eee3.png)

ちなみにHubKitを停止しておかないとこのようにボタンがグレーアウトされますので、かならずHubKitを停止させてから実行しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/8d4534e6-05f1-e826-8939-d40e6f8cb896.png)

バージョンが取得できたらこのように現在のバージョンも表示されます。`0.9.2.0`になってますね。最新のバージョンは`0.9.3.1`だったので、これが原因で不調だったようです。
さっそく「アップデート」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/f19daf1c-aaee-c68b-c011-5f740058e4a2.png)

アップデートには数分かかりますので、気長に待ちましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/164b18f4-5644-7f61-23c3-7d435dccceb4.png)

終了すると現在のバージョンも`0.9.3.1`になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/ec6b5fce-6ca7-11c2-f8a2-2e3fdfc836ca.png)

ちなみに、ファームウェアをバージョンアップしてもペアリング情報はそのまま保持されていますのでご安心ください。
このままラズパイに差し替えたら問題なく動くようになりました。＼(^o^)／

# ポイント
* GravioレシーバーのファームウェアバージョンアップはHubKitに同梱されているGravioToolsを使用する
* 4.2ではWindows版もしくはmacOS版のHubKitにのみ同梱されている
* ファームウェアをバージョンアップする際は、かならずHubKitを停止させておく
* ペアリング情報はバージョンアップ前後で保持されている
* ファームウェアはダウンロードされるので、必ず外部インターネットに接続されている必要がある

# 参考
* [Gravio][]
* [Zigbee firmware のアップデート方法](https://doc.gravio.com/manuals/gravio4/1/ja/topic/zigbee-firmware-update)

[Gravio]:https://www.gravio.com/jp
VSCode拡張機能Jupyterを.vsixファイルからインストールできない

~~v2021.8から.vsixファイルから普通にインストールできるようになりましたので、以下の作業は不要です（2021年7月追記）。~~

# 備忘メモ
オフラインでVisual Studio Codeを使っている場合、拡張機能は.vsixファイルからインストールしますが（[こちら](https://qiita.com/ss_tom_jp/items/5977e4f16d78b8ca7cc8)を参照）、[拡張機能Jupyter](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter)をインストールしようとした際に問題が発生しましたので、その対処法を説明します。

## トラブル
拡張機能Jupyterを、ダウンロードした`.vsix`ファイルからインストールしようとすると次のようなエラーメッセージが表示され、インストールできませんでした。Visual Studio Codeを最新版にしても同じメッセージが表示されます。

>日本語
>>「拡張機能 'ms-toolsai.jupyter' は、VS Code '1.55.0' と互換性がないため、インストールできません。」
>
>英語
>>「Unable to install extension 'ms-toolsai.jupyter' as it is not compatible with VS Code '1.55.0'.」

## 対処法
（バージョン情報やファイル名は21年4月時点のもの。適宜読み替えてください。）

**STEP 1** `ms-toolsai.jupyter-2021.6.755784270.vsix`ファイルの拡張子を`.zip`に変えて、中身を解凍します。

**STEP 2** 解凍したファイルのうち、`./extension/package.json`ファイルの`"engines":{...}`部分を以下のように変更します。

```json:./extension/package.json（変更前）
    ...
    "engines": {
        "vscode": "1.56.0-insider"
    },
    ...
```

```json:./extension/package.json（変更後）
    ...
    "engines": {
        "vscode": "^1.55.0"
    },
    ...
```

**STEP 3** 解凍したファイルを再度zipで圧縮し、拡張子を`.vsix`に戻して、このファイルからインストールします。

## 参考
https://github.com/microsoft/vscode-jupyter/issues/5244#issuecomment-805002536
【超初心者必見】gitの使い方をマスターする③

【超初心者必見】gitの使い方をマスターする①
https://qiita.com/ryu110/items/c8c6deecddd66dad6b11

この記事は超初心者必見】gitの使い方をマスターする②の続きです。
https://qiita.com/ryu110/items/9db9d95a260971ab3e41

⑩新しくブランチを作成する。
今いるbranchを確認する。
現在のbranchが確認でき、かつ、作成したbranchも確認できる。

```
git branch
```

新しいbranchを作成する場合。
branch名のところに作成したいブランチの名前を入力する。

```
git branch branch名
```
作成したブランチに移動したい場合

```
git checkout branch名
```
もしブランチを作成してそのまま作成したブランチに移動したい場合

```
git checkout -b branch名
```
branchBのブランチで作成したファイルをbranchAのブランチでも使いたい場合
例えば、現在はAのブランチにいるとします。
下記のように記入すればbranchBの内容をbrancghAにも取り組むことができる

```
git merge branchB
```
ブランチを削除したい場合

```
git branch -d branch名
```
⑪confrictの対象方法

別のブランチでも同じファイルの中を修正して両方のブランチでgit commitをした場合
この場合はgit mergeの時にconfrict（衝突）します。２つのブランチで同じ個所に変更があるので、どちらのコードを残すべきなのかわからないからです。
解決策としては片方のコードに書き換えることです。
下記を入力するとconfrictしている内容がでてくるので、いらないコードのほうを削除して、片方だけ残します。

```
git merge 取り込みしたいbranch名
```
confrictとでてくるので、vimでファイル編集

```
vim index.html
```
confrictの内容↓

```
Hellowwwwwwww
<<<<<<< HEAD
I have a pen.
=======
aaaaaaa
www
>>>>>>> master
```
今回はmasterの内容を取り込んでみます。
その場合、下記のコードのみ残します。

```
aaaaaaa
www
```
これで保存すれば問題なくgit addからのgit commitができます。

⑫分かりやすいようにタグをつける
git commit をすると1つ1つに対して一意のidがつきますが、わかりずらいので分かり易いように変更するのがタグ。
直近のコミットに対してタグをつける場合
今回のタグ名はNo.1にしました。ここは自由に変更してください。

```
git tag No.1
```
その後に、下記のように書くとtagの一覧がでます。

```
git tag
```
コミットした内容を知りたいときにtagをつけとけばすぐに確認できる。No.1はtag名です。

```
git show No.1
```
直近ではないコミットに対してタグをつける場合
No.0は自分がつけたいタグ名。
b6qcq7we8dgwwsdは自分がタグ名をつけたいコミットのidを入力。（充分な桁数があれば全ての桁を入力しなくてもよい）

```
git tag No.0 b6qcq7we8dgwwsd
```

タグを削除したい場合
No.1は自分が削除したいタグ名です。

```
git tag -d No.1
```

⑬gitの様々な短縮名（エイリアス）をつける方法

例えば、git checkout などは長いので打つのが大変です。
それを短縮した形で登録ができます。

例えば、git checkoutを短縮する場合

```
git config --global alias.co checkout
```

git statusを短縮する場合

```
git config --global alias.st status
```

git branchを短縮する方法

```
git config --global alias.br branch
```

git commit を短縮する方法

```
git config --global alias.ci commit
```

これらの設定をした後に登録状況を確認したい場合

```
git config -l
```

⑭複数人で共同で作業を行う時に、共有のリポジトリを作成する方法

共有レポジトリはshare.gitのようにファイル名.gitとするのが一般的。例えば、Aさんはbig、Bさんはsmallというディレクトリを管理しているとします。

共有レポジトリを作成

```
mkdir share.git
```

レポジトリを開く

```
cd share.git/
```

gitを共有レポジトリで使えるようにする。

```
git init --bare
```

Aさんが共有レポジトリに自分の内容を加える。（既にAさんはbigというレポジトリを持っていることにする）
originは追加する名前なので何でもよい。
share.gitは共有レポジトリの名前。

```
git remote add origin ~/share.git
```

これもまたgit config -lで内容は確認できます。

その後に、共有レポジトリに対して内容を加える。

```
git push origin master
```

次にBさんも共有していきます。
下記の作業だけで共有ができます。
これでAさんのコミットも共有ができる。

```
git clone ~/share.git/ small
```

これでまたファイルの内容を変更したときにgit addからのgit commitをしてあげて、その後に下記のように書けば共有レポジトリに共有されます。今回はBさん側からコミットをしています。

```
git push origin master
```

この内容をAさんが引っ張ってくる場合

```
git pull origin master
```

複数人で共有する時の良くありがちなエラーは、同じファイルの同じ行に修正を入れて、1人がgit pushをしていてもう一人がまだgit pullをせずに最新の状態ではない時にgit pushをした時にエラーになります。これを解決するには、git pull origin masterでまずは最新の状態を持ってきて、コンフリクトするので、vimコマンドで自分の編集か他の人が変更した編集かどちらかを決めて、その後にgit pushをすれば解決します。
JAVAの基本データ型の扱いについて

# JAVAの基本データ型の扱いについて

Javaのデータ型は基本データ型と参照データ型の2つの型に分類でき、各データ型の説明は以下の
以下の通りです。

| データ型 | 説明 |
| :----: | :----: |  
| 基本データ型 | Javaによって最初から定義されており、整数や文字等のリテラルを直接代入できる |  
| 参照データ型 | ユーザーが定義したクラス、配列等、基本データ型以外のデータ型 |  

<br />
基本データ型には8種のデータ型があり、各データ型で扱えるリテラルの種類と範囲は下記の通りです。  
<br />
<br />  

| データ型 | リテラル | 値 |  
| :----: | :----: | :----: |  
| char | 文字 |\u0000 ~ \uFFFF |  
| byte | 整数 | -128 ~ 127 |    
| short | 整数 | -32768 ~ 32767 |  
| int | 整数 | -2147483648 ~ 2147483647 |  
| long | 整数 | -9223372036854775808 ~ 9223372036854775807 |  
| float | 浮動小数点数 | 1.4E-45 ~ 3.4028235E38 |  
| double | 浮動小数点数 | 4.9E-324 ~ 1.7976931348623157E308 |  
| boolean | 論理値 | true,false |  

<br />  

## 別のデータ型同士での代入  

これらの整数、浮動小数点数リテラルを扱うデータ型の変数は値の範囲が小さいデータ型から大きいデータ型への値の代入は暗黙の型変換が行われるため可能です。  

``` JAVA
int i = 123;
long d = i;
System.out.println(d);
```
実行結果

```
123
```
値の範囲が大きいデータ型から小さいデータ型への代入はキャストによる変換が必要になります。  
※キャストによる変換を行わずに代入を行おうとすると例外（エラー）が発生します。

``` JAVA
long d = 123;
//キャストによる変換と代入
int i = (int)d;
System.out.println(i);

//下記の様にキャスト変換を行わずに代入しようとするとエラーになります
//int i = d;
```
実行結果

```
123
```

## 基本データ型から参照型への変換
基本データ型を参照型として扱うためのクラスがJavaでは提供されています。

| 基本データ型 | 参照データ型 |  
| :----: | :----: | 
| char | Character |
| byte | Byte |
| short | Shot | 
| int | Integer | 
| long | Long | 
| float | Float |
| double | Double | 
| boolean | Boolean |  

<br />  

対応した基本データ型と参照データ型間での代入はキャストによる変換が不要です

``` JAVA
int i = 100;
Integer j = i;
System.out.println(j);

Integer k = 200;
int l = k;
System.out.println(l);
```
実行結果

```
100
200
```
## 参照データ型を利用した扱える値の範囲の参照方法  
Javaから提供されているフィールドと基本データ型を参照型として扱うデータ型を利用することで、各データ型で扱える値の最大値と最低値を参照する事ができます。  

``` JAVA
System.out.println("Integer.MIN_VALUE");
System.out.println(Integer.MIN_VALUE);
System.out.println("Integer.MAX_VALUE");
System.out.println(Integer.MAX_VALUE);
```
実行結果

```
Integer.MIN_VALUE
-2147483648
Integer.MAX_VALUE
2147483647
```
他の基本データ型に対応した参照データ型を利用しても同様に扱える値の最大値と最低値を参照できます。

## まとめ  
-JAVAの基本データ型は８種類  
-基本データ型に対応した参照データ型が存在しており、お互いの代入ではキャストによる変換が不要  
-整数や浮動小数点数を扱う各データ型の最大値、最小値はMIN_BALUE,MAXVALUEを使用する事で参照できる。
無線ルーターとアクセスポイントの違い

■きっかけ
今後wifi構築を依頼する可能性が出てきたので、
自分も知っておかなくてはと思い先行学習しました。

■感想
奥が深い分野であるが、まずは名称と役割をおさえることができた。

■目次
・ルーターの役割
・無線LANルーター
・アクセスポイント

・ルーターの役割
　ネットワーク同士を接続するための機器。
　一般的には、ローカルネットワークとインターネットの間を仲介する。
・無線LANルーター
　ルーター機能とアクセスポイント機能を両方兼ね備えた機器。
　デバイスとつながってローカルネットワークを構築し、
　ローカルネットワークとインターネットを接続する。
・アクセスポイント
　アクセスポイントの機能しか持たない。
　ローカルネットワークを構築できるが、
　それをインターネットに接続する機能はない。

参考
https://it-trend.jp/wireless-lan-controller/article/271-0003
CygwinへのPipインストールめも

##apt-cygのインストール
apt-cygは正規版じゃないとダメっぽい。エラーでる。

```bash:以下、cygwinのコンソール内で
# ↓正規版。開発終了したらしい。
wget https://raw.githubusercontent.com/transcode-open/apt-cyg/master/apt-cyg
# 参照：https://github.com/transcode-open/apt-cyg/blob/master/status.md
```

・実行権限をつけてPATHの通っている場所に置く

```bash
chmod 755 apt-cyg
mv apt-cyg /usr/local/bin/
```

・国内のリポジトリから更新するようにする

```bash
apt-cyg -m ftp://ftp.iij.ad.jp/pub/cygwin/ update
```

##pipインストール
```bash
# 2系のpip
apt-cyg install python-pip
apt-cyg install python2-pip
# 3系のpip
apt-cyg install python3-pip

#これでもイケる？
python -m ensurepip
```

##aliasあてる
```bash
sed -i '$a alias pip='\''python -m pip'\' ~/.bashrc
source ~/.bashrc
pip --version
```