OmniAICreator/Qiita-1.07M huggingface dataset:
機械学習実行環境をDockerイメージにする時OpenCVに困ってませんか？

機械学習モデルの実行環境用にDockerイメージを作ろうとして、OpenCVのインストールにハマってしまい丸1日を費やしたので、同じことで悩む人が少しでも減ることを願ってシェアします。

# 問題点

PythonオフィシャルのDockerイメージに、機械学習に必要なライブラリをpipでインストールして起動し、必要ライブラリをインポートしてバージョン情報を表示するだけの下記プログラムを実行します。

```Python
import keras
import tensorflow
import numpy
import PIL
import cv2

print('keras:', keras.__version__)
print('tensorflow:', tensorflow.__version__)
print('numpy:', numpy.__version__)
print('pillow:', PIL.__version__)
print('cv2:', cv2.__version__)
```

すると、下記のOpenCVが依存しているネイティブ・ライブラリが見つからないというエラーがimportの時点で発生します。

```shell
Traceback (most recent call last):
  File "version.py", line 5, in <module>
    import cv2
  File "/usr/local/lib/python3.6/site-packages/cv2/__init__.py", line 3, in <module>
    from .cv2 import *
ImportError: libgthread-2.0.so.0: cannot open shared object file: No such file or directory
```

# 解決策

このエラーは、opencv-python自体はpipでインストールされておりcv2は見つかったものの、依存関係にある外部ライブラリが見つからないというエラーになります。「docker pip opencv」などをキーワードに対処方法をググってみると、大半はOpenCVのソースからコンパイルするスクリプトをDockerFileに書こうという記述ばかりが並びちょっと凹みます。

Macでは、pipでopencv-pythonがインストールできて使えていたので、余計に混乱しましたがちょっと冷静になって考えてみると、元々OpenCVはネイティブライブラリでありopencv-pythonはそれに皮を被せただけのラッパーに過ぎないと気づきました。

だったら、apt-getで元々のネイティブライブラリをインストールすれば、依存関係のエラーは解消できるはずと考えてDockerFileを以下のようにしてイメージを作成してみたところエラーは解消されました。

```DockerFile
# Replace this line to use python official image as a base.
FROM python:3.6.8-slim-stretch

LABEL Name=try_ml_docker Version=0.0.1
EXPOSE 50000

# Add the following line to get native library of OpenCV.
RUN apt-get update && apt-get install -y libopencv-dev 

WORKDIR /app
# Replace this line to copy requirements.txt inside the docker image.
ADD ./requirements.txt /app

RUN python3 -m pip install -r requirements.txt
CMD ["python3", "-m", "try_ml_docker"]
```

requirements.txtには以下の内容を記載します。coremltoolsはkerasとtensorflowのバージョンに著しく依存するので、coremltools2.0を利用する場合はkerasとtensorflowは下記バージョンに指定します。その他のpythonライブラリは最新版を利用します。

```text
coremltools==2.0
keras==2.1.6
tensorflow==1.5.0
numpy
pillow
opencv-python
```

# Tips

ソースコードやデータセットはVS Code上のものをホストとコンテナの間で共有したいのでカレント・ディレクトリを共有するようにコンテナを実行します。-vパラメーターで渡すのは絶対パスなので、\`pwd\`コマンドでカレントディレクトリの絶対パスを取得して渡しています。pwdコマンドをくくっているのはバッククォートですので気をつけてください。

```shell
$ docker run -v `pwd`:/app -it -d try_ml_docker:latest /bin/bash
```

# おわりに

Apple Musicから流れてくる甲斐バンドの「安奈」を聴きながら、やっぱMac最強、Debian/Ubuntuまじめんどくせぇ…
matplotlibで特定のデータをプロットしない方法


#はじめに
[漫画の掲載順を取得してグラフ化する記事](https://qiita.com/Seigenkousya/items/8f0ffbd2c34a8e8535e2)を書いている時に休載で掲載順を取得できない月があり、グラフ化するときに困った。
matplotlibで特定のデータをプロットしない方法が後から分かったのでメモ。

#環境
```
# uname -a                                                                                                                              
Linux kali 4.18.0-kali2-amd64 #1 SMP Debian 4.18.10-2kali1 (2018-10-09) x86_64 GNU/Linux
# python --version                                                                                                                             
Python 3.7.2+
# pip3 show matplotlib                                                                                                                         
Name: matplotlib
Version: 2.2.2
```
#問題
例えば、以下のようなデータがあったとする。

|month|1月|2月|3月|4月|5月|6月|7月|8月|9月|10月|11月|12月|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|data|13|15|21|5|10|　|21|17|15|16|21|13|

6月だけデータがない。

```python
Y_data=[13,15,21,5,10, ,21,17,15,16,21,13]
```

Y軸のデータの配列に空きができてしまった。どうすればいいのか。

#解決法

プロットしたくないor欠損しているデータにはNoneを代入するとその項目はプロットされなくなる。


```python
Y_data=[13,15,21,5,10,None,21,17,15,16,21,13]
```
こんな感じ。

```python
#!/usr/bin/env python 
import matplotlib.pyplot as plt
 
X_data=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Y_data=[13,15,21,5,10,None,21,17,15,16,21,13]
month_name=['Jan.','Feb.','Mar.','Apr.','May','Jun.','Jul.','Aug.','Sep.','Oct.','Nov.','Dec.']

plt.xlabel('month')
plt.ylabel('data')

plt.xticks(X_data,month_name)
plt.plot(X_data,Y_data)
plt.show()

```
>結果
![plot_None.png](https://qiita-image-store.s3.amazonaws.com/0/332794/0a8a2996-b039-6287-047d-732a0df39434.png)

一件落着。
#参考文献
[python - matplotlibにおけるグラフの始点の指定 - スタック・オーバーフロー](https://ja.stackoverflow.com/questions/41200/matplotlib%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%82%B0%E3%83%A9%E3%83%95%E3%81%AE%E5%A7%8B%E7%82%B9%E3%81%AE%E6
%8C%87%E5%AE%9A)
これのお陰で助かりました。ありがとうございます。
ExcelVBAでテーブル読込みとカラム名を指定したデータ挿入方法

エクセルシートのテーブルはListObjects("テーブル名")で取得できる。

ListObjectのListColumnsによって指定したカラム名の列を取得できる。

取得した列のDataBodyRangeを先頭行からのオフセットを指定して呼び出すことでセルを参照できるので新規追加した行のインデックスを指定すれば、追加目的のセル参照を取得できる。

```vb
Dim tbl As ListObject
Set tbl = Sheets("シート名").ListObjects("テーブル名")

' 空の行を追加してインデックス番号を取得
Dim newRowIdx As Integer
Dim newRowIdx = tbl.ListRows.Add(AlwaysInsert:=True).Index

With tbl
    .ListColumns("カラム名").DataBodyRange(newRowIdx) = "データ値"
End With
```

ListRows("カラム名")でできるといいのに。。。

以上
クラウド系業務アプリ作成ツールメモ

業務でクラウド系業務アプリ作成をすることになりそうなので、比較用のまとめを作成してみました。

こんな感じの項目で比較ポイントをまとめています。

　　a. 会社規模
　　b. 作成のしやすさ
　　c. 外部連携
　　d. サポート
　　e. コスト
　　f. 制限
　　g. その他

他にも何かあれば追加更新していきますので、ご一報ください。

# [KINTONE](https://kintone.cybozu.co.jp/)
開発の知識がなくても自社の業務に合わせたシステムをかんたんに作成できる、サイボウズのクラウドサービスです。業務アプリを直感的に作成でき、チーム内で共有して使えます。社員間のつながりを活性化する社内SNSとしての機能も備えているため、スピーディーに情報共有ができます。

## 1. メリット
　　a. 中小企業向け
　　b. アプリ作成が容易
　　c. 外部連携が容易
　　d. 国内サービスであるため、サポートが受けやすい
　　e. ランニングコストが安い

## 2. デメリット
　　f. RDBでないため、リレーション部分で工夫が必要
　　f. 最大のデータ件数が100万件が限度
　　f. APIの利用限度があるひとつのアプリで10000回

# [Sales force](https://www.salesforce.com/jp/)
セールスフォースは、CRMマーケティングおよび管理に使われる、営業やセールスフォースの機能自動化の補助を目的としたシステム。

## 1. メリット
　　a.大・中小企業向け
　　b,標準機能である程度すべてがまかなえる。
　　g.シェアは一番
## 2. デメリット
　　c.開発言語がセールスフォース独自言語となる。
　　d.カスタマイズするときのメンテナンスが要注意（更新により動かなくなりやすい）
　　e.ランニングコストが高い
　　g.処理速度が遅い

# [Zoho Creator](https://www.zoho.com/jp/creator/)
Zoho Creatorはローコードアプリ開発プラットフォーム。カスタムのモバイル対応アプリを自分で作成して使い始めることができます。また、小規模、中規模、大規模の企業ですぐに使用できる50種類以上のアプリも提供しています。

## 1. メリット
　　a.大・中小企業向け
　　b.アプリ作成が容易
　　c.外部連携が容易
　　g.RDBに対応できる

## 2. デメリット
　　d.海外サービスであるため、サポートが受けにくい
　　e.ランニングコストが安い

# [EZCraft](https://ezcraft.lincrea.co.jp/)
EZCraftは、システムの開発から運用までをワンストップで提供し、複雑な業務アプリケーションをより早く、より柔軟に構築できるローコードアプリケーションプラットフォーム（aPaaS）です。

## 1. メリット
　　a.中小企業向け
　　b.UI操作でコーディングする
　　c.外部連携はふつう？
## 2. デメリット
　　d.実績が少ない

# [nyoibox](http://www.ni-ware.com/nyoibox/index.html)
「nyoibox（如意箱）」は、クラウド上で使える、日々の業務に必要なデータベースを情報システム担当者がいない会社でも簡単に作ることができる、データベースサービスです。データベースや業務アプリケーショの作成、登録したデータの共有はもちろん、集計やグラフ化もマウス操作のみで簡単に行なえます。

## 1. メリット
　　a.中小企業向け
　　b.アプリ作成が容易
　　e.ランニングコストが一番安い
　　g.RDBに対応できる

## 2. デメリット
　　c.外部連携が少ない
　　d.実績が少ない
【さくらVPS】【CentOS7】MySQL(phpMyAdmin)、Railsの開発環境構築(2)：一般ユーザーの作成&設定

# 前回の記事
【さくらVPS】【CentOS7】MySQL(phpMyAdmin)、Railsの開発環境構築(1)：初期設定
https://qiita.com/jung_issei/items/05b3cfd25f830354d3a5


# 今回の目的
・サーバーの一般ユーザー作成
・作成した一般ユーザーにroot権限をもたせる

→上記を完了させることで、一般ユーザーでの権限内にて、WEBサイトの開発を進めることができるようにする。



# 一般ユーザーを追加＆パスワード設定
パスワードとユーザー名をきめて、下記のコマンドを実行

```
[root@ ~]# useradd -p $(perl -e 'print crypt("パスワード", "\$6\$saltsalt")') ユーザー名
```

※パスワードとユーザー名はパスワード管理のアプリケーション等に保存しておく。



# sudoというroot権限で一般ユーザーも作業ができるようにする

```
[root@ ~]# usermod -aG wheel ユーザー名
```
※sudo→superuser do→特権レベルのユーザー→root
※wheelグループ→sudoできる権限をもったユーザのグループ(名称由来不明)
※「-aG」→検索するとよく、オプションが「-G」とだけになっているが、これは既存ユーザーを一括で上書きしてしまうため、「-aG」が良いとのこと。

```
[root@ ~]# visudo
```

・念の為下記のように記述されているか確認

```
%wheel ALL=(ALL) ALL
```

※CentOS6は行頭に#でコメントアウトされていたため、念の為確認。



# wheelグループのユーザーはすべて「su -」のコマンドでrootになれるようにする

```
[root@ ~]# vi /etc/pam.d/su

#auth　　　　　required　　　　　pam_wheel.so use_uid
　↓　↓　（↓行頭にある「#」を削除）
auth　　　　　required　　　　　pam_wheel.so use_uid
```




# さいごに
次は鍵認証の設定について記事を書いていきたいと思います。
ngrok 導入方法

記事にするほどでも備忘録的に投稿

### ngrokとは
ローカル環境を動作確認をスマホなどの実機で行うことができる


### <font color="red">環境情報</font>

環境はVagrantを使って以下

|種類|バージョン|
|:--:|:--:|
|OS|centos6.7|


### Vagrantファイルの修正

```diff:ポートの設定
  # NOTE: This will enable public access to the opened port
-  # config.vm.network "forwarded_port", guest: 80, host: 8080
+  config.vm.network "forwarded_port", guest: 80, host: 1234
```

※別ですでに8080使ってたので変えました

```diff:IPの設定
  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
-  # config.vm.network "private_network", ip: "192.168.33.10"
+  config.vm.network "private_network", ip: "192.168.33.10"
````

#### vagrant起動&SSHログイン

```
$ vagrant up
$ vagrant ssh
```

### Apache,PHPのインストール

```
$ sudo yum install -y php
$ sudo yum install -y httpd
```

### apacheにphpを対応
```
$ sudo vi /etc/httpd/conf/httpd.conf 
```

一番下に以下を追加

```conf
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
```

### Apache起動と自動起動設定

```
$ sudo /etc/init.d/httpd start
$ sudo chkconfig httpd on
```

### ngrokインストール

最新版をダウンロード

```bash
$ wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
```

解凍するためにunzipをインストール

```
$ sudo yum install -y unzip
```

解凍

```
$ unzip ngrok-stable-linux-amd64.zip
```

パスが通ってるディレクトリに移動させる

```
$ sudo mv ngrok /usr/local/bin
```

確認

↓こんなん表示されたらOK

```
$ ngrok -v
ngrok version 2.2.8
```


### 疎通確認用のファイルをドキュメントルートに配置する

※ドキュメントルートの設定を確認したい人は↓で`DocumentRoot "{PATH}"`みたいな設定があるのでそこを確認してください

```
$ vi /etc/httpd/conf/httpd.conf
```

ということで今回はデフォルトの設定のままなので `/var/www/html`配下に配置します。

```
$ sudo vi /var/ww/html/index.php
```

ファイルの中身はシンプルに↓

```php
<?php

echo "OK";
```


## 疎通確認

192.168.33.10に接続する

↓こんなん出たらOK

<img width="1356" alt="スクリーンショット 2019-02-26 22.56.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/133737/a7e2b35d-7ff5-eb75-7b33-84e22ae044bd.png">

### ngrok起動

```
$ ngrok http 80
Session Status                online
Session Expires               7 hours, 59 minutes
Version                       2.2.8
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://xxxxxxx.ngrok.io -> localhost:80
Forwarding                    https://xxxxxxx.ngrok.io -> localhost:80

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00
```

上記のようなメッセージが出てくるのでForwardingに記載されているURLにアクセスすると先ほどの画面が表示されたらOK


#### <font color="red">*ngrokを利用するとどの環境からも(URLさえ知っていれば誰でも)アクセス可能なので利用には十分注意してください*</font>

##### ランダムでURLが生成されているとはいえ,悪意あるユーザからのアクセスが可能性としては0ではありません

Basic認証を用いたngrokの利用方法もあるので↓の記事を参考にしてください。
[少しでも安全にngrokを使用する(Basic認証)](https://qiita.com/da-sugi/items/77f5b9bbbd32d8a79bf3)

### おわり
stdClassをnewしたらPHP Warning:  Creating default object from empty value inとなったときの対応方法

- 環境
    - macOS Mojave バージョン10.14.3
    - PHP 7.3.1
    - Laravel Framework 5.7.26

# 事象 : stdClassをnewしたら警告が出た

```php:controlStdClassArray.php 
<?php
namespace App;

class controlStdClassArray
{
    public function createStdClassArrayNew(): array
    {
        $stdobj = new \stdClass();
        $stdobj->name = 'イタリアンパセリ';
        $stdObj->otherName = 'パースレー';
        return $stdobj;
    }
}

$clas = new controlStdClassArray();
var_dump($clas->createStdClassArrayNew());
```

```bash
$ php controlStdClassArray.php 
PHP Warning:  Creating default object from empty value in /path/to/tryPhp/app/controlStdClassArray.php on line 24

Warning: Creating default object from empty value in /path/to/tryPhp/app/controlStdClassArray.php on line 24
object(stdClass)#2 (1) {
  ["name"]=>
  string(24) "イタリアンパセリ"
}
```

# 原因 : 変数名の大文字と小文字が間違っているから
恥ずかしい原因ですがかなり気が付かずに調べたので。
> [PHP: 基本的な事 - Manual](http://php.net/manual/ja/language.variables.basics.php)
> 変数名は大文字小文字を区別します。

よって、`$stdObj->otherName = 'パースレー';`は初期化しないで実行されることとなります。
PHP5.3以降ではstdClassをnew(初期化)しないで実行すると怒られるようになりました。

- PHP5.3 : `PHP Strict Standards:  Creating default object from empty value`
- PHP5.4以降 : `PHP Warning:  Creating default object from empty value`

[PHP5.4からは即時stdClass生成がWarningエラーを吐くようになった話 | ブログ :: Web notes.log](https://blog.wnotes.net/blog/article/php5_4-stdclass-warning)

```php:controlStdClassArray.php 
// 省略
        $stdobj = new \stdClass(); // $stdobjの「o」が小文字
        $stdobj->name = 'イタリアンパセリ';
        $stdObj->otherName = 'パースレー'; // $stdobjの「o」が大文字
        return $stdobj;
// 省略
```

## 対応 : 同じ変数は大文字小文字を合わせる
```php:controlStdClassArray.php 
// 省略
        $stdObj = new \stdClass();
        $stdObj->name = 'イタリアンパセリ';
        $stdObj->otherName = 'パースレー';
        return $stdobj;
// 省略
```
```bash
$ php controlStdClassArray.php 
object(stdClass)#2 (2) {
  ["name"]=>
  string(24) "イタリアンパセリ"
  ["otherName"]=>
  string(15) "パースレー"
}
```
BeagleboneGreenを動かす01

#BeagleboneGreenの概要
BeagleboneGreenはSeeedStudioが製造・販売するシングルボードコンピュータ。
テキサス・インスツルメンツのSitara AM3358を搭載する。
AM3358はarm Cortex-A8 1GHzコア搭載の産業機器向けプロセッサである。
http://www.ti.com/product/AM3358
その他スペックはメーカーweb参照。
https://www.seeedstudio.com/beaglebone-series.html

#BeagleboneGreenを購入する
国内ではAmazonや秋月でも購入できるが、今回は製造元のSeeed Studioから購入。価格は44USDで
PayPalのレートが 1JPY = 0.00872198USDだったので5,044円。秋月の方が安い。。。。
https://www.seeedstudio.com/SeeedStudio-BeagleBone-Green-p-2504.html

配送はFedex,DHL,国際郵便から選択でき、FedexやDHLは送料が高いが3日くらいで着く。
国際郵便は送料は安いが2～4週間程度かかる。また配送の追跡ができない。今回は2月13日に注文して25日に到着した。
Seeed Studioは中国深センにあるがシンガポール経由で送られてきた。

#電源投入
電源はUSB給電である、付属のUSBケーブルでPCまたはUSB充電アダプタに接続すれば良い。

#PCとの接続
##USB接続
USBドライバ
以下のStep2にあるドライバをインストールすればよい。
http://beagleboard.org/static/beaglebone/latest/README.htm
USB仮想イーサーネットドライバがインストールされるので、USBで接続し、ブラウザから http://192.168.7.2/ にアクセスすると以下のようなサイトが表示される。(画像のIPアドレスが違うのはLAN接続したときの画像のため。)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/366164/52544d4f-2232-2153-1100-b4f566eee831.png)

また、リムーバブルストレージとしても認識されるのでその中にもUSBドライバとユーザガイドが入っている。

#LAN接続
初期設定でDHCPに対応しているので、ルータ等でDHCPサーバを動かしていれば自動でIPアドレスを取得できる。
固定IPの設定などはまた後日。

#SSH接続
TeraTermを使ってSSH接続をした。
初期設定のユーザIDは[debian] パスワードは[temppwd]
![image.png](https://qiita-image-store.s3.amazonaws.com/0/366164/b10e2f5b-4763-bc01-e65c-51d1e8f115d3.png)

今日はここまで。
GASでポップアップを出す

勉強したのでメモ

## やりたいこと
こんなかんじでポップアップを出す
<img width="1239" alt="スクリーンショット 2019-02-26 22.52.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/176479/9f18e3af-40e2-3156-6db0-b5e3b92d513b.png">

## 手順
グーグルスプレッドシートで、スクリプトエディタを選択
<img width="1244" alt="スクリーンショット 2019-02-26 22.50.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/176479/a4da9c4f-a3fe-5565-ce8d-df96fbb39739.png">

コード.gsというところに下記のように書く

<img width="1236" alt="スクリーンショット 2019-02-26 22.55.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/176479/69464e68-d76f-4e4d-d45b-91bc2c20c2f8.png">

```javascript

function myFunction() {
  //メッセージボックスを出す
  var result = Browser.msgBox("こんにちは", Browser.Buttons.OK_CANCEL);
  if (result == "cancel"){
    Logger.log("canceled...")
  }
}
```

スプレッドシート上でキャンセルボタンを押した時
`Browser.msgBox("こんにちは", Browser.Buttons.OK_CANCEL)`は`cancel`を返す

## 選択するポップアップ

<img width="606" alt="スクリーンショット 2019-02-26 23.06.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/176479/39ebc78c-a824-b9f9-e4f8-938cb5d1a1d1.png">

```javascript
function myFunction() {
  //メッセージボックスで選択肢を出す
  var result = Browser.msgBox("えらんでね", "あなたはmac?", Browser.Buttons.OK_CANCEL);
  if(result == "yes"){
    Browser.msgBox("おなじだ")
  } else {
    Browser.msgBox("残念・・・")
  }
}
```
<img width="1206" alt="スクリーンショット 2019-02-26 23.07.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/176479/9f2cf734-95c7-51ea-7ef6-311014f8a5c8.png">


```javascript

function myFunction() {
  //入力するメッセージボックス
  var result = Browser.inputBox("御名前は？", "御名前をどうぞ:", Browser.Buttons.OK_CANCEL);
  if (result != "cancel"){
    Browser.msgBox("こんにちは" + result + "さん");
  }
}
```
OneDriveフォルダ以外のフォルダをOneDriveに同期

# 概要
コマンドプロンプトで以下のように入力
```C:\Users\user>mklink /J 'link-name' 'target'
```

# 具体例
Cドライブ直下にdataフォルダ（C:\data）をOneDriveで同期したい。
OneDriveフォルダの直下に同名（data）のリンクを作成することにする。
その場合、コマンドプロンプトで以下のように実行。
```C:\Users\user>mklink /J "C:\Users\user\OneDrive - 株式会社ホゲ商事（営業三課）" "C:\data"
```

# 解説
## mklinkコマンド
`mklink`はリンクファイルを作成するDOSコマンド。
`mklink /J`と指定するとジャンクションポイントを作成できます。

## 空白スペースやら日本語やらのフォルダ名
空白スペースを含むフォルダ名をコマンドプロンプトで認識させるにはダブルクォーテーションでパスを囲みます。
私の会社用アカウントのOneDriveフォルダには空白スペースが含まれていて（"OneDrive - 株式会社ホゲ商事（営業三課）"）、データ処理に必要なプログラムが動かなかったので、今回の処置に至りました。なんで空白スペースなんて余計なものを入れるんだよ。。。フォルダ名の変更方法がわらかずに困っていたところ、下記のサイトをみつけて参考にさせていただきました。

## 参考サイト
[ココロオドルマイニチ：OneDriveで任意のフォルダ・外部HDDのフォルダを同期させる方法](https://work.lifemake.design/entry/2017/09/25/190000)
dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.63.dylib

# エラー

```
dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.63.dylib
  Referenced from: /usr/local/bin/php
  Reason: image not found
Abort trap: 6
```

# 解決策
```
$ brew uninstall --ignore-dependencies node icu4c
$ brew install node
$ brew link --overwrite node
```
GORM で Null アップデート

# はじめに

Go の O/R マッパーである GORM を使っていて、NULL でのアップデートに困っていたので記載しておきます。

# 環境
* Go 1.11.5
* jinzhu/gorm v1.9.2

# 結論

以下の User モデルを更新する例です。

```go
type User struct {
	ID   uint `gorm:"primary_key"`
	Age  int
	Name string
}

var user User
db.First(&user)

// 1 カラムの NULL アップデート
db.Model(&user).Update("name", gorm.Expr("NULL"))
// 実行 SQL : UPDATE `users` SET `name` = NULL  WHERE `users`.`id` = '1'

// 複数カラムの NULL アップデート
db.Model(&user).Updates(map[string]interface{}{
	"age":           18,
	"name":          gorm.Expr("NULL"),
})
// 実行 SQL : UPDATE `users` SET `age` = '18', `name` = NULL  WHERE `users`.`id` = '1'
```

SQL Expression によるアップデートに使用する `gorm.Expr` を使用して、直接 `NULL` を渡すことで NULL でアップデートができることが分かりました。

# 試行錯誤

通常のアップデートであれば以下のように指定することで可能ですが、NULL でアップデートするには `nil` を渡すなどで上手くいきませんでした。

```go
db.Model(&user).Updates(User{Age: 18, Name: "hello"})
```

## nil でのアップデート

`NULL` を含んだ Insert 文を実行するには、対象のカラムをポインタにして `nil` を渡すことで作成されます。

```diff
type User struct {
	ID   uint `gorm:"primary_key"`
	Age  int
-	Name string
+	Name *string
}
```

実際に実行してみると、`NULL` で作成されていることが分かります。

```go
user := User{ID: 1, Age: 18, Name: nil}
db.Create(&user)
// 実行 SQL : INSERT INTO `users` (`id`,`age`,`name`) VALUES ('1','18',NULL)
```

では、同じ要領でアップデートでもポインタにしたカラムに `nil` を渡してみると、無視されてしまうことが分かりました。

```go
var user User
db.First(&user)

db.Model(&user).Updates(User{Age: 18, Name: nil})
// 実行 SQL : UPDATE `users` SET `age` = '18'  WHERE `users`.`id` = '1'
```

[GORM のドキュメント](http://doc.gorm.io/crud.html#query)を見ると以下のように書いてあったので、構造体で実行すると無視されてしまうようです。
>When query with struct, GORM will only query with those fields has non-zero value, that means if your field's value is 0, '', false or other zero values, it won't be used to build query conditions,

# 参考
[How Do I Set a Field To NULL?](https://github.com/jinzhu/gorm/issues/1073)
[GORM](http://doc.gorm.io/)
Twythonを使って色々やってみる

## twythonをインストール
```
$ pip install twython
```
## OAuth 2設定
twythonをimportし、TwitterのAPI情報を設定

```python
from twython import Twython

APP_KEY = 'YOUR_APP_KEY'
APP_SECRET = 'YOUR_APP_SECRET'

twitter = Twython(APP_KEY, APP_SECRET, oauth_version=2)
ACCESS_TOKEN = twitter.obtain_access_token()

twitter = Twython(APP_KEY, access_token=ACCESS_TOKEN)
```
Tweetをキーワードで抽出

```python
twitter.search(q='xxx')

#人気順で表示する場合は↓等、色々カスタマイズできます（リファレンスtwitter developer参照）
#twitter.search(q='xxx', result_type='popular')
```

## リファレンス
[twython](https://twython.readthedocs.io/en/latest/index.html)
[twitter developer](https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets
)
掛け算のようで割り算、割り算のようでいて掛け算

素人考えなので、役に立つことはない話。
ちゃんとしたことは数学の先生に聞いてくださいね。

(向きのない数は)個数を数えるとか、個数の割合でいう密度で表したりする(と思う)。

1×4=4 とか。1というものが、4個あると考える。

つぎに、Z(n)={-n,...,-4,-3,-2,-1,0,1,2,3,4,...,n}の集合を考える。要素数は 2n+1個で1個の集合だ。4×Z(n)とすると、{-4n,...,-8,-4,0,4,8,...,4n}みたいになる。個数は2n+1個だ。

### 掛け算のようでいて、結果が割り算なもの
$\mathbb{Z}$={...,-4,-3,-2,-1,0,1,2,3,4,...}とすると、要素数は∞個で一つの集合になる。$4\times\mathbb{Z}$とすると、$4\mathbb{Z}$={...,-8,-4,0,4,8,...}みたいな4の倍数の集合になる。集合の詰まり具合は、1/4になる。{4の倍数},{4の倍数+1},{4の倍数+2},{4の倍数+3}と集合を4つに割った集合の一つだから。

数学チックに書くとこうなる。

```math
\mathbb{Z}=\{4n\mid n \in \mathbb{Z}\}\cup
\{4n+1\mid n \in \mathbb{Z}\} \cup 
\{4n+2\mid n \in \mathbb{Z}\} \cup
\{4n+3\mid n \in \mathbb{Z}\}
```

掛け算をしているようでいて、集合を割っている。

### 割り算のようでいて、結果が掛け算のようなもの
$\frac{1}{4}\times\mathbb{Z}$とすると、$\frac{1}{4}\mathbb{Z}$={...,$-\frac{2}{4}$, $-\frac{1}{4}$, 0, $\frac{1}{4}$,  $\frac{2}{4}$, $\frac{3}{4}$, 1,...}みたいな1/4の倍数の集合になる。元の集合$\mathbb{Z}$と比べると、{$\mathbb{Z}$}, {$\mathbb{Z}$+1/4},{$\mathbb{Z}$+2/4},{$\mathbb{Z}$+3/4}と集合の数が4倍になる。

割り算をしているようでいて、集合を掛け合わせ増やしている。

### 割り算は仲間がいて始めて成り立つ？
割り算とは「これが1だぞ」という仲間を決めて、その仲間で集合を分割することだと思う。例えば、リンゴが2つあって半切れを1つだぞ、と決める。2÷ (1/2)=4で4切れあるとか、1km=1000mのように1000個の塊を1だとみなそうぜ・・・とか。(群論でも部分群Hを単位元eとみなせば、同じこと)

### 掛け算は、集合の組み合わせ？
そう考えると、割り算が身近になる一方で、掛け算とは何だろうと思う。
集合の組み合わせともいえるかもしれない。

直積という演算で、集合の組み合わせを作る。

{a, b}●{x, y, z}={a●x, a●y, a●z, b●x, b●y, b●z}

{a, b}の要素数は2、{x, y, z}の要素数は 3 となる。掛け合わせたあとの要素数は6になる。
2×3 は 6 って奴に似た何かに見えない？

ついでにいうと、{x, y, z} がひと塊、つまり 1 とみなせば、次のようになる。

{a, b}●{x, y, z} = {a●{x, y, z}, b●{x, y, z}} 

要素数は2で 2×1=2 といった掛け算ともいえるし、{x, y, z}を固まりにする行為が、6÷3=2 としたとも言える。
【pandas】最も近い値でマージするmerge_asof関数

# はじめに
今まで存在を知らなかったのですが、めちゃめちゃ便利なのでメモ。
pandas の merge_asof関数について紹介します。
初投稿ですのでお手柔らかに。

# 基本的な例
```python
import pandas as pd
df_left = pd.DataFrame({'a': [1, 5, 10], 'left_val': ['a', 'b', 'c']})
df_right = pd.DataFrame({'a': [1, 2, 3, 6, 7], 'right_val': [1, 2, 3, 6, 7]})
```
と２つのテーブルがあったとします。

このとき、

```python
pd.merge_asof(df_left, df_right, on='a', direction='nearest')
```
と書くだけで、df_left のカラム['a'] に対し、df_right['a'] の最も近い値をキーとして、
2つのテーブルを結合することができます。

<img width="250" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/222558/f0e0fb0b-1ba1-17b6-cb03-256275d81cc4.png">

図のように、

* df_left['a'] = 1 に最も近い、df_right['a'] = 1の right_val を結合
* df_left['a'] = 5 に最も近い、df_right['a'] = 6の right_val を結合
* df_left['a'] = 10 に最も近い、df_right['a'] = 7の right_val を結合

していることが分かります。


# 許容する範囲の指定
"tolerance" という引数を使うことで、最も近い値をどこまで許容するか、
指定することができます。

```python
import pandas as pd
pd.merge_asof(df_left, df_right, on='a', direction='nearest', tolerance=2)
```

<img width="250" alt="キャプチャ2.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/222558/b7f0c80c-6503-16b7-56f0-46ab5828c7fc.png">
a=10 に最も近い df_right['a'] は7ですが、
指定した tolerance=2 よりも差が大きいので、NaNが入っています。


# 参考
公式リファレンス：https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.merge_asof.html
sympyで. (積分) 「2019年　東京大学 前期日程 数学（理科） 第1問」 をやってみたい


(参考)東京大学 理科一類、理科二類、理科三類前期の問題・解答＜Toshin.com
http://www.toshin.com/sokuho/univ.php?univname=%C5%EC%B5%FE%C2%E7%B3%D8&gakkaname=&gakubuname=%CD%FD%B2%CA%B0%EC%CE%E0%A1%A2%CD%FD%B2%CA%C6%F3%CE%E0%A1%A2%CD%FD%B2%CA%BB%B0%CE%E0&housikiname=%C1%B0%B4%FC&kamokuname=%BF%F4%B3%D8
https://www.wolframalpha.com/input/?i=Integrate%5B(x**2%2Bx%2Fsqrt(1%2Bx**2))*(1%2Bx%2F(1%2Bx**2)%2Fsqrt(1%2Bx**2)),%7Bx,0,1%7D%5D
Integrate[(x**2+x/sqrt(1+x**2))*(1+x/(1+x**2)/sqrt(1+x**2)),{x,0,1}]
(-70 + 60 Sqrt[2] + 3 Pi)/24

```fullscript.py
from sympy import *
x = Symbol('x')
f=(x**2+x/sqrt(1+x**2))*(1+x/(1+x**2)/sqrt(1+x**2))
print(f)
print(integrate(f,(x, 0, 1)))
# (x**2 + x/sqrt(x**2 + 1))*(x/(x**2 + 1)**(3/2) + 1)
# -35/12 + pi/8 + 5*sqrt(2)/2
```

#解答例の手順通り
製作中
Android Phone : ARCore01-HelloAR

<H3>Source</H3>
gitlab:https://gitlab.com/kangyueLuo/helloar

<H3>Start</H3>
對於擴增世界應用的喜愛，在加上 Google ARCore 降低了使用擴增實境技術的門檻，及 Youtube 上許多教學影片，幫助我推開了 AR世界的門。

<H3>Reference</H3>
https://www.youtube.com/watch?v=EWXGaypl2ms&index=2&list=PLsOU6EOcj51cEDYpCLK_bzo4qtjOwDWfW&fbclid=IwAR3lJFYH9b_MptZHkTkbSA3Ri1Cqr7Tuq1XqAkTSHxQef3K_X2wHImoFTNU
Linux の Homebrew を試した

こんにちは
Homebrew for Linux が公式サポートされ 、実際にインストールして試してみました[^1]。最新バージョン（例えば GitHub の latest バージョン）をほぼ常に使いたい場合には解となりそうです。

[^1]: 「[brewがlinuxで使えるらしいのでやってみる](https://qiita.com/ryicoh/items/8db8df2d0786abb17c08)」などで紹介されています。

```console
$ brew --version
Homebrew 2.0.2
Linuxbrew/homebrew-core (git revision 26046; last commit 2019-02-26)
$ brew install gcc binutils
$ g++ --version
  g++ (Homebrew gcc 5.5.0_4) 5.5.0
$ ld --version
GNU ld (GNU Binutils) 2.32
$ which gcc
/home/linuxbrew/.linuxbrew/bin/gcc
$ which ld
/home/linuxbrew/.linuxbrew/bin/ld
```

標準的なコンパイル方法例は、

```console
$ g++ -std=c++11 -I/usr/include -I$HOMEBREW_PREFIX/include -L$HOMEBREW_PREFIX/lib test.cpp
```

なお MacOSX （の Homebrew）の場合では、Xcode でインストールした ```clang++``` を使い、```/bin/ls``` を使うところが、比較すると異なっている気がしました。
ローカルでビルドしたものをpackageするときは --template-file オプションはつけない

## Overview

* AWS SAM を使ってpackageを実行するとき、 `--template-file` オプションでテンプレートファイルを指定してしまうと `--template-file` で指定したファイルの `CodeUri` にあるリソースをもとに package を実行しようとする
* ローカルでビルドしたものをデプロイするときは `--teplate-file` オプションはつけてはいけない

## 問題に気づいた経緯

* ローカルでビルドしたものをデプロイするさいに、 `node_modules` 配下のファイルが Lambda Function にデプロイされていない
* `.aws-sam/build` 配下には `node_modules` 配下のリソースが生成されている

build、package 実行時のコマンドは以下でした

```sh
sam build
sam package \
  --template-file template.yaml \
  --output-template-file packaged.yaml \
  --s3-bucket my-bucket \
;
```

## 原因

AWS SAM を使ってデプロイするとき、 `--template-file` オプションでテンプレートファイルを指定すると `--template-file` で指定したファイルの `CodeUri` にあるリソースをデプロイしようとするため.
CodeUri にはビルド前のリソースが指定されているので、これをデプロイしようとすると `node_modules` 配下は含まれていないため、デプロイ後の Lambda Function にも `node_modules` が含まれていない.

## 解決方法

ローカルでビルドしたものをpackageするときは `--template-file` オプションはつけない

```sh
sam build
sam package \
  --output-template-file packaged.yaml \
  --s3-bucket my-bucket \
;
```

## 教訓

**ツールが中でどんな処理を行っているのかちゃんと把握しよう**。

アーティファクトの依存関係からして当たり前っちゃ当たり前ですね。。
`template.yaml` (入力) => `sam build` => `pacakged.yaml` (出力) という関係なので、
次のステップで `sam package` を実行するときに入力として `template.yaml` を指定するのはおかしいわけです。
`package` でこのオプションを指定するのは、ローカルでビルドした資材を直接 Lambda Function にデプロイする場合です。

## 参考

GitHub に Issue が上がっていました
https://github.com/awslabs/aws-sam-cli/issues/908
Flux.jlでSin波を学習する

# 背景
Juliaにはいくつかニューラルネットワークライブラリがある。
私は昔Mocha.jlを使っていたがJulia1.0以降だと今の所非推奨ということなのでFlux.jlに移民した。
自分の中で新しいニューラルネットワークのライブラリを使う時Sin波を学習するという儀式があるので、儀式を行った。

# コード
```julia

using Plots
gr()

using Flux
using Statistics
using Flux.Tracker: TrackedReal, data
using Flux: mse
using Base.Iterators: repeated, flatten

# 訓練データ
N = 100
X = range(0, stop = pi, length = N)
Y = sin.(X)

# 訓練データをプロットしておく
plot(X, Y)

data_x = [[x] for x in X]
data_y = [[y] for y in Y]
# batch処理すべきだが、めんどうなのでrepeatedでごまかした。
# Model-Zooもrepeatedでなんとかしてる奴あるしいいよね。
data_xf = Iterators.flatten(repeated(data_x, 100))
data_yf = Iterators.flatten(repeated(data_y, 100))
入力データは[(入力の配列, 出力の配列)]な形式
dataset = zip(data_xf, data_yf)

# モデル
m = Chain(
  Dense(1, 20, relu),
  Dense(20, 1, σ))

loss(x, y) = mse(m(x), y) 

opt = Descent()
Flux.train!(loss, params(m), dataset, opt)

Nt = 100
Xt = range(0, stop = pi, length = Nt)
input_xt = [[x] for x in Xt]
expect_yt = m.(input_xt)

Yt = collect(Iterators.flatten(expect_yt))
# 結果はTrackedRealという型に入ってくるため数字だけ抜き出す。
Yt2 = data.(Yt)

plot!(Xt, Yt2)
png("result.png")
```

# 結果
![result.png](https://qiita-image-store.s3.amazonaws.com/0/292138/210e526c-6f55-e4e4-6d72-2e806a03fa72.png)

# どうでもいい話
彼女欲しいので女性紹介してください。
GCEでSSH鍵でログインが出来ない(（Permission denied (publickey,gssapi-keyex,gssapi-with-mic)）の解決方法

# 事象
1. ちゃんとSSHの鍵は設定している。（以下のキャプチャは設定してないけど、本来はちゃんと設定されている）
<img width="753" alt="SSH鍵設定箇所.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/17419/f51e1ae0-3db4-d2d8-b7d7-8cc17266ebbb.jpeg">
2. SSHポートも空いている
3. クライアント側からSSHログインをしようとするとエラーがPermission denied (publickey,gssapi-keyex,gssapi-with-mic)
4. /var/log/secure を確認すると

```
Feb 25 16:31:59 wp sshd[20577]: Received disconnect from xx.xx.xx.xx
```
もはや、何が原因がわからない状態。

# 原因
1. .ssh自体の権限は700に設定されているか！？
2. authorized_keysの権限は600になっているのか！？
3. id_rsaの権限は600になっているのか！？(ローカルPC)
4. id_rsa.pubの権限は644になっているのか！？(ローカルPC)→あまり気にしなくても良い
5. 公開鍵(authorized_keys)はちゃんとコピペできているか！？

この辺を確認する。
https://blog.adachin.me/archives/2054 より

すると、 /home/[ユーザ]/.ssh/authorized_keys が存在しない。
gcpのComputeEngine→VMインスタンスから、SSH鍵をいくら設定をしても駄目。
再起動しても駄目。 （バグ？かと思ったけど、このPJだけで他のPJだとちゃんとauthorized_keysが出来る）
ここの部分をいくら設定しても駄目。
<img width="753" alt="SSH鍵設定箇所.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/17419/f51e1ae0-3db4-d2d8-b7d7-8cc17266ebbb.jpeg">

# 対策
いくらComputeEngine→VMインスタンスから、SSH鍵を作成しても駄目なので、手動でやる。

1. authorized_keysを/home/[ユーザ]/.ssh/ にコピペ
2. authorized_keysの権限は600にする
3. authorized_keysのユーザをログインユーザに合わせる。

これでようやくログインが出来る。

# 稀なのかもしれない
普通、ComputeEngine→VMインスタンスから、SSH鍵を設定すれば、authorized_keysは自動出来る。
いくらググっても同じ条件で苦しんでいる人が出てこない。
これは稀なのか。

# なんとなく原因
SSHのログイン管理を一時的にIAMで管理していたことがあり、その設定が残ると、authorized_keysが出来ない気がする。
カスタムメタデータの `enable-oslogin` を消して、VM再起動しても駄目だった。
一度やってしまうと、そうなるのかもしれない。
ROOTをMacにインストールしたときのエラー対処メモ

# MacにROOTをインストールする

## はじめに


CERNが開発しているデータ分析ソフトであるROOTをMacにインストールしたときにエラーが出たので、その時の対処方法メモ。


Linuxへのインストールはこちらを参考までに。
https://qiita.com/dyamaguc/items/2f723cbc304c4debd82e

自分の環境は次の通り。
- Mac Book Air
- Mac OS X 10.13.6
- Xcodeやコンパイラはインストール済み

## インストール

ROOTをこちらのページからダウンロード。
https://root.cern.ch/content/release-61406
今回は
root_v6.14.06.macosx64-10.13-clang100.dmg
このファイルをダウンロードした。
その後、ダウンロードしたファイルをダブルクリックして、インストーラーを起動。
デフォルトのまま進めてインストール自体は完了。

## Pathを通す

このインストーラーを使用すると、ROOTは
`/Applications/root_v6.14.06`
にインストールされる。
ターミナルを開いて、
`source /Applications/root_v6.14.06/bin/thisroot.sh`
とコマンドを打てば、ROOTの準備は完了。
（`.bash_profile`に上のコマンドを書いておくのがおすすめ）

## ROOTを起動とエラー内容

ターミナルを開いて、
`root`コマンドをたたくと、次のようなメッセージが表示された。

````
$root
ERROR in cling::CIFactory::createCI(): cannot extract standard library include paths!
Invoking:
  LC_ALL=C /Library/Developer/CommandLineTools/usr/bin/c++   -O2 -DNDEBUG -xc++ -E -v /dev/null 2>&1 >/dev/null | awk '/^#include </,/^End of search/{if (!/^#include </ && !/^End of search/){ print }}' | GREP_OPTIONS= grep -E "(c|g)\+\+"
Results was:
With exit code 256
input_line_1:1:10: fatal error: 'new' file not found
#include <new>
         ^~~~~
input_line_3:37:10: fatal error: 'string' file not found
#include <string>
         ^~~~~~~~
   ------------------------------------------------------------
  | Welcome to ROOT 6.14/06                http://root.cern.ch |
  |                               (c) 1995-2018, The ROOT Team |
  | Built for macosx64                                         |
  | From tags/v6-14-06@v6-14-06, Nov 05 2018, 10:35:04         |
  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q' |
   ------------------------------------------------------------

input_line_9:1:10: fatal error: 'iostream' file not found
#include <iostream>
         ^~~~~~~~~~
root [0] 
````

なんだかライブラリを読み込めていなさそう...

調べてみたところ、こちらのQAを読むと...
https://root-forum.cern.ch/t/cannot-extract-standard-library-include-paths/27494/6

`$xcode-select --install`
というコマンドで解決したそうな。

ターミナルを開いて、このコマンドを実行。インストールするか？と聞かれるので、インストールボタンを押す。
しばらく（5分程度）でインストール完了。
ターミナルを起動し直して、再び`root`コマンドをたたくと

````
$root
   ------------------------------------------------------------
  | Welcome to ROOT 6.14/06                http://root.cern.ch |
  |                               (c) 1995-2018, The ROOT Team |
  | Built for macosx64                                         |
  | From tags/v6-14-06@v6-14-06, Nov 05 2018, 10:35:04         |
  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q' |
   ------------------------------------------------------------

root [0] 
````

直った！
クラスの継承

未来電子テクノロジー(https://www.miraidenshi-tech.jp/intern-content/program/ )でインターンをしている@hisayamaです。
今回はクラスの継承についてアウトプットします。

#クラスの継承
新しいクラスを作る上で、もともとあるメインのクラスのプロパティやメソッドを継承して、それに色々付け加えたい時はクラスの継承を行います。

新しい子クラスはこのように定義します。

```php
class 子クラス extends 親クラス {          }
```
この親クラスはスーパークラスとも呼び、継承したクラスのことを指します。
このように定義することで、親クラスのコンストラクタやメソッドが呼び出せるようになります。
さらに子クラスでは子クラス独自のプロパティやメソッドを追加できます！

ちなみに子クラスは複数の親クラスを継承できません。1つだけです。
反対に親クラスは複数の子クラスに継承できます。


子クラスのメソッドを呼び出すとします。
もし、子クラスにメソッドが定義**されている**場合は、**子クラス**のメソッドが呼び出されます。
一方で定義**されていない**場合、**親クラス**のメソッドが呼び出されます。

反対に、子クラスで設定した独自プロパティやメソッドは親クラスからは呼び出せないので注意が必要です！
Ruby 　irb、テキストエディタ使用とエラー解決方法

動作環境はMacとなります。
主に自分の勉強用メモとして残しています。

#Rubyプログラム　irb使用
文字列はシングルクオートかダブルクオートで囲む

```irb
irb(main):001:0> "Hello, World"
=> "Hello, World"#Rubyは最後の式を自動的に出力するので、プログラムとは言えない。
```

putsは何かを出力する命令で、これをつけることでプログラムと言える。

```irb
irb(main):004:0> puts 'Hello World!'#これがプログラム
Hello World!
=> nil#putsは必ずnilを返す
```
数値の計算


```irb
irb(main):005:0> 1 + 1
=> 2
irb(main):006:0> 10 - 1
=> 9
```

###irbで記述したプログラムをクリアしたい時
clear か　control+lキー

###irbを終了したい場合
exit　か　contol+dキー

#テキストエディタ使用 

この環境ではAtom使用しています。
＄はターミナルでの操作を表します。

###ファイル作成



```
$mkdir ruby_projects　#mkdirはmake directoryの略でファイル作成の意味
```

```
$ls #今いるディレクトリの中身を確認
$cd ruby_projects/　#今いるディレクトリから移動
$touch hello.rb #ファイル作成
$atom . #Atomを開く時のコマンド
```

rubyプログラムを作成する場合、拡張子は.rbとする。

##テキストエディタ

```hello.rb
puts 'Hello, World!'#行末に;をつけてもエラーにはならないが、rubyは改行で認識されるため通常書かない
puts 10 + 3
```

ターミナル

```
$ ruby hello.rb #ruby　+ ファイル名で出力
Hello, World!
13
```

##Linuxコマンド

現在のディレクトリをカレントディレクトリという。
ディレクトリとファイルはざっくり同じ。

```
$ pwd #現在いるファイルの階層を表示
$ cd .. #現在いるフォルダの１つ上の階層に移動
$ ls #現在いるフォルダの中身を表示
```

###エラーを自力で取り除く方法

```hello.rb
puts 'Hello, World!'
put 10 + 3 #putsをputと間違えた
```

ターミナル

```
$ ruby hello.rb
Hello, World!　#問題なく出力される。
hello.rb:2:in `<main>': undefined method `put' for main:Object (NoMethodError)
#hello.rbファイルの二行目のputというメソッドがないよというエラー
Did you mean?  puts
               putc
#もしかしてこういう意味？とエラーが教えてくれている。
```

メソッドとは処理のまとまりのこと。
エラーメッセージをグーグル検索すると、解決の意図が見つかることが多い。
特にrubyは日本で広く普及されているので、情報が見つかりやすい。

**以上を踏まえて修正**

```hello.rb
puts 'Hello, World!'
puts 10 + 3 #putをputsへ修正
```

ターミナル

```
$ ruby hello.rb
Hello, World!
13
```

正常にプログラムが実行された！
気軽にRedisに触れてみる

## 環境

Docker for MacがインストールされているMac OS

## Dokcer Hubからイメージを取得

```
$ docker image pull redis:latest
```
  * `image`は省略可

## 取得したイメージからDockerコンテナの立ち上げ

```
$ docker container run --name test-redis -d redis
```
  * `container`は省略可能

## コンテナのプロセスを確認

```
$ docker contatiner ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
0d84da96b73b        redis               "docker-entrypoint.s…"   3 seconds ago       Up 4 seconds        6379/tcp            test-redis
```
  * `container`は省略可能

## クライアント用コンテナにログイン

```
$ docker container run -it --name test-redis-cli --link test-redis:redis --rm redis redis-cli -h redis -p 6379
redis:6379> scan 0 match *
1) "0"
2) (empty list or set)
```
  * `container`は省略可能
  * プロセスを確認すると、ログイン中はコンテナが2つ立ち上がっている

```
$ docker container ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS               NAMES
7b20f5d32830        redis               "docker-entrypoint.s…"   8 seconds ago        Up 8 seconds        6379/tcp            test-redis-cli
0d84da96b73b        redis               "docker-entrypoint.s…"   About a minute ago   Up About a minute   6379/tcp            test-redis
```

## SET, GET

```
redis:6379> set foo bar
OK
redis:6379> get foo
"bar"
```

## INCR, DECR

```
redis:6379> set foo 10
OK
redis:6379> incr foo
(integer) 11
redis:6379> incr foo
(integer) 12
redis:6379> decr foo
(integer) 11
```

## DEL

```
redis:6379> set foo bar
OK
redis:6379> get foo
"bar"
redis:6379> del foo
(integer) 1
redis:6379> get foo
(nil)
```

## SCAN

```
redis:6379> set A 10
OK
redis:6379> set B 11
OK
redis:6379> set C 12
OK
redis:6379> scan 0 match *
1) "0"
2) 1) "C"
   2) "B"
   3) "A"
```
  * `keys *`は良くない

## 参考

- https://hub.docker.com/_/redis/
- http://redisgate.jp/redis/command/scan.php
UE4の参照とReferenceViewerについて

# ReferenceViewerとは？
エディタに標準搭載されておりアセット間の参照を調べるツールです。
対象のアセットがどのアセットを参照しているか、参照されているかなどを調べることが出来ます。

# 参照の種類
参照の種類は大きく2つあります。
**ハードリファレンス**と**ソフトリファレンス**です。

ハードリファレンスされているアセットは、
**参照しているアセットがロードされると一緒にロードされます。**
ソフトリファレンスはロードされません。

そのままGetするとロードされていないため、
正常に扱うことが出来ません。
FStreamableManager などからロードしてから使う必要があります。
![sample.png](https://qiita-image-store.s3.amazonaws.com/0/177910/a13442fa-2b1d-45ce-a851-994d3beda44b.png)
画像の白い線で繋がれているものがハードリファレンスされているもので、
下の色がついた線はソフトリファレンスされているものです。

# リファレンスの注意
大きなメモリ確保を行うアセットをハードリファレンスしていると、
実機のメモリを大きく使ってしまうことがあります。
例：
アクターA（10MB）がアクターB（100MB）をハードリファレンスすると、
110MBのメモリが使用されます。

# 参考
[公式ドキュメント](http://api.unrealengine.com/JPN/Engine/Content/Browser/ReferenceViewer/)
AnimateCCで生成したファイルの画像をbase64化する方法

#概要
ゲームの広告だがそのゲームの一部を疑似体験できる、プレイアブルアドという代物を実装することになった。
アプリ上のwebviewで表示されるので、ターゲットブラウザはsafariとchrome。
通常のhtml,css,jsでイケるのだが、複雑なことになると工数かかりそうだなーと思っていたがAdobe AnimateCCという持て余しまくっているツールのことを思い出したので、それで作ってみた。快適快適。
が、とある広告プラットフォームの入稿のフォーマットは**単一htmlのみ。**
画像のパスをbase64にすれば良いだけの話がいたくハマったので、解決策をここに記す。

#間違い
animteCCから書き出されたjsにこんな記載があります。

```javascript
lib.properties = {
  	id: 'CBE7D0B014C34055B50EB7B1A2F1A211',
  	width: 640,
  	height: 1136,
  	fps: 24,
  	color: "#FFFFFF",
  	opacity: 1.00,
  	manifest: [
  		{src:"images/test_atlas_.png?1551178733007", id:"test_atlas_"}
  	],
  	preloads: []
  };
```
これだけ見ると、srcの中身をbase64化したものに変えるだけで良いと思うが、全然動きません。
理由は、**裏でPreloadJSが動いているから。**
animateCCは基本的にCreateJSにおんぶにだっこなので、マニフェスト内の画像はPreloadJSによって事前ロードされます。
なので、base64をhtml内のimgタグに書き、jsでそいつを読み込んであげてanimate内の画像管理部分に紐づけてあげる、までを自前でやる必要があります。

#htmlに追記する
html内にimgタグでbase64を書いちゃいましょう。

```html
<img id="test_atlas_" style="display:none" width="2048" height="2048" title="" alt="" src="data:image/png;base64,iVBORw0K...">
```
canvasの下あたりにimgタグを追加します。**display:none**にしておくことを忘れず。
idは、上で紹介したmanifestのidと同じ名前にしましょう。

#jsを改造する
###animateでエクスポートしたjsに変数を追記
最後のほうで、グローバル変数を定義している部分があるので、createjs, AdobeAn,に続き、「images」を追加します。

```javascript
})(createjs = createjs||{}, AdobeAn = AdobeAn||{});
var createjs, AdobeAn, images;
```

###htmlのインラインjsでpreloadの記載を修正
init()の上からすぐに見つかると思うので、この5行をコメントアウトします。

```javascript
// var loader = new createjs.LoadQueue(false);
// loader.addEventListener("fileload", function(evt){handleFileLoad(evt,comp)});
// loader.addEventListener("complete", function(evt){handleComplete(evt,comp)});
// var lib=comp.getLibrary();
// loader.loadManifest(lib.properties.manifest);
```

そして、下記を追加します。
images変数を初期化し、htmlにべた書きしたbase64の画像と、manifestのidを紐づけています。

```javascript
images = images||{};
var manifest = lib.properties.manifest;
for (var i=0, l=manifest.length; i<l; i++) {
  	var id = manifest[i].id;
  	var img = document.getElementById(id);
  	if (img != null) {
  		images[id] = img;
  	}
}
handleComplete(comp);
```

###もうちょい修正
loaderの記述のすぐ下のほうに、handleCompleteという関数があります。
修正前はloaderのcompleteイベントも一緒に渡していたのですが、loader使わないので引数を修正します。

```javascript
//function handleComplete(evt, comp) {
function handleComplete(comp) {
```

さらにすぐ下のほう、この一文もいらないのでコメントアウト。

```javascript
// var queue = evt.target;
```

最後です。さらにすぐ下のほう。for文でloaderから画像の本体を引っ張ってくる部分を、loaderではなく自前で用意したimagesに置き換えてあげます。

```javascript
for(i=0; i<ssMetadata.length; i++) {
  	// ss[ssMetadata[i].name] = new createjs.SpriteSheet( {"images": [queue.getResult(ssMetadata[i].name)], "frames": ssMetadata[i].frames} )
    ss[ssMetadata[i].name] = new createjs.SpriteSheet( {"images": [images[ssMetadata[i].name]], "frames": ssMetadata[i].frames} )
}
```

#終わり
これで画像をソース内に入れ込むことができました！
cdnから読んでるcreateJSもインラインに含めてしまえば、立派な**入稿用単一html**が完成しました！
プレイアブルアドの実装を考えている方の参考になれば幸いです。**ニッチすぎる！！！！**
現場からは以上です。

参考（これしかなかった）
https://www.reddit.com/r/createjs/comments/4dfldb/how_do_i_use_base24_instead_of_external_library/
nmcliでネットワークの初期設定の実施

![computer_hub_loop_setsuzoku.png](https://qiita-image-store.s3.amazonaws.com/0/258841/497691c7-d741-566b-0472-1b805a83dd0d.png)

## 背景

ネットワーク関連の設定方法nmcli編
仮想マシン構築したりする際にぱっと出てこないのでチートシート

#### man

何事もmanを読むとこから。
usageだけ参照。

``` bash 
NAME
       nmcli - command-line tool for controlling NetworkManager

SYNOPSIS
       nmcli [OPTIONS...] {help | general | networking | radio | connection | device | agent |
             monitor} [COMMAND] [ARGUMENTS...]
```

#### NIC繋いだらやること

``` bash
デバイスを確認
$ nmcli device

インターフェイスを有効化
$ nmcli connection modify eth0 connection.autoconnect yes
```

#### IPアドレス変更

``` bash
$ nmcli connection modify ens1 ipv4.method manual ipv4.addresses 192.168.1.100/24 
```

再起動後も含めた恒久的な変更は「connection.autoconnect yes」を付与するだけです。
nmtuiでいう「autoconnect」がこれに当たります。

``` bash
$ nmcli connection modify ens1 ipv4.method manual ipv4.addresses 192.168.1.100/24 connection.autoconnect yes
```

デフォルトゲートウェイやDNSも変更できる

``` bash
デフォルトゲートウェイを設定
$ nmcli connection modify eth0 ipv4.gateway 172.16.0.1

DNS設定
$ nmcli connection modify eth0 ipv4.dns 172.16.0.1
```

#### ホスト名変更

hostnamectlとかでもいいですがnmcliでも変更できます。便利。
「systemd-hostnamed」

``` bash
$ nmcli general hostname srv01
$ systemctl restart systemd-hostnamed
```

#### NIC名変更

NICの名前の変更も出来ます。
デフォルトで6系から命名規則が変わりましたが

```
$ nmcli c m ens0 connection.interface-name enp0s8 connection.id ens
```

#### Bondig

bondingデバイスを追加

``` bash
$ nmcli connection add type bond autoconnect no con-name bond01 ifname bond01 mode active-backup
```

slaveを割り当てる

``` bash
$ nmcli connection add type bond-slave autoconnect no ifname enp8s0f1 master bond01
```

bondingデバイスへIPアドレスを割り当てる

``` bash
$ nmcli connection modify <bond con-name> ipv4.method manual ipv4.address <ip address/suffix> ipv4.gateway <gateway address> ipv6.method ignore

$ nmcli  connection modify <bond con-name> ipv4.dns <dns address>
```

自動接続設定の無効化(元のNICの設定を変更)

``` bash
$ nmcli connection modify <slave con-name①> connection.autoconnect no
```

自動接続設定

``` bash
$ nmcli connection modify bond-slave-<slave con-name①> connection.autoconnect yes
$ nmcli connection modify bond-slave-<slave con-name②> connection.autoconnect yes
$ nmcli connection modify <bond con-name> connection.autoconnect yes
$ nmcli connection modify <bond con-name> connection.autoconnect-slaves 1
```

Bondigモデルの説明

```
・balance-rr
全スレーブを順繰り(ラウンドロビン)に使ってパケットを送信。
送信のみ負荷分散。

・active-backup
1つのスレーブのみを active interfaceとしパケットを送信。
active interfaceに障害が発生した場合、他の backup slave を active interfaceに切り替え、冗長性を確保。

・balance-xor
送信元/先 MACアドレスを元に送信スレーブを決定しパケットを送信。
送信のみ負荷分散。

・802.3ad
IEEE 802.3ad(LACP)に準拠したリンクアグリゲーション。

・balance-tlb
スレーブの負荷に応じて送信スレーブを決定しパケットを送信。
送信のみ負荷分散

・balance-alb
balance-tlbの機能に加え、受信も負荷分散。

・balance-alb
balance-tlbの機能に加え、受信も負荷分散。
```

## まとめ

本業じゃないので雑な感じになってます。

## 参考リンク

https://blog.lorentzca.me/configure-network-bonding-in-centos7-dont-forget-subnetmask/
https://qiita.com/yteraoka/items/e661c2a8c6e7617e64f9
Red Hat Enterprize Linux 8.0 Betaをとりあえずインストールしてみました。

# Red Hat Enterprize Linux 8.0 Betaをとりあえずインストールしてみました。

## Red Hat Enterprize Linux 8.0 Betaをとりあえずインストール
2018年11月15日にRed Hat Enterprize Linux 8.0 Betaが公開されました。
なので、とりあえずVMware Workstation 15 Playerにインストールしてみました。

注意点として、ゲストOSの選択でLinuxを選択し、バージョンを「その他のLinux4.x以降のカーネル」を選択すること。
※64ビットを選択するとディスクを認識しないので必ず、64ビットの記載なしのほうを選択して下さい。(私はこれが分からずハマリました...w)


![RHEL8Beta_001](https://raw.githubusercontent.com/legitwhiz/legitwhiz.github.io/master/technology_memo/images/RHEL8Beta/RHEL8_001.JPG)
後は、RHEL7となんら変わらずにインストールできました。(Beta版では言語で日本語は選択肢が存在しませんでした。
![RHEL8Beta_002](https://raw.githubusercontent.com/legitwhiz/legitwhiz.github.io/master/technology_memo/images/RHEL8Beta/RHEL8_002.JPG)

![RHEL8Beta_003](https://raw.githubusercontent.com/legitwhiz/legitwhiz.github.io/master/technology_memo/images/RHEL8Beta/RHEL8_003.JPG)

![RHEL8Beta_004](https://raw.githubusercontent.com/legitwhiz/legitwhiz.github.io/master/technology_memo/images/RHEL8Beta/RHEL8_004.JPG)



## Red Hat Enterprize Linux 8.0 Betaの気になったポイント

- カーネルがやっと4.18(5.0のrc版が出ているのに!?)

- AnacondaのGUIや、Kickstartコマンドにおいて、Btrfsが利用できなくなります。

- RedHat 7.xでは、ntpとchronyの両方が利用可能でしたが、8.xではchronyのみがサポート。

- yumがDNFベースのYum 4に変更。(サブコマンドが拡張されてます)

- ディスプレイサーバーがXorgからWaylandに変更されます

- iptables、firewalldがnftablesに置き換えられます。(firewalldをやっと覚えたのに・・・。)

- ストレージ暗号化のデフォルトフォーマットがLUKSv2に変更。

- OpenSSL 1.1.1およびTLS 1.3をサポート

- シンプルで一貫したユーザ管理画面「Red Hat Enterprise Linux Web Console」

- API経由での洗練されたデータ管理を実現する新ストレージ管理システム「Stratis」

- IPVLANを経由で仮想マシンに配置されたコンテナとホストを接続することで，スループットの負荷を低減し，レイテンシを最小限に

- ネットワークのパフォーマンスを高速化する新たなTCP/IPスタックとして「Bandwith and Rpund-trip propagation time（BBR）⁠」を採用

- RHELのリポジトリがBaseOSとAppStreamsの２つになりました。

以上、個人的(ITインフラ開発者として)にきになった点をざっと羅列してみました！


なお、RHEL8の変更点が以下のスライドでまとまってました。
https://speakerdeck.com/moriwaka/red-hat-enterprise-linux-8-betafalsemidokoro


Red Hat Enterprise Linux 8の一般提供は2019年中だそうです。

## 最後に

とあえず今日はここまでとします。
nftables、chrony、リポジトリについては、後々調査してレポートしてみたいと思います。
「Red Hat Enterprise Linux Web Console」もどんなものか興味ありますが、何せ情報が少ない。
SASで適当なデータ（テストデータ？）を作るときのプログラムをPythonで。

適当なデータを作る時に，SASではこんな書き方をしてデータを作ってました。

```sas_testdata.sas
data testdata;
  do SUBJID = 10 to 1100 by 10;
    do VISIT = -1 , 1 to 5;
      VALUE = rand("normal",0,1);
      output;
    end;
  end;
run;
```

pythonで書くと，こんな感じになりそうです。

```python:python_testdata.py
import pandas as pd
import numpy as np

SUBJIDs = np.arange(10, 1100 ,10)
VISITs   = np.array([-1,1,2,3,4,5])

testdata = pd.DataFrame([(SUBJID, VISIT, np.random.normal(0,1))
                        for SUBJID in SUBJIDs
                        for VISIT in VISITs]
                        ,columns=['SUBJID', 'VISIT', 'VALUE']
                        )
testdata.head(10)
```


もっと良い方法がありそうではありますが，現状こんな書き方をしています。
Macでコマンドからmicro SDカードの購入後チェック

Raspberry Piにでも使おうかと、
SandiskのmicroSDXCカード海外パッケージモデル SDSQUAR-128G-GN6MAを購入したが、
microSDの並行輸入品には偽物が多いとの話なので本物か気になる。

WindowsではH2testwでチェックするのが一般的のように見えるが、
macでは、[F3を利用するよう](http://oss.digirati.com.br/f3/)な記述があるため、F3を利用して確認してみる。

## 確認環境

* macOS Mojave
* f3 stable 7.1

## 前提

* UHS-Iに対応したカードリーダーを利用し、macにmicroSDを差し込み、利用できるようになっていること
* [Homebrew](https://brew.sh/index_ja)がインストールされていること

## 手順

f3のインストール

```
$ brew install f3
$ f3write -V
F3 Write 7.1
$ f3read -V
F3 Read 7.1
```

マウントポイント(OS標準で差し込んだ場合、/Volumes配下)から対象のSDカードをマウントしているパスを探す

```
$ ls /Volumes/
対象のSDカード名
```

書き込みチェック

```
$ f3write /Volumes/対象のSDカード名/
F3 write 7.1
Copyright (C) 2010 Digirati Internet LTDA.
This is free software; see the source for copying conditions.

Free space: 119.02 GB
Creating file 1.h2w ... OK!
Creating file 2.h2w ... OK!
Creating file 3.h2w ... OK!
〜 省略 〜
Creating file 118.h2w ... OK!
Creating file 119.h2w ... OK!
Creating file 120.h2w ... OK!
Free space: 128.00 KB
Average writing speed: 56.08 MB/s
```

読み込みチェック

```
$ f3read /Volumes/対象のSDカード名/
F3 read 7.1
Copyright (C) 2010 Digirati Internet LTDA.
This is free software; see the source for copying conditions.

                  SECTORS      ok/corrupted/changed/overwritten
Validating file 1.h2w ... 2097152/        0/      0/      0
Validating file 2.h2w ... 2097152/        0/      0/      0
Validating file 3.h2w ... 2097152/        0/      0/      0
〜 省略 〜
Validating file 118.h2w ... 2097152/        0/      0/      0
Validating file 119.h2w ... 2097152/        0/      0/      0
Validating file 120.h2w ...   36864/        0/      0/      0

  Data OK: 119.02 GB (249597952 sectors)
Data LOST: 0.00 Byte (0 sectors)
	       Corrupted: 0.00 Byte (0 sectors)
	Slightly changed: 0.00 Byte (0 sectors)
	     Overwritten: 0.00 Byte (0 sectors)
Average reading speed: 72.16 MB/s
```

書き込みチェック時に作成されたファイルを削除

```
$ rm /Volumes/対象のSDカード名/*.h2w
```

## 結果

だいたい、書き込みチェックに30〜40分、読み込みチェックに10分〜20分程度掛かった。
読み取り72.16 MB/s、書き込み56.08 MB/sと、公称値の半分くらいに見えるし、おそらく本物っぽい。

## 参考

https://github.com/AltraMayor/f3
http://oss.digirati.com.br/f3/
公式チュートリアルよりわかりやすいBottleの説明【@route】

#**公式チュートリアル（英語）よりわかりやすい****Pythonのwebフレームワークbottleの解説**

強気に行きます。
半分忘備録、半分共有したい思いで書いてます。
この記事はいろいろな記事を見て、

「Bottle動いた！」
「これだけで動くなんてすげえ！」

**…知りたいのはそこじゃなくて具体的な使い方なんだよ！！！！**
ってなった人に対する記事です。

私自体がいろいろな言語を触るも仕事では一切使いませんし、何だったら今はpythonはおろかVBAともほとんど縁がない仕事しています。
そんな人間がBottleをつかってwebアプリ？を作ろうともがく記事です。

#対象と筆者のレベル

対象：ちゃんと意味が分かりながら触りたい人向け
著者のレベル（全般）：実務経験なし。基本情報、応用情報合格。
筆者のレベル（コーディング）：読めって言われたら定義とかループとかならわかるけど、それ以上は…といった感じ。
筆者の特徴：学校の先生ができる（しているとはいっていない）ので、教えるほうにスキルポイント振ってます

#bottleのインストール
これはほかの記事を見て頑張ってください。私はpycharmを使っているので、設定からインタープリターを＋し、bottleと検索して使えるようになりました。

#bottleのhello worldと<span>@</span>route の使い方

要約：「<span>@</span>route('/○○/')のurlがリクエストされたら以下を返すよ！」

初投稿（2019/02/26）時点ではこれ以外のことはしっかりマニュアル読まないとわからないレベルでした。

便利なことは
<span>@</span>route('/') ←これが最小単位
<span>@</span>route('/○○/')←色々足していける。urlでよく見る感じ
　・・・・・・・
としておけば、あれとこれとそれの時に実行するという風にできることです。同じことをたくさん書かなくていいのでとても便利で好き。ほかの言語もこういうことできるんでしょうねきっと。

###bottleのhello world

```python:helloworld.py
from bottle import route, run

@route('/')#今回は一番簡単な奴
def hibottle():#関数名なんてなんでもよい
    return "so easy! :)"#ここの文面が出てくる

run(host='localhost',port=8080,debug=True)
```
![190e4dbe791981fb5ec9c96acfce579c.png](https://qiita-image-store.s3.amazonaws.com/0/361263/ca70a522-ecc6-d775-e372-727b67171bb7.png)


実行してから[http://localhost:8080/](http://localhost:8080/)にアクセスするとhello world成功です。

この段階ではファイル名なんてなんでもよいです。run(○○)はローカルサーバーを立てるおまじないなので、特に気にしないで大丈夫です。ここでエラーが出る時はそもそもbottleが入っていないか、ポートが悪いことが多そうです。8080がなんたらっていう記事を探しましょう。

###もうすこし遊びたい奴のhello world
```python:helloworld2.py
from bottle import route, run

@route('/')#今回は一番簡単な奴
@route('/hi/')#hiでも同じものが出る
def hibottle():#関数名なんてなんでもよい
    return "so easy! :)"#ここの文面が出てくる

@route('/hi/im/gosu/')
def imnotgosu():#関数名なんてなんでもよい
    return "support is so easy dude? :)"#わかるひとにはわかる

run(host='localhost',port=8080,debug=True)
```
![route1.jpg](https://qiita-image-store.s3.amazonaws.com/0/361263/e72f2485-3b46-1f3e-82c4-f105b5facc39.jpeg)


実行して出てきたページからurl末尾を　'/'→'/hi/im/gosu/'　にする（[http://localhost:8080/hi/im/gosu/](http://localhost:8080/hi/im/gosu/)にアクセスする）と2つ目に設定した文字が出てきます。また　'/hi/'　も設定してある（こちらは1つ目）のでページが表示されますが、　'/hi/im/'　は設定をしていないので、404 Notfoundでエラーになります。

これ弄っているだけで個人的にはまあまあ楽しいです。

#今後の更新予定
【<spam>@</spam>route】Part.2⇒ワイルドカード（<spam>@</spam>routeのなかにある<spam><</spam>name<spam>></spam>的なあいつ）について
【template】⇒使えたらhtmlだけのページをブラウザに表示することができます。
【static_file】⇒templateと併用するとcssや画像付きのページをブラウザに表示することができます。