OmniAICreator/Qiita-1.07M huggingface dataset:
AmazonSNSをCLIからササっと使ってみる（メール+SMS）

# IAMユーザーを作成
AmazonSNSFullAccessを持たせてIAMユーザーを作成する。
Key IDとSecret Access Keyをメモっておく。

# AWSのCLIをインストール

```bash
# pipがない人はpipを入れる
curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
sudo python get-pip.py

# pip経由でCLIをインストール
sudo pip install awscli

aws configure
# 以下のように設定
# AWS Access Key ID [None]: 先ほど作成したIAMのKey ID
# AWS Secret Access Key [None]: 先ほど作成したIAMのSecret Access Key
# Default region name [None]: ap-northeast-1
# Default output format [None]: json
```

# トピックを作成
AmazonSNSではトピックを購読するという形でメッセージを送ります。
試しにトピックを作ります。

```bash
aws sns create-topic --name my_topic
```
以下のように出力されれば成功です。

```json
{
    "TopicArn": "arn:aws:sns:ap-northeast-1:[AWSアカウントID]:my_topic"
}
```

# メールを送ってみる
まずはメールを送ってみます。

```bash
aws sns subscribe \
--topic-arn arn:aws:sns:ap-northeast-1:[AWSアカウントID]:my_topic \
--protocol email \
--notification-endpoint wktq@dev.jp
```

これで購読確認のメールが送信されます。承認すると、管理画面に購読者が追加されます。
![スクリーンショット 2019-04-14 11.24.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/9998dd9e-e6c6-d980-53c9-173e2ef1dc6c.png)

試しにメールを送ってみます。

```bash
aws sns publish \
--topic-arn arn:aws:sns:ap-northeast-1:[AWSアカウントID]:my_topic \
--subject "Test mail" \
--message "Hello World"
```

無事に届きました。
![スクリーンショット 2019-04-14 11.27.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/e01b0748-12f0-510d-3012-327b57e1c4bd.png)

# SMSを送ってみる

```bash
aws sns subscribe \
--topic-arn arn:aws:sns:ap-northeast-1:[AWSアカウントID]:my_topic \
--protocol sms \
--notification-endpoint +818012345678
```

```json
{
    "SubscriptionArn": "arn:aws:sns:ap-northeast-1:[AWSアカウントID]:my_topic:[ユニークARN]"
}
```

SMSの場合は2段階確認が不要です。おそらく自動的に有効な電話番号かチェックしています。
--target-arnには直接電話番号を入れてもokのようです。

ちゃんと届きました。

```bash
aws sns publish \
--target-arn "+818091246940" \
--subject "Test mail" \
--message "Hello World"
```

<img width="375" alt="IMG_757065D71941-1.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/259a72a6-8d1e-7fd9-b25d-a5bdcde2eadf.jpeg">

宝箱は早速アンロックします。

# 料金
[https://aws.amazon.com/jp/sns/sms-pricing/](https://aws.amazon.com/jp/sns/sms-pricing/)
料金は上記より確認できます。（Japanを検索）

キャリア以外にもHNIとかあってよくわかりませんが、$0.06278~0.09268（7.03円〜10.38円のようです）
ubuntu 18.04にvscodeをインストールする

# 内容

この記事はUbuntu18.04にVSCode1.33.1をインストールした記事になっています。Ubuntu22.04にVSCode1.68.1をインストールした記事は[こちら](https://higmasan.com/2022/07/03/ubuntu-22-04%e3%81%abvscode%e3%82%92%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%99%e3%82%8b/)にあります。

# 環境

- ubuntu 18.04
- vscode 1.33.1

# リポジトリを登録する

aptのレポジトリで使用するマイクロソフトのキーをダウンロードしてきます。

```
~$ curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
```

ダウンロードしてきたキーをaptに登録します。

```
~$ sudo install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/
```

aptのリポジトリを登録します

```
~$ sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list'
```

# インストール

aptでhttpsアクセスできるように**apt-transport-https**をインストールします。

```
~$ sudo apt install apt-transport-https
```

vscodeをインストールします。

```
~$ sudo apt update
~$ sudo apt install code
```

起動は**code**です。

```
~$ code
```
botkitとnodejsでslackbotを作成した際の参考リンク集

#はじめに
最近botkitを使ってslackbotを作成しました。
その時に参考にしたページをまとめます。
完全に備忘録です。

#参考リンク
一番ベースにしたもの(slackbot管理ページへのリンクもある)
https://qiita.com/batch_/items/f141c595a6e587cd4588

Windowsでの環境構築
https://qiita.com/NagaokaKenichi/items/e0715b6bdde8459a705c

controller.hears(どんなメッセージが来た時にどんなメッセージを返すか)の設定について詳しく書いてある
https://clickan.click/slack-botkit/

Herokuにデプロイする
https://qiita.com/biga816/items/148a1156cd8b1a964b91

### まだ試してない
外部APIを叩く方法について書かれている
https://qiita.com/potato4d/items/81e9e8aef6cd57c234af

Slash Command(/inviteみたいなやつ)のつくりかた
(たぶん上のリンクたちとは違うサービスを使ってる？)
https://qiita.com/hiconyan/items/b506b0631265268a850b
USBについてのメモ#2

USBについて雑多なメモ。その2

#USBのソフトウェア
##ソフトウェアの階層
ざっくりとわけるとホスト/デバイスにそれぞれ3つにわけられる。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294245/baa41180-86fc-a602-b5de-71959ff11ed8.png" width=50%>

###ホスト
- ホストコントローラドライバ
    - 一番HWに近い層で、以下の仕事を担っている。
        - レジスタの初期化や制御データの初期化
        - USBホスト・ポート制御(ルートハブ制御、デバイス接続/切断制御、サスペンド/レジューム制御)
        - 転送制御(コントトール転送、バルク転送、インタラプト転送、アイソクロナス転送)
        - 割り込み/イベント処理
        - 上記機能に関するUSBバス・ドライバ、OS機能、PCI Expressバスドライバへのインターフェースの提供
    - USB3.0で提供されることとなったxHCは単一のコントローラでLow/Full/High/Super Speedをサポートすることができる。
        - USB2.0対応のEHCIではHighスピード通信専用
        - そのため、コンパチ対応のため、OHCI/UHCIコントローラーを搭載する必要があった。
- バスドライバ
    - 特定のコントローラ/デバイスに依存しない層で、すべてのコントローラ/デバイスに対して拡張性を意識した設計をする必要がある。
    - コントローラドライバ、クラスドライバを管理するそうである。
    - USBデバイスの管理をし、クラスドライバ/コントローラドライバにインターフェースを提供している。
        - USBデバイス管理
            - デバイスエニュメレーション管理(アドレス割り当て、各種ディスクリプタ情報取得/保持)
            - デバイスツリー構成、デバイスアドレス管理
            - USBハブポート制御/管理
            - バスステート、リソース管理
            - パワーマネジメント管理
        - クラスドライバインターフェース
            - デフォルトパイプ(標準リクエスト)リクエストの生成/発行
            - バルク、インタラプト、アイソクロナス/コントロールパイプによるリクエストの生成/発行
            - デバイススロットの有効化/無効化
            - バルクストリーム転送
            - デバイス情報提供、アクセス、制御(標準ディスクリプタ取得/設定など)
            - パイプステート制御
            - コンフィグレーション/インターフェース設定、オルタネートセッティング
            - クラスリクエスト、ベンダリクエスト
        - コントローラドライバインターフェース
            - 接続/切断、サスペンドレジューム検出
            - エニュメレーションに関する標準リクエストコール 
- クラスドライバ
    - 特定のデバイスのターゲット機能を実現する階層
    - マスストレージクラスやオーディオクラス用の標準デバイスクラスもあれば、ベンダ用のクラスドライバもある。

###デバイス
- ディスクリプタ情報を生成してホストに渡すことが重要な機能の1つで、その情報をもとにUSBホストは同じUSB接続でも通信相手によって必要な通信を行うことができる。
- デバイスソフトウェアにも以下の階層が存在する。
- コントローラドライバ
    - HWに一番近い層で、以下の仕事を担っている
        - USBデバイス接続/切断
            - VBUS制御
        - パワーマネジメント
            - サスペンドレジューム制御
        - 転送制御
            - コントロール転送/バルク転送/インタラプト転送/アイソクロナス転送
        - DMAコントローラ・ハードウェア制御
            - USB EPCバッファ-メモリ間DMA転送
            - USB EPCバッファ-他デバイス間DMA転送
        - 割り込み制御
            - 転送割り込み/DMA終了割り込み
            - 切断/接続、サスペンド/レジューム割り込み
- バスドライバ
    - クラスドライバ/コントローラドライバの管理を行っている層で以下の仕事を担っている
        - ディスクリプタ管理
        - リクエスト処理
        - USBデバイス管理
            - 接続・切断、イベント発生
        - コントローラドライバインターフェース
        - クラスドライバインターフェース
- クラスドライバ
    - USB製品に合わせてユーザーから見た機能を実現する層
    - USB2.0 3.0による違いに関してはバスドライバ、コントローラドライバで吸収されているため、基本的な通信においての差分はあまり気にしなくてもいい。(5.0Gbpsを実現するにはケアが必要。)
    - 以下の仕事を担っている
        - クラス固有ディスクリプタ管理
        - デバイスクラス転送制御
        - クラスリクエスト機能
        - アプリケーションへのAPIの提供
        - ブリッジI/F機能
Raspberry Pi 3 B+に シャットダウンスイッチを付ける


## シャットダウンスイッチをつけた理由
カムプログラムロボットに組み込んだRaspberry Piでプログラムするとき、ChromeBookのLinuxターミナルや、VNCクライアントで接続して作業するので、作業終了後は shutdownコマンドやGUIのShutdownボタンで、OSをシャットダウンして Raspberry Piを終了させます。
でも、ChromeBookを終了した後に、Raspberry Piのシャットダウンを忘れていた事に気づくことが度々あり、その都度 ChromeBookを起動させるのが面倒でした。

**↓こんなの作っています。**
![P_20190313_024111_vHDR_Auto - Edited (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57306/2f11d5a2-de3f-d5f4-49fa-cac840adfb4c.jpeg)
[Qiita: Raspberry Pi 3 Mobel B+とカムプログラムロボットでロボット作成
](https://qiita.com/K-Ponta/items/507b1a655a3489663bc8)

あと、（どのくら先になるか分かりませんが）自立起動させた場合、シャットダウンボタンがあったほうが都合がいいかなと思い、シャットダウンボタンを追加してみました。


### シャットダウンボタンの設置イメージ
ブレッドボード上に設置したタクトスイッチの端子を、GPIO.7(BCM 4)と、GND に接続します。
![P_20190414_101104_vHDR_Auto - Edited.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57306/4ef86e97-75b2-8be2-97c8-8d39fbac73c1.jpeg)

## OS環境
Raspberry Piの OSはRaspbian 9.8になります。

```bash
pi@raspberrypi:~ $ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 9.8 (stretch)
Release:        9.8
Codename:       stretch
```

OSの各パッケージはまめに **apt-get update** しているので最新だと思います。

## シャットダウンプログラム

プログラムは piユーザのホームディレクトリに binディレクトを作成してそこに保存することにしました。

```bash
pi@raspberrypi:~ $ mkdir bin/
pi@raspberrypi:~ $ vi ./bin/shutdown_button.py
```

プログラムはpythonで記述し、python2,python3の両方で動作することを確認済みです。
プログラムは、このページを参考にシャットダウンボタンを作成しました。
[クラゲのIoT: RaspberryPiにshutdownボタンを付けよう](http://jellyware.jp/kurage/raspi/shutdown_button.html)

```python:shutdown_button.py
#!/usr/bin/python

import time
import RPi.GPIO as GPIO
import os

GPIO.setmode(GPIO.BCM)

GPIO.setup(4,GPIO.IN, pull_up_down=GPIO.PUD_UP)

try:
    while True:
        GPIO.wait_for_edge(4, GPIO.FALLING)
        sw_counter = 0

        while True:
            sw_status = GPIO.input(4)

            if sw_status == 0:
                sw_counter = sw_counter + 1
                if sw_counter >= 200:
                    os.system("sudo shutdown -h now")
                    break
            else:
                break

            time.sleep(0.01)

except KeyboardInterrupt:
    pass
finally:
    GPIO.cleanup()
```

2秒以上、押し続けた場合、shutdown コマンドを実行するようにしています。

## OS起動時に自動実行するようにする

動作確認後、etcの下にあるrc.local ファイルを編集して、起動時にプログラムを実行するようにしています。

```bash
pi@raspberrypi:~ $ sudo vi /etc/rc.local 
```

exit 0 の前の1行が追加したコードになります。

```bash:/etc/rc.local
/home/pi/bin/shutdown_button.py
exit 0
```

追加後、Rsapberry Piを再起動すると設定が反映されます。
再起動後、タクトスイッチを長押してシャットダウンが実行されることを確認します。

## 最後に
シャットダウンスイッチを作っていて、Raspberry Piのハードウェアとソフトウェアの両方を比較的簡単に連動させながら扱えるの魅力を再実感しました。
コンピュータのプログラムを学ぶときに、手で触れられる部分とプログラムを連動させられると**実感**として判りやすいので、大切ですね。

願わくは、20年度からの小学校でのプログラム教育義務化にもこの感覚は反映させてほしいです。小学校の子がいる、おっさんプログラマからのお願いです。

でも、できる環境があるのと、それを教えることができる環境があるかは、別物ですよね。。。。、難しいです。
Sambaでリモート接続

### Windows → Vagrant → VB → CentOSにSambaをインストールしてファイル共有

**ユーザー作成**

```
sudo useradd user-name
passwd user-password
```

**sambaをインスト―ル**

```
sudo yum -y install samba
#Sambaにユーザーを登録
sudo pdbedit -a user-name
```

**samba設定ファイルを編集**

```
sudo vi /etc/samba/smb.conf

以下　変更追加
[global]
        workgroup = MY-WORK-GRP
        security = user
        passdb backend = tdbsam
        printing = bsd
        wide links = yes
        unix extensions = no

[public]
        comment = Vagrant local my-project
        path = /home/my-project
        public = yes
        browseable = yes
        writable = yes
        read only = No
        inherit acls = Yes
        force user = user-name
        force group = user-name
        guest ok = yes
        guest only = yes
        map archive = no
        valid users = vagrant,user-name
        create mode = 0775
        directory mode = 0775
        hosts allow = ALL
        vfs objects = streams_xattr

[homes]
        comment = Home Directories
        valid users = %S, %D%w%S
        browseable = No
        read only = No
        inherit acls = Yes

[printers]
        comment = All Printers
        path = /var/tmp
        printable = Yes
        create mask = 0600
        browseable = No
```



Samba起動

```
sudo systemctl start smb
sudo systemctl enable smb
```

selinuxの設定を無効にする

```
vim /etc/selinux/config
SELINUX=disabled
```


**シンボリックリンク**
1. /home/my-project/以下にプロジェクトを配置して、windowsから読み書きできるようにする
2. /home/vagrant/にプロジェクトへのシンボリックリンクを張る

```
mkdir /home/my-project
# windowsのユーザー名またはグループ名にしておく
chown hogehoge:hogehoge /home/my-project
chmod 0755 /home/vagrant
chmod 0775 /home/vagrant/my-project
ln -s /home/my-project/my-project　/home/vagrant/my-project
```


共有設定（Windows)
仮想マシンのIP：192.168.33.100

```
\\192.168.33.100\public\my-project
```


その他(sshのパスワード認証を許可)

```
sudo vi /etc/ssh/sshd_config
# 下記コメントアウトを解除設定
#PasswordAuthentication yes
systemctl restart sshd
```
VirtualBox のバグで Guest Addition がインストールできない

注: この記事は2019年3月28日に書いた．

VirtualBox を，WindowsホストでUbuntu16.04ゲストというパターンで動かしている．数日前から急にshared folderがマウントできなくなってしまった．正確には以下のコマンドで手動マウントはできるのだが，自動マウントをしてくれない．

```
# mount -t vboxsf (マウントポイント名) /media/sf_(マウントポイント名)
```

その他にも妙な挙動がいくつか．どうも，Guest Addition のビルドに失敗している模様．

```
# cd /media/(ユーザ名)/VBox_GAs_....
# ./VBoxLinuxAdditions.run
```
を実行すると失敗して，`/var/log/vboxadd-setup.log` を見ると，

```
/tmp/vbox.0/r0drv/linux/memobj-r0drv-linux.c:1113:18: error: too many arguments to function ‘get_user_pages’
             rc = get_user_pages(pTask,                  /* Task for fault accounting. */^M
                  ^
```

てなのが出ている．


[解決法](https://qiita.com/nk0130/items/0899b523ec7444b20135)を書いてくれている人がいた．直っているけれどリリースには入っていないのだそうで[テストビルド](https://www.virtualbox.org/wiki/Testbuilds)を持ってくるのだと．

なんでも
The Windows test build packages are working precisely like a usual VirtualBox installer packages, with one difference: they will not work (the error message will point to unsigned drivers) if you install them on Windows 10 if your system has UEFI secure boot enabled. To make these test build work you need to disable UEFI secure boot in the system's UEFI config.
だそうなので，UEFIセキュアブートを無効にしなくてはいけない．

うまくいった．
Sigfox Sequence Number（シーケンス番号）管理

シーケンス番号は、Sigfoxプロトコルのオーバーヘッドの一部であり、メッセージが送信されるたびにデバイス自体によってインクリメントされます。Sigfoxクラウドは、シーケンス番号をデバイスメッセージの一貫性の観点で確認し、メッセージを受信しますが、このシーケンス番号に連続していない場合、警告・エラーが発生します。

###Warningイベント
シーケンス番号に飛びが発生すると、**"break in message sequence"**イベントが発生します。このイベントは警告イベントであり、メッセージ受信には影響を及ぼしません。
###Errorイベント
規定値以上のシーケンス番号抜けがある場合には、**"out of message sequence"**イベントが発生します。このイベントが発生すると、Sigfoxクラウドは該当デバイスからのメッセージを受信しなくなるため、その状態を復帰させるためには、**disengage sequence number**をする必要があります。
###シーケンスライフサイクル
シーケンス番号は、4096メッセージで、ゼロリセットされます。

#Errorイベントの発生トリガ
**Errorイベント判定は、回線契約レベル（Subscription Level）と2つのメッセージの経過日によって異なり、
`[前のシーケンス番号] + 300 x [2つのメッセージの経過日]`
`[前のシーケンス番号] + [Subscription Level] x ([2つのメッセージの経過日]+2)`
のmax値を超えた場合にErrorイベントが発生します。**

例えば、ひとつ前に3日前に受信できていたシーケンス番号が「5」の場合、
回線契約レベル（Subscription Level）が140回/日であれば、`max値は5+300×3=905`となります。
max値を超えてしまった場合に、Errorイベントが発生します。

また、min値は5+140×(3+2)=705であり、7~705の範囲内のシーケンス番号飛びであれば、Warningイベントとなります。
706~905の範囲内のシーケンス番号飛びであれば、メッセージは破棄されます。

[Sigfox Japan KCCS](https://qiita.com/organizations/sigfox)
railsでbootstrap-sassを導入する手順

## はじめに
railsでbootstrapを使う際の手順についてまとめました。
今回はscssを使用するのでbootstrap-sassを使用します。

##①gemをinstall
```ruby:Gemfile
gem 'bootstrap-sass'
gem 'jquery-rails'
```
追加後、`bundle install`

##②application.jsに以下を追加
```javascript:application.js
//= require jquery
//= require jquery_ujs
```
//= require_tree .より上に追加する。

##③application.scssに変更
application.scss
↓
application.scss
に名称変更

##④application.scssに以下を追加
```scss:application.scss
@import "bootstrap";
@import "bootstrap-sprockets";
```
AtCoderの問題をJavascriptで解くためのテンプレ作りました

最近アルゴリズムの勉強も兼ねて競技プログラミング（AtCoder）をやるようになったのですが、
どうやら競技プログラミングをJavascript / Node.jsで解く人は少数派であり、各種コンテストサイトでの対応状況は芳しくないと思われます。

AtCoderの処理系はNode.js v5.12が利用されており（2019/4/14時点）、色々と使えない構文や関数が存在しています。

 - let （strict modeにすれば使える）
 - 分割代入
 - べき乗演算子
 - Array​.prototype​.includes()
 - String​.prototype​.pad​Start()
 - BigInt
 - Object.entries / Object.values ... etc

そのため、手元のNode.jsのバージョンが高いと、「解けた！」と思っていざ提出すると通らないなんてことがあるので、nvm入れて切り替えてやっていたのですが、「Javascriptなんだからトランスパイルすれば良くね...？」と思ったので作りました。

https://github.com/DecoratedKnight/js-cp-template

babelとbabel-polyfillだけで十分かなと思っていたら、BigIntに関してはpolyfillでもダメだったので、[BigInteger.js](https://www.npmjs.com/package/big-integer) を入れました。（外部ライブラリ使って問題解くのはどうなんだ、という気もしますが...）
webpackで1枚のjsにバンドルしますので、例えばlodash入れたりとかもできてしまいます。

当然のことながらコードはビルド後の物を提出することになり、[こんな感じ](https://atcoder.jp/contests/abc124/submissions/4966156) になってしまうので、この方式で提出する人が増えると、回答を見比べるとかそういった楽しみが無くなってしまうのが痛いです！

最新のNode.jsのバージョンに追従してくれればこんなことしなくていいのに（チラッ）
そのためにも、まずは少しでもJavascriptで問題を解く人が増えるといいなと思います！
Gifsicle+node.jsでgifアニメをまとめて最適化

## はじめに
[自サイト](https://pentamania.github.io/portal/)では彩りのため、gifアニメを載せている。しかし元々ブログやtwitter紹介用に大きめに録画したものを、特に何の加工もせずCSSで小さく表示していただけだったので、無駄にファイルサイズがでかく（ものによっては1MB超えだったり）、訪問者に全く優しくなかった。

さすがにどうにかしようと思ったが、いちいちアニメを撮り直す元気もない。
バッジ処理でまとめて最適化できないだろうかとネットを巡って見つけたのが以下のgifsicleというツール。
https://www.lcdf.org/gifsicle/

[npmにNode.js用にラップされたパッケージ](https://www.npmjs.com/package/gifsicle)があったのでそちらを利用し、最適化スクリプトを書いた。

```optimize-gif.js
const { execFile } = require('child_process');
const gifsicle = require('gifsicle');
const fs = require('fs');
const path = require('path');

const RESIZE_WIDTH = "150";
const COLOR_NUM = "64";

const baseDir = path.resolve('./assets/images/works-thumbnail');
const inputFileDir = path.resolve(`${baseDir}/rawgif`);

fs.readdirSync(inputFileDir).forEach(file => {
  execFile(gifsicle,
    [
      '--resize-fit-width', RESIZE_WIDTH,
      '--colors', COLOR_NUM,
      'optimize=3',
      '-o', `${baseDir}/${file}`, // 出力先
      `${inputFileDir}/${file}` // 入力
    ],
    (err) => {
      console.log('minified!: ', file);
    }
  );
});
```

execFileで第二引数にオプションを渡して実行する。
入出力オプションを除くと、今回は以下を設定。

- アスペクト比を保ちながらリサイズ（--resize-fit-widthオプション）
- 色数の制限（--colors）
- [最適化レベル](https://qiita.com/tatoo3198/items/58771c30ff03975197b6#%E6%9C%80%E9%81%A9%E5%8C%96)
（--optimize：ただしこれはいまいち効果が実感できず）

## 結果
オリジナルと比較すると、さすがに劣化が目立つけど、サイト上で縮小表示するとあまり気にはならない程度ではある。

##### オリジナル
![hatuyume-lucky.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81823/b1334271-a731-8f01-591a-1c314a5bdfaa.gif)

##### 縮小版
![hatuyume-lucky.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81823/fc9aa5bc-79e8-8b4b-7b27-7f1ee2a424ba.gif)

何かわちゃわちゃしているなぁ感ができていればよいので良しとする。

### ダイエット結果の一例
- 787KB（407x293） → **236KB（150x108）**
- 465KB（210x165） → **167KB（150x118）**
- 1040KB（472x416） → **138KB（150x132）**

ファイルサイズ縮小率は基本的には1/3 ~ 1/4弱だが、中にはガクッと減ったものも。

フレーム数を落とすなど、もうちょっとチューニングできそうな気もするけど、とりあえずこれで妥協します。


# 参考
- https://github.com/pentamania/portal （自サイトのリポジトリ）
デバイスメッセージをSigfoxクラウド上で確認できないとき

Sigfoxデバイスを長らく使っていると、「あれ？メッセージが届いてきていない？」と気づかれる瞬間があるのではないでしょうか？
まずはサービスエリアを疑う訳ですが、今まで使えていた場所なので、そんなはずがない。。。
そんな場合、まずは"MESSAGES"画面ではなく、**"TRASH MESSAGES"**メニューを開いてみてください。TRASH MESSAGEに最近のメッセージデータが表示されているのであれば、下記を確認してください。

1. トークンが切れていないか？
2. シーケンス番号飛びによりメッセージ受信が拒否されている

#トークンが切れていないか？
Sigfoxデバイスを利用する場合は、[KCCS](https://www.kccs-iot.jp/)や[パートナー](https://www.kccs-iot.jp/partner/)、[Sigfox Buy](https://buy.sigfox.com/)から回線トークンを購入します。トークンには、契約開始日(Start date)に基づいたActivate(回線開通)可能な期限(Activation end date)、通信可能な期限(Communication end date)が定義されています。
例えば、契約内容（Contract Info）が下記の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/e2321eff-0876-5149-ab68-95102f20c882.png)


- Start date : 2017-03-31
- Activation end date : 2018-03-31
- Communication end date : 2019-03-31

その契約上で使うデバイスは、2018年3月31日までにアクティベーションする必要があります。期限ギリギリ（2018年3月31日）にアクティベートしたデバイスは、2019年3月31日まで使用可能という意味になります。
また、例えば、2017年10月10日にアクティベートした場合は、そこから1年間がトークンの期限となります。
トークンの延長も可能ですが、トークン自動更新の設定を入れていない場合、トークン切れによるメッセージ受信ができないという事例がよくあります。

**"トークン切れ"**の場合は、下図のようにデバイス一覧画面の**Token state**欄に![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/ef3900a8-6402-939d-06fc-c958154e4214.png)というマークが付いています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/abb34887-925c-b257-fbc3-da27276a3581.png)

念のため、デバイスIDをクリックし、デバイス情報（Information）ページを見てみると、トークンが切れていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/353d57a7-417f-ebec-f8d0-95f3e83b8ffd.png)

### トークン切れの場合の対処方法
トークン切れの場合は、**"リスタート"**することにより、引き続きメッセージ受信ができるようになります。
継続して利用可能なトークンが契約内に残っていることを前提に、![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/dbbf435a-5fe5-f264-5a52-530a5ae8fb0b.png)
Restartボタンをクリックしていただければ結構です。

#シーケンス番号飛びによりメッセージ受信が拒否されている
Sigfoxの場合、なりすましデバイス防止のひとつとして、シーケンス番号管理をしています。(デバイス管理については[こちら](https://qiita.com/ghibi/items/4eccef2ba81cf86a3385)も見てください）
シーケンス番号が一定値以上飛んでしまった場合には、メッセージが受信できなくなります。
Deviceの"EVENTS"メニューを見ると、シーケンス番号の警告(warning)やエラー(error)情報を確認することができます。
シーケンス番号によるメッセージ管理については、[こちら](https://qiita.com/ghibi/items/36127777480ed107405a)参照。

###シーケンス番号飛び時の対処方法
DeviceTypeないしDeviceのInfomationページ右上に配置されている![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/ddcd09e6-0f34-6dec-e9f4-330e83f3a246.png)
engaged sequence numberボタンをクリックしてください。
これにより、シーケンス番号管理がリセットされ、以降のメッセージを受信できるようになります。

[Sigfox Japan KCCS](https://qiita.com/organizations/sigfox)
google Colaboratoryで簡単にファイルの入出力

### ドライブ内にpngファイルを保存してみる

```python
from google.colab import drive
drive.mount('./gdrive')
```
とすると

```
Go to this URL in a browser: ハイパーリンクがここに表示される

Enter your authorization code:
··········
□
```

ここでパスワードの入力を求められるので，上のハイパーリンクをクリックしてサイトに飛ぶ

↓

アカウントの選択
「Google Drive File Stream」に移動

ここでcolaboratoryで保存したいgoogle driveのアカウント（私の場合はcolaboratoryで使用しているアカウント）をクリック
↓

Google Drive File Stream が Google アカウントへのアクセスをリクエストしています

下の方を見ると「許可」のボタンがあるので，それを押す

↓

ログイン

このコードをコピーし、アプリケーションに切り替えて貼り付けてください。

4/LAGqa4WWzSrti88D5C0P6kfYJbfL-XhnCTQmfp

のように長いパスワードが表示されるので，それをコピーして最初に求められたパスワードのところに張り付ける．

↓

```python
!ls gdrive
```
!と打つとlinuxコマンドが使えるので，マウントが成功したかを確認
成功していると

```
'My Drive'
```

と出力される．

```python

drive_root_dir="./gdrive/My Drive"

import numpy as np
from PIL import Image

img = (np.random.rand(128,128,3)*255.0).astype(np.uint8)
print(img)
print(drive_root_dir+"/noise.png")
np.save(drive_root_dir+"/noise", img)
```
でpng画像が保存ができる．


同様に，この状態でloadもそのままできます．

```python
load_img = np.load(drive_root_dir+"/noise.npy")
print(load_img)
```
とすればnpyで画像をロードできます．
アソシエーション(rails 学習)

###はじめに
初学者の学習アウトプットです。
先輩方。
アドバイス、訂正、オススメ記事等ありましたらお願いします。

#アソシエーション
railsを学習しているのですがアソシエーションって言葉は覚えて、モデル同士の関係に関連付けをするっていうのは分かったのです。

しかし!!!!!

モデル同士の関連付けしてどうなるの？
何ナノ？アソシエーション~~それ美味しいの~~？
(初心者あるある)っていうことに陥って何となく~~分かった~~(分かったつもりになってた)
を抜け出せるように理解したいと思いました。

じゃ、やりましょう!!

###アソシエーションを定義する
今回Twitterの簡易版アプリを使用しています。
ツイート(投稿)とユーザーを関連付けさせます。
全てのツイートはいずれかのユーザーが投稿したもので、ユーザーは自分が投稿した複数のツイートを所持していることになります。

モデルクラスにhas_manyやbelongs_to等が定義されてる。
所属する側のテーブルに所属するクラス名_idというカラムが存在する。

```ruby

class User < ApplicationRecord #Userモデル
    devise :database_authenticatable, :registerable,
           :recoverable, :rememberable, :validatable
    has_many :tweets  
  end
```
```ruby

 class Tweet < ApplicationRecord #Tweetモデル
    belongs_to :user
  end
```

こいう感じで定義されました。

ここまでは理解ができるのですが次ですね。
次、何が？どうなんの？って、、、

###アソシエーションを実装

アソシエーションなしの場合。
tweetsテーブルに対して、user_idがuserのidと等しいレコードを取得しています。

```
#ターミナルにてrails cコマンド実行

$ rails c
  [1] pry(main)> user = User.find(1)
  [2] pry(main)> Tweet.where(user_id: user.id)
  => [#<Tweet id: 1, image: "http://photo1.jpg", text: "いい景色だ。", created_at: "2014-12-06 09:00:00", updated_at: "2014-12-06 09:00:00", user_id: 1>,
  #<Tweet id: 1, image: "http://photo2.jpg", text: "楽しい思い出は消えない。", created_at: "2014-12-06 10:00:00", updated_at: "2014-12-06 10:00:00", user_id: 1>]
```

アソシエーション実装後
Userモデルに「User has many Tweets」の状態のアソシエーションを定義したので、Userモデルのインスタンス.tweetsと記述するだけでそのインスタンスが所持しているツイートを取得することができます。(記述が少なくなってる)

```
 $ rails c
  [1] pry(main)> user = User.find(1)
  [2] pry(main)> user.tweets
  => [#<Tweet id: 1, image: "http://photo1.jpg", text: "いい景色だ。", created_at: "2014-12-06 09:00:00", updated_at: "2014-12-06 09:00:00", user_id: 1>,
  #<Tweet id: 1, image: "http://photo2.jpg", text: "楽しい思い出は消えない。", created_at: "2014-12-06 10:00:00", updated_at: "2014-12-06 10:00:00", user_id: 1>]
```
これを実装すると

```ruby

  class UsersController < ApplicationController

    def show
      @nickname = current_user.nickname
      @tweets = current_user.tweets
    end

  end
 ```

こんな感じになり簡単というか記述が減って綺麗に見えるのでよかった!と思いました。
あと自分でアソシエーションをしっかり組んで自分のアプリに技術を落とし込んでいきたいです。
もっと色んなパターンも他にもあると思うのでそこも勉強が必要かなと。

こちらの記事参考にしました。

【Rails初心者向け】モデル間の関連付け（アソシエーション）まとめ
https://qiita.com/To_BB/items/47d2c7b1bc3513025d7b
Ionic4 に Google Analytics を入れる

## 初めに
ionic4 でPWAアプリを開発しようとした際、Ionic の公式サイトで記述されている
方法で、Google Analytics がうまく導入できずに困ったときのために
この記事を書きていきます。

## Ionic4 のプロジェクトを制作する
始めるにあたり、Ionic CLI を使い、プロジェクトを作成します。
その際、テンプレートはどれでも構いませんが、
フレームワークは、Angularで進めていきます。

```bash
ionic start Example  
```

## Google Analytics を導入する

それでは、実際に導入していきたいと思います。
ここでは、Google Analytics での登録完了後、トラフィックコード: `UA-XXXXXXXXX-Y` が発行されますので,こちらを保存してください。

進めていくうえで参考にしたサイトはこちらになります。

https://blog.yuhiisk.com/archive/2018/05/18/angular-google-analytics.html

プロジェクト ”Example” 作成後、


``` bash
cd Example
ionic g service gs
```
とコマンドを入力してください。入力後、
`ga.service.ts`, を編集します。

```ga.service.ts
import { Injectable } from '@angular/core';

declare let gtag:any;
@Injectable({
  providedIn: 'root'
})
export class GaService {

  constructor() { }

  private useGA():boolean{
    return typeof gtag!==undefined;
  }
  sendPageView(url:string):void{
    if(!this.useGA()){return;}
    gtag('config','UA-XXXXXXXXX-Y',{
    //'UA-XXXXXXXXX-Y'には、生成されたコードを入力してください。
    'page-path':url 
    });
  }
  sendEvent(eventName:string,
            eventCategory:string,
            eventAction:string,
            eventLabel:any):void{
    if(!this.useGA()){ return; }
    gtag('event',eventName,{
      event_category:eventCategory,
      event_action:eventAction,
      event_label:eventLabel
    });
  }
}

```

次に、app.compornent.tsを編集します。

```app.compornent.ts

import { Component } from '@angular/core';
import { Platform } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { Router,NavigationEnd } from '@angular/router';
import { GaService } from './ga.service';
import { filter } from 'rxjs/operators';

declare let ga: Function;

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html'
})
export class AppComponent {
  constructor(
    private platform: Platform,
    private splashScreen: SplashScreen,
    private statusBar: StatusBar,
    private router:Router,
    private gaService :GaService
    
  ) {
    this.initializeApp();
  }

  initializeApp() {
    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
      this.router.events
      .pipe(
       filter(e=>e instanceof NavigationEnd))
      .subscribe((params: any)=>{
        this.gaService.sendPageView(params.url);
      });
      
    });
  }
}

```

最後に、index.htmlに、次のコードを`head`内に追加してください。

```index.html
<head>
 ...
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXXX-Y"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
  </script>
 ...
</head>
```


これにより、Google Analytics の準備はできました。
このコードをデプロイした後、Google Analytics で、
現在の利用者が１人とカウントされていたら成功です。
混合正規分布によるクラスタリング

```{r}
#混合指数分布によるクラスタリング

#mixed exponential Intervals p.29

n=1000



k=4

X=array(0,dim=c(k,n))

param=c()

for(j in 1:k){
  
val=sample(5:50,1)

param=c(param,val)
  
X[j,]=abs(rpois(n,val))  
  
}

X=as.numeric(X)

lam=1/sample(5:10,k);p=rep(1/k,k)



ite=1000

for(l in 1:ite){
  
q=array(0,dim=c(k,length(X)))

for(i in 1:k){
for(j in 1:length(X)){  
 
q[i,j]=p[i]*dexp(X[j],1/lam[i])   
  
}
}  

q=t(t(q)/c(apply(q,2,sum)))

p=apply(q,1,mean)

lam=1/(q%*%X/c(apply(q,1,sum)))

q[q==0]=10^(-20)

#print(sum(log(q)))

print(lam)
  
}


```

```{r}

#混合正規分布によるクラスタリング

library(dplyr)

N=10000;

class=4

pi=rep(0.25,class)

mu=c(-5,5,8,3);sig=c(1,5,3,4)

#真の出身（正解データ）

attr=sample(1:class,N,replace = T,prob=pi)

x=rep(-99,N)

for(j in 1:class){
  
 x[which(attr==j)]<-rnorm(length(which(attr==j)),mu[j],sig[j])
 
}

#initial conditions

mu=sample(c(-20:20),class);sig=sample(c(1:50),class)

pi=c(0.2,0.6,0.1,0.1)

times=100

for(j in 1:times){
  
s_piN=array(0,dim=c(class,N))  

for(i in 1:class){
  
 s_piN[i,]=pi[i]*dnorm(x,mu[i],sig[i]) 
  
}

qn=c()

for(i in 1:class){
  
 qn=c(qn,sum(s_piN[i,]/apply(s_piN,2,sum))/N) 

}

pi=qn

mu=c()

sig=c()

for(i in 1:class){
  
mu_val=sum(x*s_piN[i,]/apply(s_piN,2,sum))/(N*pi[i])  
  
mu=c(mu,mu_val)  

sig=c(sig,sqrt(sum((s_piN[i,]/apply(s_piN,2,sum))*((x-mu_val)*(x-mu_val)))/(N*pi[i])))
  
}


}

```

```{r}

N=1000

pi0=0.5;pi1=0.5

mu0=5;mu1=-5

sig0=1;sig1=5


attr=sample(0:1,N,replace=T,prob=c(pi0,pi1))

x=rep(-99,N)

x[which(attr==0)]=rnorm(length(which(attr==0)),mu0,sig0)

x[which(attr==1)]=rnorm(length(which(attr==1)),mu1,sig1)

#initial conditions

mu0=1;mu1=1;sig0=10;sig1=20;pi0=0.1;pi1=0.9

iteration=20

for(i in 1:iteration){
  
 piN0=pi0*dnorm(x,mu0,sig0);piN1=pi1*dnorm(x,mu1,sig1)
 
 qn0=piN0/(piN0+piN1);qn1=piN1/(piN0+piN1)
 
 pi0=sum(qn0)/N;pi1=sum(qn1)/N
 
 mu0=sum(qn0*x)/(N*pi0);mu1=sum(qn1*x)/(N*pi1)
  
 sig0=sqrt(sum(qn0*(x-mu0)*(x-mu0))/(N*pi0))
 
 sig1=sqrt(sum(qn1*(x-mu1)*(x-mu1))/(N*pi1))
  
}

```
UbuntuとApacheでmod_auth_formを使ってみる

# はじめに
この記事ではJavaによるOP実装例をベースに、シングルサインオン(SSO)を実現する方法を書いてみます。
https://qiita.com/namikitakeo/items/c4f1a23ed7609c65342e

# 実行環境
下記バージョンで動作確認しています。myopはJavaアプリケーションでApacheのリバースプロキシ設定で中継します。
- Ubuntu on Windows(14.04.6 LTS, Trusty Tahr)
- Apache2 Ubuntu(Apache/2.4.7)

<pre>
ProxyPass /myop/ http://127.0.0.1:8080/myop/
ProxyPassReverse /myop/ http://127.0.0.1:8080/myop/
</pre>

# 実装方針
mod_auth_formを利用する事でログイン/ログアウトをApacheで行いセッション管理にCOOKIEを用いる事でSSOを実現します。

以下の例ではフォーム認証のID/パスワードにはファイルを利用します。もちろんDBやLDAPに対応する事も可能ですので認証に依存しない認可の仕組みをつくる事が可能となります。

<pre>
$htpasswd -b /etc/apache2/passwd user01 user01
</pre>

以下のURL構成を想定しています。
<pre>
https://myop.example.com/myop/authorize
https://myop.example.com/myop/jwk_uri
https://myop.example.com/myop/tokeninfo
https://myop.example.com/myop/.well-known/openid-configuration
https://myop.example.com/login.html
https://myop.example.com/dologin.html
https://myop.example.com/logout.html
https://myop.example.com/dologout.html
</pre>

以下のURLのみID/パスワードで保護します。ユーザーが最初にアクセスした際は有効なCOOKIEがありませんので、
<pre>
https://myop.example.com/myop/authorize?param=aaa
</pre>

ログイン画面にリダイレクトされます。
<pre>
https://myop.example.com/login.html?param=aaa
</pre>

ログイン画面では/dologin.htmlにパラメータをPOSTする事で有効なCOOKIEを発行します。
<pre>
httpd_username：user01
httpd_password：user01
httpd_location：https://myop.example.com/myop/authorize?param=aaa
</pre>

Apacheのリバースプロキシ設定でTomcatのmyopに中継する際にHTTPヘッダ(uid)で有効なID(user01)を連携します。

<pre>
&lt;Location "/myop/authorize"&gt;
        require valid-user
        AuthUserFile /etc/apache2/passwd
        AuthType form
        AuthName realm
        AuthFormLoginRequiredLocation /login.html?%{QUERY_STRING}
        Session On
        SessionCookieName session path=/
        SessionCryptoPassphrase secret
        RewriteEngine On
        RewriteCond %{LA-U:REMOTE_USER} (.+)
        RewriteRule . - [E=RU:%1,NS]
        RequestHeader set uid %{RU}e
&lt;/Location&gt;
&lt;Location /dologin.html&gt;
        SetHandler form-login-handler
        AuthFormProvider file
        AuthUserFile /etc/apache2/passwd
        AuthType form
        AuthName realm
        AuthFormLoginSuccessLocation /myop/authorize?%{QUERY_STRING}
        AuthFormLoginRequiredLocation /login.html
        Session On
        SessionCookieName session path=/
        SessionCryptoPassphrase secret
&lt;/Location&gt;
&lt;Location /dologout.html&gt;
        SetHandler form-logout-handler
        AuthFormLogoutLocation /logout.html
        AuthName realm
        Session On
        SessionCookieName session path=/
        SessionCryptoPassphrase secret
&lt;/Location&gt;
</pre>
Elixir ~前提となる基本に立ち返る~

　#ここまでのあらまし

ここまで、Enumを使った記法や簡単な関数のモジュール化、PJとして扱うところまでをやった。

[こちらのサイト](https://dev.to/gumi/elixir-02--30n1) を参照しながら体系的理解について備忘録的にドキュメントをしたためていきます。

#本題、Elixirの基本

わたしにとって引っかかった、覚えるべきところを記していくのでElixirの基本、あらましについてすべてを記述していくわけではありません。

四則演算

```elixir
iex > (1 + 2) * 3 - 4
5
```

四則演算は、カッコで囲まれたところや乗法除法から計算していく模様。
中高の数学と同じといえそうです。

除法の/は結果が整数であっても浮動小数点を以て扱うよう。

これに対して答えを整数で返すのがdiv、除法の余りを返すのがrem。

```elixir
iex > div(10, 2)
5
iex > div 10, 2
5
iex > rem 10, 3
1
```

ここで、基本的な型についてわたしに引っかかったものを備忘録。
”プログラミングElixir”という書籍がここのあたりの記述があかるかったけれど、プログラミング入門者のわたしにはいささか内容が緻密で読みづらかったので後にまわすことにしています。

論理値 true
アトム :atom 
リスト [1,2,3]
タプル{1,2,3}

論理値かどうか確かめるのがis_boolean/1関数。

```elixir
iex > is_boolean(1 > 2)
true
iex > is_boolean(1)
false
```

ヘルプを表示するのがh。自学自習、Elixir学習において避けて通れない英語読解のために役に立ちそう。ガンガン使っていこう。

```elixir
iex > h is_number/1
```
返ってきたヘルプがこちら
<img width="649" alt="スクリーンショット 2019-04-14 09.46.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306722/673af7dd-691d-6848-38a1-802fa0176a54.png">

入力したタームが整数か浮動小数であった場合true、それ以外はfalseを返す、といったところでしょうか。

アトムはそれ自体がそのまま値になる。

```elixir
iex > :atom
:atom
iex > :atom == :hello
false
```

is_atom/1やis_boolean/1といった関数がありますがここでは例示に対する理解が完璧でないため割愛します。

Elixirのモジュール名もアトム。モジュールをつくるときは大文字から始める。

```elixir
iex(14)> is_atom(String)
"htrue
iex(15)> is_atom(MyModule)
true
```

文字列は””で囲む。
アトムを文字列に含めるときは#{}で囲む。

```elixir
iex > "hello"
"hello"
iex > "hello #{world}"
** (CompileError) iex:17: undefined function world/0
    (elixir) src/elixir_bitstring.erl:142: :elixir_bitstring.expand_expr/4
    (elixir) src/elixir_bitstring.erl:27: :elixir_bitstring.expand/8
    (elixir) src/elixir_bitstring.erl:20: :elixir_bitstring.expand/4
iex > "hello #{:world}"
"hello world"
```

↑アトムとして扱うための：を忘れたのでコンパイルエラーが出ています。

文字列には改行が含められる。またエスケープシーケンス\nで加えてもよい。
IO.puts/2で示されるアトム:okは、正しく入力できた際の戻り値。

```elixir
iex > IO.puts"hello/nworld"
hello/nworld
:ok
iex > IO.puts"hello
... > world
... > "
hello
world

:ok
```
あれ。ちょっと改行のしくみに疑問。

バイト数を調べるのがbyte_size/1、文字数を調べるのがString.length/1。

```elixir
iex > byte_size("hello")
5
iex > byte_size("健康")
6
iex > String.length("hello")
5
iex(23)> String.length("健康")
2
```

#編集後記

たいへんわかりやすくまとまっているブログを見つけたので理解をあたらしくすることができています。
続きは次のドキュメントに切り分けます。

全然関係ないんですがHHKB Lite 2 US配列を買いました。
音楽業界ってアップルのテンキー付きJIS配列が標準かつわたしのMacBook ProもJIS配なので、まだまだ慣れないですが書き始めてエンジンかかってくるとタイピングが楽しくなってきます。
めざせ後継メインマシンUSキー化＆HHKB Professional購入。

うまずたゆまず、頑張ります。
Kento Mizuno
とにかくDockerイメージを渡したい

dockerイメージの受け渡しを行うときに、docker-hubや自前のリポジトリを使える状態にあれば良いのですが、とにかくイメージよこせ！と、とりあえず早急にイメージだけを渡す必要に迫られ他ので、その際にとった方法を残しておきます。

### イメージのエクスポート
`docker save`を行うと、イメージをtar形式で標準出力してくれます。これをリダイレクトして任意のファイルに出力します。
その後、gzipコマンドでさらに圧縮すると、元のサイズの1/3強くらいになりました。

```
docker save [イメージ名] > my image.tar
gzip image.tar
```
あとは出来上がったファイルをダウンロードやコピーをするなりして、催促する人に渡します。

### イメージのインポート
エクスポートと逆の手順にてインポートすることができます。
つまり、gzipコマンドで解凍し、解凍されたファイルを`docker load`で読み込みます。

```
gzip -d image.tar.gz
docker load < image.tar
```

エラーが発生しなければOKです。
私は、`docker save`したファイルが壊れていた事が何回か続いたため、人に渡す前には`docker load`でエラーが発生しない確認を行なってから人に渡すようにしようと思います。

### 参考
https://docs.docker.com/engine/reference/commandline/save/
Python事始め

###自分がPythonを勉強していて気になったことを紹介します

###前提
環境：windows10

---
###sys と os
os.path と sys.path は混合しがちですが、両者は全く異なるものです。[os](https://docs.python.org/ja/3/library/os.html) はosに関連したメソッドを利用するモジュールです。他方[sys](https://docs.python.org/ja/3/library/sys.html) はインタプリタにした関連するメソッドが利用できるモジュールです。

###os
osは、Pythonを使ってディレクトリを作成したり、ディレクトリのPATHを取得したりできます。

カレントディレクトリの取得
次の方法でカレントディレクトリを取得できます。最後のやつはソースファイルから実行する場合。

```
os.getcwd() 
os.path.abspath(".") 
os.path.dirname(os.path.abspath("__file__"))
```

参考：[pythonでsysモジュールとosモジュールの区別（使い分け方）がよくわかりません。](https://teratail.com/questions/17254)
  
ディレクトリ内のファイル確認

```
os.listdir()
```


ディレクトリの移動

```
os.chdir("C://Dev//sample") 
```

環境変数名の取得

```
os.environ["環境変数名"] 
os.getenv("環境変数名")
```

###sys


>インタプリタや実行環境に関連した変数や関数がまとめられたライブラリ
引用元：[ライブラリ：sys](https://www.lifewithpython.com/2013/03/sys.html)

とのことで、`sys`に含まれている変数と関数は [sys --- システムパラメータと関数](https://docs.python.org/ja/3/library/sys.html) で確認できます。
例えば、`sys.path`でリスト形式で格納されている環境変数のPathを確認することができます。

```python.py
import sys
sys.path
```

`os.path` と `sys.path` が混同しやすいのですが、前者はモジュール、後者はリストです。

または、インタープリターにインポート済のモジュールを確認するのは以下の方法で可能です。

```
sys.modules.keys()
```



####importとfrom

次のような使い分けをします。

- [標準ライブラリ](https://docs.python.org/ja/3/library/index.html)を使うときは `import`
- 外部ライブラリを使うときは `from`
- fromされた外部ライブラリを使うときは `import`

<!--
```Javascript:fileName.js
'↑「言語名：ファイル名」と書いとくと言語に合わせて色を変えてくれるみたい。'
'Bash, C#(cs), C++(cpp), CSS, Diff, HTML, XML, Ini, Java, Javascript, PHP, Perl, Python, Ruby, SQL, 1C, AVR Assembler(avrasm), Apache, Axapta, CMake, DOS .bat(dos), Delphi, Django, Erlang, Erlang, REPL, Go, Haskell, Lisp, Lua, MEL, Nginx, Objective C(objectivec), Parser3, Python, profile, Scala, Smalltalk, TeX, VBScript, VHDL, Vala'
'ここだけソースがコードになってないけどごめんね(;´･ω･)'
'バッククオート(`)はSHIFT押しながら「@」キーを押す。'
'※キーボードによって違うので参考まで'
```
コメントアウトの練習

もう一度練習

「＊」か「＿」1個で*＿イタリック(斜体)＿*。2個で__太字__。

>「Code - コードの挿入」で使ったからこれも書いとかなきゃ(;´･ω･)
>こっちはソースがコードになってる方ね(;´･ω･)

-->
iTerm2のステータスバー表示位置を変更する

![iterm2_statusbar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4614/24477d4a-4e67-4f28-936c-be79b958589d.png)

iTerm2のステータスバーは下記から有効化することができる。

```
Preferences > Profiles > Session > Status bar enabled > Configure Status Bar
```

表示位置は `Preferences > Appearance > Status Bar Location` で上に表示するか、下に表示するかが選択できる。

## 参考

* [iTerm2 にステータスバーが付いた - Qiita](https://qiita.com/delphinus/items/1748937aefeb241bdcee)
Craft CMS がいいなーと思っているところ #craftcms

![rectangle_large_type_2_c653b67a8fe982157ea07276c5b38ac9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8890/a6a2e78e-d7a7-a498-be18-0ff2671fce91.jpeg)


これは [Craft CMS Advent Calendar 2018](https://adventar.org/calendars/2941) 3日目の記事です。

[Craft CMS 3](https://craftcms.com/) が出て今年は Craft CMS 3 案件も何件かやりましたが、やっぱり便利ですね。  
去年の [Craft CMS Advent Calendar](https://adventar.org/calendars/2212) では Craft 3 のことを書いてましたね。

> Craft CMS の次期バージョン Craft 3 について調べてみた | mersy note  
> [https://note.mersy418.com/article/craft3](https://note.mersy418.com/article/craft3)

他のCMSもいいところはたくさんありますが、 Craft CMS のわかりやすさ、使いやすさというのもあるかなと思ってます。

## コンテンツ管理の編集画面の使いやすさ

a-blog cms のユニット、Drupalのパラグラフ、MTのブロックエディタみたいなものですが、管理画面、特にデータを投入する入力画面のインターフェースが使いやすい、調整しやすいってのはやっぱりいいですね。

![picture_pc_932e28f853707f0485c0f7d0b0e4fe18.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8890/4f885feb-8f9b-6917-08d0-3cccf0e89617.jpeg)


リレーション（エントリ同士の関連付け）とかもやりやすいのはいいですねぇ。

ここは開発者がメインで触るのではなく、ユーザさん（大体はクライアント）が多く触る部分なので重要だなー、と。

## グローバル

CMSでの設定値を管理画面で持たせることができる、という感じなんですが、これが結構便利だなー、と。


![picture_pc_a2fa2ef43ef8a28e18059ea97cd7b77d.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8890/c7384718-d9db-edad-07a7-90f8a726e3eb.jpeg)

MTだとそういうのがないからカスタムフィールドを作って、 MTAppjQuery でカスタマイズして拡張するとかになりますが。

この辺りは色々使い回ししやすくて、設計する側としては気に入っています。

## テンプレート

Twig で色々やれるのが便利ですね。  
MTはMTタグを覚えれば色々できて楽チンですが。

Craftじゃなくても使われる話なので、ある程度フレームワークとしてあるものが使われてるのは安心です。

## オリジナルダッシュボード

MT の DataAPI が出た時にオリジナルダッシュボードを作るとかやろうとしたのが、 Craft CMS だとかなり簡単にできる印象があります。  
この辺は動的CMSの強みなんだろうなー、と。

とある案件で CMS のデフォルトの管理画面、管理ユーザ向けの管理画面、一般ユーザ向けのページといったものをかなり柔軟に自由度高く作れるのがよかったです。

CMS の管理画面自体のカスタマイズってのは慣れの問題もあるけど、MTの方が楽な印象はあります。  
a-blog cms も結構なところまでやれそうだなー、という印象はあります。が、やるかどうかはまた別の問題かな、という雰囲気を感じます。  
Drupal も Dashboard は作れるから色々できそう。  
見た目の好み的には MT だけど、他もまだまだ使いこなせてないだけな気もしますね。

## 日本語のドキュメントがある

[@bun](https://twitter.com/bun) が訳してくれたドキュメントがあるので、使いやすい。ありがたい。感謝感謝。

![picture_pc_927140e709c4a0fc4c786ce825c685ce.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8890/c214fac1-76be-7586-6622-dd670e52bef6.jpeg)

> Craft CMS について | Craft 3 ドキュメント  
> [https://docs.craftcms.com/v3/ja/](https://docs.craftcms.com/v3/ja/)

困った時も [@bun](https://twitter.com/bun) に twitter で投げれば懇切丁寧に教えてくれるので、これまた安心ですね！

## 初のアジア太平洋イベントの開催

Craft CMS のイベント的な [Dot All](http://dotall.com/2018) は毎年どこかであるみたいなのだけど、来年2月に小さい版？がオーストラリアのメルボルンである様子。

> Dot One Australia | Craft CMS  
> [https://craftcms.com/dot-one-australia](https://craftcms.com/dot-one-australia)

アジア環太平洋で開かれる最初のイベントみたい。日本開催だとありがたいなー、と思うところはあるけど、NZに近いオーストラリアだし、都合がつけば参加してみたいなー（英語わからないけど）

## ということで Craft CMS 使ってみませんか？

他のCMSでももちろんできるところが多いので、絶対的な強みなのか？と言われるとそうじゃない部分もあるとは思います。  
でも、Craft CMS 作りやすいなーと思うところもあるし、お客さんからそういった感想をいただくことがあるのも事実。

先日の [MTDDC Meetup TOKYO 2018](http://mtddc2018.mt-tokyo.net/session/#speaker_id313) で @bun が Craft CMS のセッションをしましたが、日本の制作会社でも使ってる人がちらほらいそうな感じ。  
そういう人たちと色々意見交換とか、どういう風に使ってるか？とかをざっくばらんに話せる機会を作ってみたいなー、と思います。  
色々勉強させてもらいたいですね。

個人的にはマルチサイトのところとか、多言語の仕組みをしっかり使うとか、ルーティングの設定とかまだまだ細部まで把握できていない、使ったことがないところもあるにはあるのだけど、そこはまた機会を見て掘り下げてみたいな、と個人的には思います。

来年も Craft CMS には色々お世話になりそうな気がしています。
[Python] youtubeliveのアーカイブの見どころを特定する

# 動機
最近面白い配信者がたくさんいます．(とくにえつじlive)

ですが，live放送をすべて見ることはできませんし，何より時間が足りません．

そこで面白いところだけ見れたらいいなと思い，見どころを特定するプログラムを作成しました．

# 流れ
パラメータi, g, m

- youtubeliveからチャット(コメント)を取得する
- コメントの最後に”草”もしくは”w”がついているかを確認する
- ついていればその時間を記録し，その瞬間からi秒間の間に同じように"草"もしくは"w"コメントがないかを確認する
- それを繰り返し，草コメントの数をカウントする
- g回より大きい数以上の草コメントがあればその時間は見どころとする
- 草コメントがあった瞬間から見ても内容が入ってこないのでm秒間前の時間を表示する

# 結果
このようなかんじで出力されます．
いいねももらえます．

![Screenshot from 2019-04-22 21-02-27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237843/309849bb-2a1d-fac1-3c77-e95bafc6006b.png)

[21歳　えつじ誕生日雑談 - YouTube](https://www.youtube.com/watch?v=qRF8YuI6-So)

# 感想
youtubeliveのチャットを取得する方法を調べた先駆者様がいらっしゃったので簡単にできました．

見どころを特定するのにあたり，もう少しいい方法を考えたいです．今の方法ではあまりにも単純すぎます．

しかし，実際にやってみたところそこそこ上手く機能していました．

ただし，チャンネルによってパラメータを調整しないとうまく行かなかったです．

# ソースコード
[youtube_highlight/main.py at master · okamoto950712/youtube_highlight](https://github.com/okamoto950712/youtube_highlight/blob/master/main.py)

# バグとか
プログラムではスパチャの金額も一応控えているのですが，100円スパチャやコメントがないスパチャはデータ構造が違うみたいで漏れがあります．
あとドルに対応できていません．

チャットをyoutube data apiで取得できるみたいですので，時間があれば書き直したいです．

# 参考
[PythonでYouTube Liveのアーカイブからチャット（コメント）を取得する（改訂版） - 雑記帳(@watagasi_)](http://watagassy.hatenablog.com/entry/2018/10/08/132939)
【備忘録】Office365のメール流量制限まとめ

組織の個人ユーザーが一般的にメールを使っている限り、流量制限に引っかかること考えにくい。しかし、流量制限に引っかかったケースがあったので、MSの公式ドキュメントなどから、備忘録でまとめみた。



# 受信について

メールボックスごとに、1時間当たり3600のメッセージ。
これを超えると送信元に「上限を超えたから配信不能な」と返信する、らしい。(試してないからわからないけど）

かといって、ここまで受信できるかというとそうでもない。
メッセージの追跡でステータスが[Pending]のメールを追跡したところ[recipientthread limit exceeded]になっていて、どうも「受信メールボックスが存在するデータベースが過負荷だから、サーバーを守るため配送スロットリングかけてるよ！」ってことらしい。

■とりあえず対応

1. 待つ。しばらく（数時間？）すれば順次リトライしてくれて、最終的にはメールボックスに届くので、待てばいい。

2. メールボックスの強制移動。数時間も待てないケースは、メールボックスを移動させれば解消される。経験上、1~2時間ぐらい。PowerShellでExchangeに接続して、以下実行。

    New-MoveRequest -identity <ユーザーのメールアドレス>

■根本策

送信元サーバーのIPが固定されているなら、「コネクタ」を作成する。


# 送信について

メールボックスごとに1日当たり10,000宛先、1分あたり30メッセージ。
これを超えるとメッセージの送信を拒否されるらしい。

個人で使っているのにこの制限に引っかかることはないと思うけど、[正当なバルク メッセージ (たとえば、顧客向けのニュースレター) ]とか[システムアラートの送信]などを送信している場合は、考慮が必要。

■とりあえず対応

とりあえず、待つ。
1時間待てばおくれるようになる。
それか、送信元アドレスを分ける。

■システムから送信している場合
いくつかの推奨構成が記載されているので、以下まとめ。


1. マイクロソフトの推奨構成は「アプリからOffice365にサインインして送信する」。アプリから365にサインインする構成なので、通常の個人アカウントと何ら変わらない扱いができるし、システム構成もシンプル。


2. 推奨構成が使えない場合で宛先がテナント内だけなら「アプリから365に直接送信する」。SPFレコードに送信元になるIPを追加する。「メールボックスごとに1日当たり10,000通、1分あたり3,600メッセージ」よりも制限は多いようだけど、じわじわ流量を増やさないとIPスロットリングの制限受けるので、注意。
※コネクタは使えない


3. 推奨構成が使えない場合で宛先にテナント外を含むなら「SMTPリレー」を使う。コネクタを作成して、SPFに追加する。メールボックスごとに1日当たり10,000宛先、1分あたり30メッセージ」よりも制限値は大きい。外部ドメイン宛にもメール送信できるけど、「バルクメールの送信はできません」と記載がある。


4. 正当なバルクメッセージの送信をする場合は、「サードパーティプロバイダを使う」「オンプレミスのSMTPサーバーを使うことを真剣に検討」が良いらしい。



# 参考にした情報

Exchange Online の制限
https://docs.microsoft.com/ja-jp/office365/servicedescriptions/exchange-online-service-description/exchange-online-limits

New-MoveRequest
https://docs.microsoft.com/en-us/powershell/module/exchange/move-and-migration/New-MoveRequest?view=exchange-ps

Office 365 を使用してメールを送信するように多機能デバイスまたはアプリケーションをセット アップする方法
https://docs.microsoft.com/ja-jp/exchange/mail-flow-best-practices/how-to-set-up-a-multifunction-device-or-application-to-send-email-using-office-3

IPスロットリングについて
https://blogs.technet.microsoft.com/exchangeteamjp/2015/03/23/ip/
[Rust]HKTに対して関数定義



https://keens.github.io/blog/2017/06/24/jienerikusubenkyoukaihosoku/

ここで紹介されている`HKT`に対して関数を定義したい。
具体的には中身の数値（ここでは`i32`）を２乗する関数`square`を定義したい。

```rust
trait HKT<U> {
    type T;
    type MU;
}

trait Mappable<U>: HKT<U> {
    fn map<F: FnOnce(Self::T) -> U>(self, f: F) -> Self::MU;
}

fn square<T>(mappable: T) -> T::MU
where
    T: Mappable<i32, T = i32>,
{
    mappable.map(|x| x * x)
}
```

これで完成。**`Mappable`に対して`T=i32`の型パラメータ指定ができる**ことに気づくまでに時間がかかった。

例えば`Option`に対して実装するならこうなる。

```rust
impl<T, U> HKT<U> for Option<T> {
    type T = T;
    type MU = Option<U>;
}

impl<T, U> Mappable<U> for Option<T> {
    fn map<F: FnOnce(Self::T) -> U>(self, f: F) -> Self::MU {
        match self {
            Some(v) => Some(f(v)),
            None => None,
        }
    }
}

fn main() {
    let a = Some(1i32);

    println!("{:?}", square(a));
}
```
GCPのアーキテクチャ作図は公式のフォーマットを使うのが一番良さげ

# はじめに

GCP関連の記事や設計書を書く上で欠かせないのがGCPのコンポーネントのアイコンやアーキテクチャ図

たいした内容じゃないけど、備忘として記事化しておく。

ちょっと調べたら分かることだけど、GoogleはGCPや関連技術を説明するためのコンポーネントアイコンだけでなく資料を一から説明しないでも済むようにPowerPointやGoogleSlideを豊富に[公式サイト](https://cloud.google.com/icons/)で紹介してくれている

http://cloud.google.com/icons/

![スクリーンショット 2019-04-14 7.46.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55225/1ee9a72c-dfcc-1c1f-1c9f-ec00a2446db5.png)

しかも中身を色々と探ってみると、単にGCP関連のアイコンだけでなく色々な分野の技術を説明する上でユーザーが一から資料を作らなくても済むように様々なフォーマットを用意してくれている

勿論、公式が展開しているだけあってこれらのアイコンは資料やアーキテクチャ図を作成する際に許可なく利用可能である


# Googleスライドのコンテンツ
PowerPointはボタンをクリックすると資料がダウンロードされてそのまま使えるのは良いものの、他のメンバーと共有しながら作業するにはやや使いずらいのでGoogleスライドをベースにコンテンツの内容を紹介したい

[Googleスライドの公式フォーマット リンク](http://docs.google.com/presentation/d/1vjm5YdmOH5LrubFhHf1vlqW2O9Z2UqdWA8biN3e8K5U/edit)

## アイコン一覧
はじめにGCPが展開しているサービスのアイコンを一気にまとめているページがあり、必要に応じてここから自分が用いるサービスをコピってきてアーキテクチャ図を作成できる

![スクリーンショット 2019-04-14 8.11.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55225/96f0bf7e-3269-9788-f121-43917e011f2f.png)

## ダイヤグラム一覧
GCPに関連するサービスアイコンだけでなくそれらの繋がりや構成を示すためのダイヤグラムもかなり豊富に用意してくれている

![スクリーンショット 2019-04-14 8.16.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55225/af126701-a3d2-b65d-e81b-7a90c27f024c.png)

これでヘッダーやフッターなどに悩む必要なし

## マテリアルアイコン
GCPに関わらず社会全般のアイコンを取ってきたい場合は、ここから取得するようにレコメンドされている

[material.io](http://material.io/tools/icons/)

大抵のイメージアイコンならこのサイトで事足りる気がする

## ダイヤグラム例(General)
ここからがとてもありがたいコンテンツなのだが、いくつかの代表的なアーキテクチャパターンをすでにフォーマットとして作図してくれているので、基本はこれらをちょこちょこカスタムするだけで作図がすぐにできるようにしてくれている

![スクリーンショット 2019-04-14 8.26.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55225/7b18c4f9-4b4c-051c-8641-21e1b538b051.png)


## ダイヤグラム例（業界別）
さらに踏み込んで業界別に使いそうなコンポーネントをまとめてアーキテクチャ図をすでに複数パターン用意してくれている

用意されているパターンの一部を紹介すると

- ゲームアプリのバックエンド
- 映像コンテンツのリアルタイム配信
- リアルタイムビッディング
- センサー情報の収集機能
- 時系列分析
- 不正検知

などなど、これ以外にも非常に多くのパターンがすでに用意されている

![スクリーンショット 2019-04-14 8.29.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55225/f090f29e-f8d3-c410-0d58-d396da54bc78.png)


# Draw.ioで作図
作図するだけならPowerpointやGoogleSlideでやらずにDraw.ioでやった方が効率が良いと思われる

Draw.ioにGCP関連のコンポーネントがプリセットされているので、これらを使って実際にアーキテクチャ図
を作成することができる

[フォーマットサンプル](https://www.draw.io/?splash=0&libs=gcp)

![スクリーンショット 2019-04-14 7.59.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55225/dd17fff4-c4bd-3c9f-d8bd-1ed850129f40.png)

こんな感じのアーキテクチャ図を１０分ほどで簡単に作成できる

CacooやLucidChart（GCPNext19にも出展してた）でも同じようなことができるが、Draw.ioが登録なども不要で一番取っつきやすい感あり


おしまい
Dart-Controle Flow statements

# Dart-Controle Flow statements
Dart言語における条件分岐やループ処理等を整理します。

## 条件分岐

### if文
まんまJavaと一緒の書き方です。

```dart
void main(List<String> args) {
  bool flg = false;

  if(flg == true) {
    print("true");
  } else if(flg == false) {
    print("false");
  } else {
    print("else");
  }
}
```

### switch文
これもjavaと一緒の書き方です。

```dart
void main(List<String> args) {
  String command = 'OPEN';
  switch(command) {
    case 'COLOSED' :
      print('CLOSED');
      break;
    case 'OPEN' :
      print('OPEN');
      break;
    default:
      print('DEFAULT');
  }
}
```

## ループ

### for文
dartにおけるfor文は三種類の書き方ができます。

```dart
void main(List<String> args) {
  List<int> list = [1,2,3];

  // 一般的な書き方
  for(int i = 0; i < list.length; i++) {
    print(list[i]);
  }

  // クロージャーを使用した書き方
  //{}は省略可能
  list.forEach((i) => {print(i)});

  // 拡張for文
  for(int i in list) {
    print(i);
  }
}
```
プラグインとライブラリーの違いについて

#プラグインとライブラリーの違い
プラグインもライブラリーも共にメインのプログラムから呼ばれるサブプログラム群やツールのようなものですが、アーキテクチャの視点からは大きな違いがあります。

プラグインとライブラリーの違いについて簡単に書いてみます。

##プラグイン
プラグインはメインのプログラムのインターフェイスに依存して作成されます。

メインのプログラムはプラグインに依存せず、他のプラグインに差し替えて動作させることが可能です。

##ライブラリー

ライブラリーはその逆で、メインのプログラムがライブラリーのインターフェースに乗っ取って構築されます。

メインのプログラムはライブラリーに依存することになり、ライブラリーを別のライブラリーに差し替えるということが困難となります。
pandasのapplyに複数のSeriesを渡したときの要素の取得方法

# 概要
applyに2つのseriesを渡したときに、一つの変数の中に2つのSeriesが
入った？状態になってどう扱えば一意のSeriesから要素を取れるのかということを
試行錯誤したので記事にして忘れても見返せるようにします。

# 具体的なシチュエーション

列Dの値を列Aに転記したいが、列Dの値がNaNのときは
列Aの値を保持したい。

# どうするのか

``` python
def overwrite(row):
    if pd.isnull(row['D']):
        return row['A']
    else:
        return row['D']

comp_df['A'] = comp_df[['D', 'A']].apply(overwrite, axis=1)

```

もしくは

``` python
def overwrite(row):
    A, D = row
    if pd.isnull(A):
        return A
    else:
        return D

comp_df['A'] = comp_df[['D', 'A']].apply(overwrite, axis=1)
```

# 振り返って見ると
そりゃそうなるよねというコードなので一体どこで詰まってたんだっけ。。。
Javaにあるクラスの使い方とは？

[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしている@yuka_ponです。

Javaを学んでいると、たくさんのクラスが登場しますよね？
そこで今回は、Javaに登場するクラスについて学んだことをまとめてみました。

#クラスについて
##クラスとは？
そもそも、**クラス**とは一体何でしょうか？

クラスとは、プログラムを実行するための処理をまとめたものです。
その処理を実行するためには、オブジェクトを作る必要があります。

そのクラスは、次のように表示することで作れます。

```Java
class クラス名 {
  実行処理
}

```

##クラス継承について
クラスには、**クラス継承**というものもあります。
これは、クラスが保持している実行処理を他のクラスにも同様に処理させるものです。
継承元のクラスを**スーパークラス**や**親クラス**と呼ぶのに対して、継承したクラスを**サブクラス**や**子クラス**と呼びます。

クラスの継承は、次のように表します。

```Java
class 親クラス名 {
 実行処理
} 

class 子クラス名 extends 親クラス名 {
　実行処理
}
```

#クラスの種類
##内部クラス
**内部クラス**とは、クラス内に新たなクラスを作成することです。

その時は、次のように表します。

```Java
class クラス名1 {
 class クラス名2 {
  実行処理
 }
}
```

##ラッパークラス
**ラッパークラス**とは、int型のような基本データを利用するために使うクラスです。


この他にも、クラスはたくさんあります。
詳しくは、[コチラ](https://www.sejuku.net/blog/24931)。