OmniAICreator/Qiita-1.07M huggingface dataset:
Raspberry Pi Mouseを始めようかなと検討してみた（その４）

おもしろそうなページ見つけました。
[AIでRCカーを走らせよう](https://www.facebook.com/groups/2249059025382644/)
いずれRCカーでもやりたいと思っているのでウォッチです！
関連リンクです。
[話題のAIで自動運転するドンキーカーを走らせてみた](https://robotstart.info/2019/08/29/donkeycar-maker-tokyo.html)
[ドンキーカーの販売：FaBo Store](https://fabo.store/)
[FaBo DonkeyCar Docs](https://faboplatform.github.io/DonkeyDocs/)

ubuntuのUSBメモリへのインストールですが、使っているiiyamaノートPCのブートメニューが再起動時にしか開けず（F2キー）、USBメモリはやめて仮想環境にインストールすることにしました。

ROSを使う前提でいろいろ調べました。
・[ROSをWindows上の仮想環境で快適に使う方法あるの？](http://dashimaki360.hatenablog.com/entry/2018/01/08/233551)によると、ROSを使うなら､virtualboxよりVMwareのほうが良さそうです。
・[ROS講座02 インストール](https://qiita.com/srs/items/e0e0a9dc3f94c2d3348e)を参考に、Ubuntu16.04とkineticを使うことにします。
・VMware15は[ここ](https://www.vmware.com/products/workstation-player/workstation-player-evaluation.html)からダウンロードしました。
・Ubuntu 16.04 LTSは[ここ](https://www.ubuntulinux.jp/News/ubuntu1604-ja-remix)からダウンロードしました。
・インストールは、[VMwareのROS環境構築](http://peach-pie.blog.jp/archives/12581678.html)を参考にインストール予定です。
　他にも[ROS講座54 VMWare上でROSを使う](https://qiita.com/srs/items/25efd45641c274bb8415)も参考にします。
でも、いろいろやったのですが、細かいところの設定が難しそうです。

なので、古いパソコンにubuntu入れることにしました。
参考は「[Windows 10でUbuntuのインストール用USBメモリを作成](https://www.archlinux.site/2018/03/windows-10ubuntuusb.html)」のHPです。インストールUSBメモリ作成はunetbootinはうまくいかなかったのでrufusを使いました。MBRで作成します。
![setting.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/06e1c4df-6563-748a-7b8f-b4a99e66a8b8.jpeg)

[ラズパイ用のubuntu16.04イメージのダウンロード先](http://cdimage.ubuntu.com/releases/16.04/release/)
[Ubuntuで簡易画像編集するツール「Pinta」](https://www.virment.com/how-to-install-use-flameshot-ubuhttps://www.virment.com/how-to-install-use-flameshot-ubuntu/ntu/)

やっと、Linux環境整いました。次はロボットさわります！

追記：面白い記事見つけました
[【個人開発】Qiitaの人気の記事・ユーザー・書籍を見つけられるWebサービスを作りました](https://qiita.com/KIYS/items/8035763122a790e093e6)
[QT Visualizer](https://qtvisualizer.com/)
Excelは作業机、Access(データベース)は保管倉庫！

# Excelは、大変便利なアプリです

「Excelを使える」ということは「パソコンを使える」ということと同じように理解されています。

しかし、Excelは表計算ソフトから発展したアプリで、データを共有管理するアプリではありません。

そのため、Excelでデータ管理をしようとすると、いつか必ず行き詰ります。

これは、Excelがデータをリレーションできないからです。リレーションとはデータの紐づけのことです。

## データを整理するには、2つの種別に分ける必要がある
データを入力すると、同じデータを何度も繰り返し入力することがよくあります。

何度も同じものを入力するデータをマスターデータの呼びます。

例えば、納品書などのデータの場合、納品書には、日付、得意先名、商品名、数量、金額などのテータが記入されています。

得意先名、商品名、単価など、固定したデータが、マスターデータです。

日付、数量など、納品書ごとに異なるデータをトランザクションデータと呼びます。

データには、この2種類の属性があります。

- 固定したデータ・・・マスター
- 変化するデータ・・・トランザクション

データを管理するには、この2種類のデータを区別して保管する必要があります。

## データを保管倉庫から取り出して、机で作業する。

日常生活でたとえると、保管している倉庫から必要なものを取出して、机で作業するような感覚です。

Excelは作業机のようなアプリです。
手軽に使えるアプリですが、別のExcelファイルに登録されているデータを参照するには、使いにくいアプリです。

作業中のデータは、ほかの人が利用することはできません。つまり、データを共有作業できないのです。


Access(データベース)は、倉庫のようなアプリです。
大変多くのデータを保存でき、条件により必要なデータを抽出する能力に優れています。

ExcelとAccessをうまく連携して使うことにより、データを効率よく管理することができます。

#ExcelとAccessを連携してシステムを作成する
ExcelとAccessを連携したシステムを公開しています。

[<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93227/e732b622-6860-185e-4beb-841d3eeb95fc.png" width="70%">](https://access-cloud.hatenablog.com/entry/cardbox-bari)
https://access-cloud.hatenablog.com/entry/cardbox-bari
Rubyの変数とスコープについて

#はじめに

- 筆者は先週の土曜日(2019/9/14)から、Rubyの学習を始めた修行中の身です。
　間違っている箇所があれば、ご指摘くださいませ。


#変数について
- 変数とは、オブジェクトの入れ物、またはオブジェクトを識別する名札のようなもの
- よく例えられる概念としては「箱」
- 箱に名前（変数名）をつけて、その中に中身（オブジェクト）を入れる

```rb
#サンプルコード

#「word」という名前で変数を定義し、その中に"Hello World"という文字列を代入
word = "Hello World"

#以下の通り、word変数を呼び出すと「Hello World」が表示された！
puts word
=> Hello World
```

#スコープについて
- スコープは変数の有効範囲、範囲を超えるとその変数は使えなくなる
- スコープは変数の種類によって範囲が異なる
- 変数には、以下の種類がある（本当はもっとあるらいしいが省略
 - ローカル変数
 - インスタンス変数
 - クラス変数

##### ローカル変数
- スコープは、定義されたメソッド内でのみ使用可能
- メソッドの壁を超えられない

```rb
#有効範囲の検証
def test
 name = "kazuki"
end

puts test
# =>kazuki

###範囲外 
def test1
 return name
end

puts test1
# エラー発生、nameはtest関数の中でのみ有効
# => test.ruby:6:in `test1': undefined local variable or method `name' for main:Object (NameError)

```

##### インスタンス変数
- 頭に ```@``` をつけることで定義できる
- スコープは、インスタンス内ならどこでも使用可能
- インスタンス毎に値を持てる
- 同じクラス内ならメソッドの壁を超えて参照可能

```rb
#有効範囲の検証
class Test
  def initialize(name)
    @name = name     #インスタンス変数を定義
  end

  def puts_name
    puts @name
  end
end

test1 = Test.new("kazuki")
test2 = Test.new("toshiro")
test1.puts_name
# =>kazui
test2.puts_name
# =>toshiro
```

##### クラス変数
- 頭に ```@@``` をつけることで定義できる
- スコープは、クラス内ならどこでも使用可能
- インスタンス変数はインスタンス毎に値を持てるが、クラス変数はクラス内で1つの値を持つ

```rb
#有効範囲の検証
class Test
  def initialize(name)
    @@name = name     #クラス変数を定義
  end

  def puts_name
    puts @@name
  end
end

test1 = Test.new("kazuki")
test2 = Test.new("toshiro")
test1.puts_name
# =>toshiro
test2.puts_name
# =>toshiro

#解説
# クラス変数はクラス内で1つの値を持つため、
# test2 = Test.new("toshiro")で@@nameにtoshiroを代入したあとは、
# どのインスタンスで呼び出してもtoshiroが表示される。
```
機械学習なんもわからん人がノリと勘でC言語でNNもどきとGA使ってオセロAIを学習させてみた

# 背景
学校でC言語の授業があり、授業の最後に自由になにか作品を作って提出するとのことだったので、オセロAIを作ってついでに学習させてみることにしました。あくまで学校の授業の延長で、ガバガバなところは許してください。

# オセロAIの概要
8×8マス全てに個々に重みを設定し、置ける場所で最も重いマスに石を置くという、至って単純なAIです。各マスの重みをNNで求めます。

# NNの概要
入力層 64個 各マスに置かれている石のデータ
中間層 10個 2層
出力層 64個 各マスの重み

活性化関数、バイアスはよくわからなかったです。

# GAの概要
NNは各ノードを繋ぐシナプスがあり、そこに重みが設定されていて、それを元に次のノードの値を計算します。今回はGAを使って重みを最適化します。交配方法は二点交叉を採用しました。理由は、なんとなくです。

# GAの使い方
親データはExcelのランダム関数で適当に生成したのを二つ用意しました。
基本的にポイント制で、ポイントの降順で順位付けしています。
突然変異の確率、評価の方法、親の選定をいろいろ変えていました。

1 突然変異の確立 遺伝子の要素1つにつき 5 %
  評価方法:勝ち + 1　負け + 0
  次世代の親の選定　上位1～5位と20位からランダムに2体

2 突然変異の確立 3 %
  評価方法:勝ち 30 + とった石 * 2　負け 0
  次世代の親の選定　上位1～5位と20位からランダムに2体

3 突然変異の確立 0.5%
  評価方法:勝ち 30 + とった石 ^ 2　負け 0
  次世代の親の選定　上位1～5位と20位からランダムに2体

4 突然変異の確立 0.5%
  評価方法:勝ち　とった石 * 2 + 四隅一個当たり + 30　負け 0
  次世代の親の選定　上位1～5位と20位からランダムに2体

5 突然変異の確立 0.3%
  評価方法:勝ち　とった石 * 2 + 四隅一個当たり + 30　負け 0
  次世代の親の選定　確定で上位1、2位
　親データとして2を6万世代学習させたデータと4を3万世代学習させたデータを使用

# 学習結果
対戦相手として固定のAIを用意したかったので、[こちら](https://uguisu.skr.jp/othello/5-1.html)のサイトを参考にしました。

上がオセロの盤面、下の数字がNNが求めた各マスの重みです。

方法1
学習世代:1000
![1-1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344267/504ac851-0e22-8b7a-7238-9a6427020908.png)
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344267/96be06ae-73f7-4031-80a6-205157710e84.png)
弱い
角の重みが低いのに、角の周りは高くなっています。
こんなの強いはずがありません。
ただ右端の角は高くなっています。

方法2
学習世代:6万
![2-1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344267/35a74e3a-b6e7-924b-6b3a-3c2f17114189.png)
![2-2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344267/1723f793-02c5-2a02-afb8-42e662567448.png)
あまり1と変わってない印象。
ちなみに先行の時は勝ったけど、後攻では負けた。
わりと運で勝ってる感はある。

方法3
学習世代:3万
![3-1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344267/04c4224f-ee6e-ff76-0f44-2519d0056cac.png)
![3-2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344267/1c76886d-2258-2d16-5b1f-6ee83db4ff1c.png)
相も変わらずといった感じ
石を取った分だけポイントが莫大になるから多く石取ってくれると思ったが、そんなことはなかった
というか自分はそんなにオセロの戦略とか詳しくないので、四隅しか見てません。

方法4
学習世代:3万
![4-1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344267/bf138843-7417-cecd-134e-f012464fc060.png)
![4-2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344267/dfc3d1c6-692f-c9d8-4ead-4b2f2e25fecf.png)
四隅を取ると多くポイントがもらえるようにしてみました。
が、うまくいかなかったです

方法5
学習世代:1万
![5-1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344267/0cee6315-0922-ffb8-b40d-a909fd7f09a6.png)
![5-2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344267/19afbbad-f9ad-dbdd-76fd-fbe13c1a10b8.png)
基本ルールは変えず、親を既存のデータにして、突然変異の確率を下げました。
ですが、あんまり変わんない感じ。


# 結論
今回のやり方ではあまり強くなっている感じではなかったと思います。評価の方法を変えたり、既存のAIの手を教師として教師有り学習をさせたりすれば多少は強くなったかもしれません。

# 最後に
今回のソースコードを[github gist](https://gist.github.com/sakastudio/8faa736b6528bf97e7036fb69cdca914)に載せておきます。自由にダウンロード、改変、再配布などしてくれてOKです。再配布するときにTwitterとかで教えてくれると嬉しかったりします(面倒くさければしなくて大丈夫です)。

# 遺伝子データについて
.cppファイルと同じフォルダに.txtファイルで保存されています。
ファイル名はgeneticX-YYY.txtです。
Xは学習方法の種類です。
YYYは学習した世代数です。
parent1.txt、parent2.txtを作って最初の親としてください。
【powershell】クリップボード監視下でのSet-Clipboardのエラー回避

# 背景
powershell でファイルに出力するまでもないような場合は `Set-Clipboard` でクリップボードに格納して貼り付けるなどしているのですが、クリップボード監視ツールが常駐していると結構な頻度でエラーを吐きます。再度実行すれば問題ないものの何度も赤文字で警告されると心に来るのでエラー回避用のコマンドレットを作成してみました。

# コード
```powershell
function Set-ClipboardForce {
    <#
        .SYNOPSIS
        Set-Clipboard のエラー回避のためのコマンドレット
        クリップボード監視下で頻発するエラーを回避する
        .EXAMPLE
        ls -name | c
    #>
    
    function isClipped ($a) {
        try {
            $a | Set-Clipboard -ErrorAction Stop
            return $true
        }
        catch {
            return $false
        }
    }

    $array = New-Object System.Collections.ArrayList
    foreach ($item in $input) {
        $array.Add($item) > $null
    }

    $i = 0
    while (-not (isClipped $array)) {
        if ($i++ -gt 10) {
            Write-Host "failed to clip!" -ForegroundColor Magenta
            return
        }
        Start-Sleep -Milliseconds 100
        Write-Host "trying to clip..." -ForegroundColor DarkGray
    }
}

# Alias
Set-Alias c Set-ClipboardForce
```

コピーできているか確認するためのサブ関数 `isClipped` を作成して最大10回までリトライさせています。自動変数 `$input` は `ArrayListEnumeratorSimple` ということで一度アクセスすると内容がリセットされるので、いったん配列に格納しなおしてからループに投入しています。
配列への追加は単純に `+=` でもいいのですがコピー内容が増えると遅くなるのでより高速な `System.Collections.ArrayList` を使用しています。
Elixirでバブルソートを書いてみる

```elixir:bubule.exs
defmodule BubbleSort do
  def swap([a]), do: [a]
  def swap([a, b]) when a >= b, do: [b, a]
  def swap([a, b]), do: [a, b]

  def fetch_two_from(list) when length(list) == 1, do: list
  def fetch_two_from(list) do
    [a | [b | _]] = list
    [a, b]
  end

  def sort(list) do
    #IO.inspect list
    1..(length(list) - 1)
      |> Enum.reduce(list, fn _, acc ->
        _sort(acc, [])
      end)
  end

  defp _sort(list, sorted) when length(list) == 0 do
    #IO.inspect sorted
    sorted
  end
  defp _sort(list, sorted) do
    fetch_two_from(list) |> swap() |> _next_sort(list, sorted)
  end

  defp _next_sort(swapped, list, sorted) when length(swapped) <= 1 do
    _sort([], sorted ++ swapped)
  end
  defp _next_sort(swapped, list, sorted) do
    [a | [b | _]] = swapped
    [_ | [_ | tail]] = list

    _sort([b] ++ tail, sorted ++ [a])
  end
end
```

# 記事を投稿しようとおもったきっかけなど
- [英語で学ぶコンピュータ・サイエンスVol.2](http://kidscodeclub.jp/20190922_online/) にボランティアスタッフとして参加するつもりでした
- 台風の接近のため会場での開催は無しとなって、シアトルからのオンライン配信となり、[Zoom](https://zoom.us/jp-jp/meetings.html)で英語授業のほうに参加していました
    - 私は残念ながら英語をあまり聞き取れません
- ソートがテーマのようで、[バブルソート](https://ja.wikipedia.org/wiki/%E3%83%90%E3%83%96%E3%83%AB%E3%82%BD%E3%83%BC%E3%83%88)を解説されていました
- 私がこれをはたしてプログラミングできるのだろうかとふと思いまして、おおよそ20年ぶりくらいにバブルソートをひょんなことから出会った[Elixir](https://elixir-lang.org/)で書いてみることにした次第です
- [Elixir](https://elixir-lang.org/)にはすでに便利なものが用意されていますのでそれを使えばよいとおもいます
    - [Enum.sort/1](https://hexdocs.pm/elixir/Enum.html#sort/1)
    - [Enum.sort/2](https://hexdocs.pm/elixir/Enum.html#sort/1)
- [Enum.reduce](https://hexdocs.pm/elixir/Enum.html#reduce/3)を使っているところはあれこれ悩んでこういう形になりましたがもっとよいやり方があるのではないかとおもっています
    - 必ず(要素数 - 1)回処理することになっていますが、すでにソート済であればそこで打ち切るといった処理を書けていません
    - 一応動きはしますが、あんまりいいコード例ではないとおもいます :sob: 
- `[head | tail] = [1, 2, 3]` みたいな感じのところはうまくなった気がします
- 私がこれを書いている間に子どもたちは[バイナリサーチ](https://ja.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%8E%A2%E7%B4%A2)を学んでいました……
- 時代はかわりました
    - 私が子供のころにはコンピューターと言えば、[ファミリーコンピュータ](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%83%9F%E3%83%AA%E3%83%BC%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF)だけでした
    - 買ってもらうために、あれこれ、親に説得を試みたことを覚えています
- これからは英語は当然できる、プログラミングも堪能な若い人がどんどん増えてくるとおもいますので日々精進して参りたいとおもう次第でございます
IDA Proで関数の配列を見つけた後に行うべきこと

#概要
IDA Pro上で関数ポインタが連続する領域（関数の配列）を見つけた後には、構造体と**プロトタイプ宣言**を利用。
すると、各関数呼び出し時に引数が自動で識別されるようになり、解析がはかどる。

関数がWin32 APIの場合には[FireEyeのflare-ida](https://www.fireeye.com/blog/threat-research/2013/06/applying-function-types-structure-fields-ida.html)の**StructTyper**を利用することでプロトタイプ宣言の自動化も可能。
![synbolic-constant.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400927/267e7056-8872-471f-3cf4-82850d787152.png)

#設定フロー
1. 関数の配列から、配列要素の関数呼び出しを見つける
2. 構造体を定義して配列要素の各関数を定義
3. 各関数にプロトタイプ宣言を定義【**ココをStructTyperで自動化**】
4. 引数を定数表示

##関数の配列から、配列要素の関数呼び出しを見つける
今回の例では、スタック上に積まれた関数の配列へのポインタを**call**している部分を見つけたところから開始します。
![raw-assembly.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400927/1bdfc38d-bbbb-fd55-cff1-8109dfd1ba98.png)


##構造体を定義して配列要素の各関数を定義
1) Structureタブで右クリックし、Add struct typeを選択
![add-struct.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400927/df75c2bc-9283-f122-38f1-84231edd9d48.png)
2) 構造体名を入力しOKで構造体作成
3) 構造体名を右クリックし、Data選択
4) 追加された要素上でd押下により要素サイズをdd(4 bytes)とする
　　※ 本説明中では32bitのプログラムを解析しているためポインタサイズは4 bytesであるが、
　　　64bitのプログラムを解析する場合には要素サイズを 8 bytesとすること
![data.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400927/b365b65f-fbab-26ea-1bd9-af78aaa31fde.png)
5) 配列の要素数分だけ(3)~(4)を繰り返す
6) 各要素を右クリックし、Renameを選択で関数名を付与
![prepared-structure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400927/5c9ebad7-5673-5a9b-e59e-69dee064e4ae.png)
7) 配列要素の関数呼び出し箇所でオペランドを右クリック(※)し、Structure offset->作成した構造体を選択
　　※ 本説明中では**call  dword ptr [eax+4]**の**eax**を右クリック
![structure-offset.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400927/051941d2-254f-6337-7601-8cfde342b406.png)

##各関数にプロトタイプ宣言を定義【**ココをStructTyperで自動化**】
###手動でのプロトロタイプ宣言方法
Structureタブで(6)で付与した関数名を右クリックし、Set type選択、[Microsoftのドキュメント](https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc)で確認した関数定義を設定
![set-type.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400927/49ba3a36-f1ca-c9c4-befd-d3e4f87843b1.png)

###自動でのプロトタイプ宣言方法(StructTyper利用)
1) Github上にて[fireeye/flare-ida](https://github.com/fireeye/flare-ida)をダウンロード
2) StrutTyperをIDA proへインストール
>plugins
>To install, copy the contents of the plugins directory in this repository to your %PROGRAMFILES%\IDA\plugins folder.

>python
>The python directory here can be copied to your %PROGRAMFILES%\IDA\python folder, or you can modify your PYTHONPATH environment variable to include the directory.

3) IDA Pro上部メニューのEdit > Plugins > StructTyperにて作成した構造体を選択

![structtyper.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400927/7ac8a463-3fd6-ac67-c91a-7e4dbf59f47e.png)
「手動でのプロトロタイプ宣言方法」と同様の結果が得られる。

####プロトタイプ宣言実施後
![after-structtyper.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400927/f2cfa194-992e-1dc5-3b9d-4a935497ece5.png)

####引数を定数表示
引数の数値を右クリックし、Symbolic constant選択、適切な定数を設定
![synbolic-constant.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400927/267e7056-8872-471f-3cf4-82850d787152.png)

##最後に
今後も、バイナリ解析用のテクニックを自分のメモとして残していくつもりです。
間違いや改善点がありましたら、ご一報いただけるとありがたいです。
man コマンドを日本語化する

# man コマンドを日本語化する

man はコマンドの詳細な説明を表示するコマンドです。
日本語化することで素早くコマンドの使い方を理解することができます。

```sh
$ brew install groff
$ sudo vi /etc/man.conf
-------------------------
# 96行目 行頭に「#」を付けてコメントアウト
JNROFF  /usr/bin/groff -Tnippon -mandocj -c
# ↓↓↓↓↓ 最新版に変更
JNROFF  /usr/local/bin/groff -Dutf8 -Tutf8 -mandoc -mja -E

# 106行目 行頭に「#」を付けてコメントアウト
PAGER  /usr/bin/less -is
# ↓↓↓↓↓↓ 日本語表示に対応
PAGER  /usr/bin/less -isr

# 107行目 行頭に「#」を付けてコメントアウト
BROWSER  /usr/bin/less -is
# ↓↓↓↓↓↓ 日本語表示に対応
BROWSER /usr/bin/less -isr
--------------------------
```

```sh
# man のドキュメントをダウンロード
$ curl -O http://linuxjm.osdn.jp/man-pages-ja-20190915.tar.gz
# 最新版は以下からダウンロード
# http://linuxjm.osdn.jp/download.html

$ tar xfz man-pages-ja-20190915.tar.gz
$ cd man-pages-ja-20190915/
$ make config

--------------------------
1. Install directory   [/usr/share/man/ja_JP.UTF-8] ?:
  → インストール先は /usr/local/share/man/ja_JP.UTF-8 と入力
2. compress manual with..
  → 圧縮形式は 0 (none) とする
3.   uname of page owner [root] ?:
  → ユーザ名は root と入力
4. group of page owner [root] ?:
  → グループ名は wheel と入力
5. All OK? (Yes, [C]ontinue / No, [R]eselect) :
  →  c と入力
6. [INSTALL PACKAGE SELECTION]
   (just Return if you accept default choice)
  → デフォルトでOK、100回以上 Enter を押して進める
7. All OK? (Yes, [C]ontinue / No, [R]eselect) :
  → c と入力
8. [RESOLVE CONFLICTS]
   (just Return if you accept item 0)
  → デフォルトのままで良いので、180回以上 Enter を押してそのまま進める
9. All OK? (Yes, [C]ontinue / No, [R]eselect) :
  → c と入力

creating installation script...done
now you can "make install" as user root.

$ sudo make install
```

### ※ 日本語化されない場合は以下の通りパスを追加する
```sh
$ echo 'export MANPATH=/usr/local/share/man/ja_JP.UTF-8:$(manpath)' >> ~/.zprofile
```
Chef ドットインストール


## 用語

- workstation
  - cookbook
  - knife
  - node（サーバー）
 

- chef server
- chef client




## workstation

- knife-solo
- knife-configure
- install 

※最高
https://qiita.com/makky_tyuyan/items/007c0c7a4abf6af37dbf


https://www.chef.sh/
Bitnami redmine を Ubuntu にインストールし、付いてくる git を使えるようにする

簡単にできるかと思ったら、結構嵌ってしまったので備忘録としてメモしたいと思います。

# インストール先の環境

* OS は Ubuntu 18.04.3。
* イメージは bitnami-redmine-4.0.4-5-linux-x64-installer.run
* さくら VPS 上に構築。
* 先にインストールした apache があるため、ポートは 10080, 10443 を使う。
* git は bitnami に付いてくるものを使う。

イメージを落としてくるところまでは出来ているものとします。

# Bitnami redmine のインストール

デフォルトとの差は、subversion を No、メール送信を No、Git を Yes に設定したくらい。
インストールが長いが(特にゲージが100%に達してからが)、我慢して待つ。
途中でredmine/mariaDB のユーザ/パスワードの設定を聞かれるので、適切な値を入れる。
パスワードは英文字と数字しか入れられないようです。（ハイフンは入るかも）

インストールが終了すると http://127.0.0.1:10080/ にアクセスするように求められるので、ssh トンネルか何かを作ってアクセスする。
(と言うものの、phpmyadmin のようにローカルアドレスをチェックしていない模様。)
さくら VPS の場合はデフォルトでファイアウォールがブロックしているので、su になって

<pre>
ufw allow to [Global IP] port 10443
</pre>

でパケットの透過を許可するようにする。

# WebDAV の設定
CGI で設定するのが本当はよいらしいのですが、今回は WebDAV を使います。
apache2 以下の conf/bitnami/bitnami.conf に以下を追加。

<pre>
Alias /git /opt/redmine-4.0.4-5/git/repo
DavLockDB "/opt/redmine-4.0.4-5/apache2/var/git/DavLock"

&lt;Location /git&gt;
  DAV on

  AuthType Basic
  AuthName "git repository"
  AuthUserFile "/opt/redmine-4.0.4-5/git/gitpasswd"
  Require valid-user
&lt;/Location&gt;
</pre>

DavLock ファイルを touch し、ユーザを daemon に変更します。
gitpasswd に htpasswd を使ってパスワードを追加します。
（bitnami の apache2/bin/ 以下にあります。）

/opt/redmine-4.0.4-5/apps/redmine/htdocs/config/configuration.yml ファイルに

<pre?
scm_git_command: /opt/redmine-4.0.4-5/git/bin/git
</pre>

を設定します。

# Git の設定
一番嵌ったところです。
まず、Git 用のレポジトリを作成し、グループ、ユーザを daemon に変更しておきます。
今回は /opt/redmine-4.0.4-5/git/repo というディレクトリを作成しました。
例として sample というプロジェクトを作成することにすると、

<pre>
mkdir sample.git
cd sample.git
git --bare init --shared=true
git --bare update-server-info
cd ..
chown -R daemon:daemon sample.git
</pre>

として初期レポジトリを作成します。4行目と最後の行が重要。

ローカルマシンに移り、

<pre>
export GIT_SSL_NO_VERIFY=1
</pre>

とした後、git clone https://&lt;Global IP&gt;:10443/git/sample.git を実行してレポジトリが取れることを確認します。取れない時はエラーログが出ているので確認します。

sample.git に中に入り、README.txt を作ってみます。

<pre>
cd sample.git
touch README.txt
git add README.txt
git commit -m 'readme'
</pre>

.git の下にある config の url に htpasswd で追加したユーザ名を追加します。仮に myname としたとすると、

<pre>
[remote "origin"]
        url = https://myname@sample.com:10443/git/sample.git/
</pre>

のようにサーバ名の前にユーザ名を追加します。
git push が実行できることを確認します。ブランチが指定されていないと怒られたときは git push origin master とします。

# Redmine のプロジェクトを追加
最後に管理権限を持ったユーザで Redmine にログインし、「管理」タブを選択してプロジェクトを作成します。リポジトリをどうするか聞かれるので、Git を選択し、上で作ったディレクトリ名（例の場合は /opt/redmine-4.0.4-5/git/repo/sample.git）を指定します。保存後、Redmine の「リポジトリ」タグを選択します。ここで404エラーが出てくる場合はパスを確認します。

#おまけ
付属する bncert-tool を使うと、Let's Encrypt で証明書を生成することが可能ですが、ポート番号が 80, 443 固定であったため、利用をあきらめ、さくらで取ったサーバ証明書を流用しました。
apache2/conf 以下の server.key, server.crt を入れ替えれば動作します。
GASのスクリプトエディタでファイル分割したgsファイルを読み込む試行錯誤

# 概要
GoogleAppsScriptのスクリプトエディタでコードを書いたときに、ファイル分割してコード管理したくなった際に、定義した関数をスクリプトエディタで使えるようにするための手順を試行錯誤したのでまとめてみます。

要するに以下のように２つ以上の.gsファイルを作って、それぞれロードして定義した関数を使えるようにしたいということです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24897/2fa4a6d3-3ada-b19d-73ef-3067afde5bb0.png)

# 発生した問題
他の記事で、定義した関数をそのまま利用すれば良いだけとあったので、スクリプトエディタでmain.gsを実行（main.gsは内部でparser.gsで定義した関数を利用しています）。
実行開始後、処理が全く終わらず。デバッグすると、別ファイル（parser.gs）に定義済みのはずの関数で処理が止まっていた。

# 試したこと
## トリガーから実行する
* 実行をスクリプトエディタ上で行っていたのを、トリガーを作成してSpreadSheet起動時にスクリプトが動作するように設定したところ、正常に別ファイル定義の関数も読み込まれた。
* SpreadSheetからだと関連付けてあるプロジェクトの全てのスクリプトが読み込まれる（？）様子。

## プロジェクト自体をライブラリとして利用する
自分のプロジェクトをライブラリとして定義し、自分のプロジェクトに関連付けることでプロジェクト全体のロードがスクリプトエディタで書いたコード実行前に読み込まれる様子

1. メニューの ファイル＞版を管理 から「新しいバージョンを保存」でバージョン番号を発行しておく（ライブラリ追加の際に必要なため）
2. メニューの ファイル＞プロジェクトのプロパティ から「情報」タブの「プロジェクトキー」を取得します
3. メニューの リソース＞ライブラリ... から「ライブラリを追加」テキストボックスに先ほど取得したプロジェクトキーを入れて保存します
4. このとき、以下のようにライブラリが追加されますので、事前に発行したバージョン番号をプルダウンで選択して保存します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24897/f130140f-1c68-5600-a8ff-ddd18a7e5c41.png)

以上でmainファイルから別ファイルに記述した関数を呼び出せるようになります。
ライブラリとして正しく利用する意味では、汎用的な処理を分割して別プロジェクトにしてしまい、本来の意味でのライブラリとして共通で利用するのが良いように思いました。

基本Googleの各種サービスとプロジェクトを紐付けて使うものなのでこのような仕様なのでしょうが、もっと簡単にできる方法あったらぜひ教えてください...。
余談ですが jsの alert() にあたる Browser.msgBox もSpreadSheet側からでないと処理が止まって動きませんでした（当然と言えば当然ですが...）

とは言えGASは便利なので、もう少しちゃんと調べてUPDATEしていきたいと思います。

# 参考
https://qiita.com/shirakiya/items/5e51e352faef6f7db9be
https://itami.info/tech/memorandum/googleappsscriptincludfunctions.html
bash or zshでnpmの補完設定

# TL;DR
bashの場合：
`npm completion >> ~/.bashrc`
zshの場合：
`npm completion >> ~/.zshrc`

# やりたかったこと
コマンドラインでnpm insくらいでTabを押すとnpm installと出てきて欲しい

# 環境
```bash
$sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.6
BuildVersion:	18G95
```

# コマンド実行結果。.bashrcに下記が追記される
```shell-session:.bashrc
###-begin-npm-completion-###
#
# npm command completion script
#
# Installation: npm completion >> ~/.bashrc  (or ~/.zshrc)
# Or, maybe: npm completion > /usr/local/etc/bash_completion.d/npm
#

if type complete &>/dev/null; then
  _npm_completion () {
    local words cword
    if type _get_comp_words_by_ref &>/dev/null; then
      _get_comp_words_by_ref -n = -n @ -n : -w words -i cword
    else
      cword="$COMP_CWORD"
      words=("${COMP_WORDS[@]}")
    fi

    local si="$IFS"
    IFS=$'\n' COMPREPLY=($(COMP_CWORD="$cword" \
                           COMP_LINE="$COMP_LINE" \
                           COMP_POINT="$COMP_POINT" \
                           npm completion -- "${words[@]}" \
                           2>/dev/null)) || return $?
    IFS="$si"
    if type __ltrim_colon_completions &>/dev/null; then
      __ltrim_colon_completions "${words[cword]}"
    fi
  }
  complete -o default -F _npm_completion npm
elif type compdef &>/dev/null; then
  _npm_completion() {
    local si=$IFS
    compadd -- $(COMP_CWORD=$((CURRENT-1)) \
                 COMP_LINE=$BUFFER \
                 COMP_POINT=0 \
                 npm completion -- "${words[@]}" \
                 2>/dev/null)
    IFS=$si
  }
  compdef _npm_completion npm
elif type compctl &>/dev/null; then
  _npm_completion () {
    local cword line point words si
    read -Ac words
    read -cn cword
    let cword-=1
    read -l line
    read -ln point
    si="$IFS"
    IFS=$'\n' reply=($(COMP_CWORD="$cword" \
                       COMP_LINE="$line" \
                       COMP_POINT="$point" \
                       npm completion -- "${words[@]}" \
                       2>/dev/null)) || return $?
    IFS="$si"
  }
  compctl -K _npm_completion npm
fi
###-end-npm-completion-###
```

`npm completion >> ~/.bashrc`と打つことでbashrcに良い感じに補完用スクリプトを追加してくれるっぽい。

# 参考
https://docs.npmjs.com/cli/completion.html
暗黙的アンラップってなんだろう

アプリ開発をしているとオプショナルバインディングとかオプショナルという言葉をよく聞くと思います。今回はそのアンラップ方法の一つで名前だけではよくわからない「暗黙的アンラップ（Implicity Unwrapped Optional）」について簡単にまとめたいと思います。

#アンラップの種類のおさらい
nilのアンラップは暗黙的アンラップを除いて3つあります。ここでは一つずつ簡単に説明したいと思います。

大前提として以下のように定義したオプショナル型の整数型（int）をアンラップしたいと思います。

```swift
var number: Int?
number = 1
``` 

###1, 強制アンラップ(Forced unwrapping)
簡単に言うと、オプショナルを使いたいときに後ろに!をつけます。

```swift
print(number!)
```

このアンラップの方法を使うとオプショナルがnilの場合クラッシュします。

###2, ??演算子(Nil Coalescing)
簡単に言うと、オプショナルを使いたいときに後ろに「?? 初期値」をつけます。

```swift
print(number ?? 0)
```

このアンラップの方法を使うとオプショナルがnilの場合は代わりに??の後に書いている初期値（今回の場合は0)を使います。

###2, if letでアンラップ
以下のように書きます。

```swift
if let n = number {
   //numberがnilではないときにnにnumberが代入される。
   print(n)
} else {
   //numberがnilのとき
}
```
これはnumberをnに代入できた時（すなわちnumberがnilではないとき）にifのカッコ内を実行するというコード。
**利点はnilだった時の挙動を決めることができる。**

###3, guard letでアンラップ

```swift
guard let n = number else { return }
print (number)
```
正直if letと違いはないのですがこれを使うと**guard文以降でもアンラップした値を使えます。**

#暗黙的アンラップとは？
さてここで本題の暗黙的アンラップについてです。暗黙的アンラップは変数を定義するところから違います。定義は以下のようにします。`?`の代わりに`!`をつけて定義します。

```swift
var number: Int! //初期値はnil
number = 1
```

これを使うと実際に値を使うときに`!`や`if let`などのアンラップをする必要がなくなります。

```swift
print(number)
```

一見すごく便利に見えますが一つ注意するべきことがあります。**これは中身がnilの場合はクラッシュしてしまします。**簡単に言うと暗黙的アンラップを使うと、使うたびに強制アンラップされます。

###暗黙的アンラップの利点
一見、強制アンラップと一緒でoptional型かわかりにくくしてしまい不便に見える暗黙的アンラップですがもちろん利点もあります。
これを使うと、初期値はないが後から必ず値を入れる保証があるものに使うと効果を発揮します。（例えば、ユーザーが前のviewで入力した値など）
所詮`!`をつけるだけと思うかもしれませんが、つけ忘れる心配が無くなるのはかなり大きな利点だと思います。

#まとめ
アンラップの方法はいくつかありますがそれぞれ特徴があるのでその特徴によって使うオプショナルバインディングの種類を変えるとより質の高いコードを書けるのではないでしょうか？この記事が皆さんのコーディングライフを豊かにするきっかけになっていたら嬉しいです。
LINE messaging APIで自分からゴミの日を教えてもらう

#やったこと

+ 勉強がてら、何かテキストなりスタンプなりを送ると、「次の日」は何のゴミの日かを教えてくれるLINE Botを作りました。
+ 定期的にお知らせしてくれるのではなく、自分からBotに問いかけ、ゴミの日を教えてもらう仕様です（第n●曜日にも対応）。
+ 同居人などにBotのアカウントを教えて友達になってもらえば、その人もBotが使えます。

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250449/62eebfc6-2d64-ed3c-67e5-9fbc66e0fb3f.jpeg' width=50%>

#中身

1.  LINE messaging APIにスマフォからメッセージを送る
+ APIからWebhook用URL（GASのアプリケーションのURL）にPOSTリクエストがいく
+ このリクエストをきっかけに、GASアプリケーションがAPIに応答メッセージを返す
+ スマフォに、このPOSTリクエストに含まれるテキストメッセージが届く


```javascript
// LINE developersのメッセージ送受信設定に記載のアクセストークン
var ACCESS_TOKEN = 'XXXXXXXXXXXXXXXXX';

function doPost(e) {
  // WebHookで受信した応答用Token
  var replyToken = JSON.parse(e.postData.contents).events[0].replyToken;
  // ユーザーのメッセージを取得。今回は特に使わない。
  //var userMessage = JSON.parse(e.postData.contents).events[0].message.text;
  // 応答メッセージ用のAPI URL
  var url = 'https://api.line.me/v2/bot/message/reply';

  UrlFetchApp.fetch(url, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + ACCESS_TOKEN,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': replyToken,
      'messages': [{
        'type': 'text',
        'text': returnGomiday(),
      }],
    }),
    });
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}

//この関数で、↑のpayload・message・textに何のゴミの日かを入れる。
function returnGomiday(){
  var tomorrow = new Date();
  tomorrow.setDate(tomorrow.getDate() + 1);
  var i_week = tomorrow.getDay();//明日の曜日のインデックス
  var n = cntDayofweek(tomorrow);//明日が何回めの●曜日なのか
  
  if (i_week == 1){
    return getMMddweek(tomorrow,i_week)+'は資源ごみ';
  }else if((i_week == 2) || (i_week == 4) ||(i_week == 6)){
    return getMMddweek(tomorrow,i_week)+'は可燃ごみ';
  }else if((i_week == 3)&&(n ==2)){
    return getMMddweek(tomorrow,i_week)+'は不燃ごみ';
  }else if((i_week == 3)&&(n ==4)){
    return getMMddweek(tomorrow,i_week)+ 'は不燃ごみ';
  }
  else{
    return getMMddweek(tomorrow,i_week)+'は該当なし';
  }
}

//日付と曜日のインデックスを渡すと、"09月２０日（金）"のようなテキストを返す
function getMMddweek(tomorrow,i_week){
  var arry = ['日','月','火','水','木','金','土'];
  var time = Utilities.formatDate(tomorrow,'Asia/Tokyo','MM月dd日');
  var week = '('+arry[i_week]+')';
  return time + week
}

//日付を入力すると、月初から何回めの●曜日なのか返す。
function cntDayofweek(date){
  var first_date = new Date();
  first_date.setDate(1);//月初設定
  var diff = Math.floor((date-first_date)/86400000);
  return diff/7+1;
}

```
# 説明
###doPost(e)
LINEからPOSTリクエストがあった時に、関数の中身が実行される。'payload'の中身に書いた'text'がユーザーへの応答メッセージになる。

###returnGomiday()
上記'text'に記載。「次の日」の曜日に応じてなんのごみの日か文字列で返す。居住地に応じて書き換え。

###cntDayofweek(date)
次の日の日付と月初との日差を、7で割り、1を足すと第n●曜日がでます。多分。

###LINE messaging APIとGASのWebアプリケーション公開方法
下記参考を参照。注意点としては、GASを修正した場合、「公開」→「ウェブアプリケーションとして導入」→「プロジェクトバージョン」をnewにして新たなURLを生成し、これをLINE messaging APIのWebhook用URLに記載しなおす必要がある。

# 参考
下の2記事を参考にさせていただきました。ありがとうございます。一つめの記事からはアイディアを、２つめからは関数doPost(e)の中身を参考にさせていただきました。

+ [ゴミの日も記念日も何でも通知してくれるLINE BotをGASで作ってみよう](https://qiita.com/commojun/items/363b8b9f41b78d00ca3c)
+ [Google Apps ScriptでLINE BOTつくったら30分で動かせた件](https://qiita.com/hakshu/items/55c2584cf82718f47464)
webpack-dev-serverの導入、設定

##webpack-dev-serverを導入して、開発を効率的にしよう

以下、記事の続きになっています。
自分の環境に読み替えるのが面倒な方は、以下記事も参考に読んでみてください。
[webpack事始め](https://qiita.com/10mi8o/items/d9449c12b94ebeae1678)


##webpack-dev-serverを導入するメリット

webpack-dev-serverはwebpackを使用したフロントエンド開発時に利用できる開発環境向けのwebサーバーです。

webpackのバンドル対象のファイルをバンドルする度にwebpackコマンド打ち込むのは面倒。ブラウザの立ち上げ、レンダリング結果の確認も効率的にしたい。

上記、開発時にちょっと不便な点を解決するために`webpack-dev-server`を使用します。

開発時に便利なパッケージなので試してみましょう。
https://github.com/webpack/webpack-dev-server


##導入してみる
インストールします。

```console
//最新のバージョンを確認してみる
$npm info webpack-dev-server
//インストール
$npm install --save-dev webpack-dev-server@3.8.0 
```

起動します。

```console
 $npx webpack-dev-server
```

<img width="801" alt="スクリーンショット 2019-09-15 10.52.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33632/33d7234f-ad23-ce2c-a93b-7dd482e9afc3.png">

上記コマンドでスクショにあるようなパスが表示されるので、アクセスしてみましょう。(パスは適宜、読み替えてください)

```
http://localhost:8081/
```
すると、このような画面が表示されます。
<img width="913" alt="スクリーンショット 2019-09-22 10.58.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33632/842f1f77-a7b4-466e-df37-6f2760e634c8.png">
ページにアクセスしたい場合は、パスを指定しましょう。

```
http://localhost:8081/dist/
```


パス指定して、ページにアクセスするのも面倒です。次に、設定ファイルを編集して、もう少し使い勝手の良い形に改善しましょう。

一旦、`ctrl + C`で`webpack-dev-server`は落としておきましょう。

##ドキュメントルートを設定する
では、`webpack-dev-server`起動時、ブラウザを立ち上げ、ドキュメントルートにアクセスする設定を書いてみましょう。

設定は`webpack.config.js`で行います。

```js:webpack.config.js
// 出力は絶対pathで指定しなければいけない為、node.jsのpathモジュールを使用する
const path = require('path');
const outputPath = path.resolve(__dirname, 'dist');

module.exports = {
    // バンドルするファイルを指定
    entry: './src/index.js',
    output: {
        // バンドルしてmain.jsとして出力
        filename: 'main.js',
        path: outputPath
    },
    // webpack-dev-serverを立ち上げた時のドキュメントルートを設定
    // ここではdistディレクトリのindex.htmlにアクセスするよう設定してます
    devServer: {
        contentBase: outputPath
    }
}
```

以下、コマンドを実行してみましょう。`--openオプション`を追加する事で同時にブラウザを立ち上げる事ができます。

コマンド実行と同時に、ブラウザが立ち上がり、ドキュメントルートに設定したページが表示されているはずです。

```console
$npx webpack-dev-server --open
```

また、webpack-dev-serverは、バンドル対象ファイルの動的な更新に追従してwebpackによるバンドルがリアルタイムに実行してくれます。

試しに`utilities.js`を変更してみてください。

```js:utilities.js
// ある数字を引数として与えるとその数字の２乗の数を返す
export function double(num) {
    return num**2;
}

// 変更してみる
export const NAME = 'バンドルされてる？';
```
ブラウザでlogを確認するとこのようにリアルタイムで更新された事を確認できたはずです。
<img width="259" alt="スクリーンショット 2019-09-22 11.27.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33632/daf8e0dc-687d-fc46-40bd-270dceaf0055.png">

このように、webpack-dev-serverが、ファイルを監視してくれてる事で更新を検知して、webpackによるモジュールバンドルを行ってくれます。

webpack-dev-serverはアプリケーション開発時に便利なツールかと思います。是非、試してみてください。

[webpack dev server 公式Doc](https://github.com/webpack/docs/wiki/webpack-dev-server)
Linux基礎(YUMツール/APTツール)

#YUMコマンド
YUM(Yellowdog Updater Modified)ツールは、パッケージ間の依存関係を解決しながらダウンロード、インストール、アップデート、アンインストールすることができるツール。
YUMの設定は「/etc/yum.conf」ファイルに記述する必要がある。パッケージのリポジトリ情報を設定するためには「/etc/yum.repos.d」ディレクトリにダウンロードサイトのURLを記載したファイルを格納する必要がある。

|オプション|説明|
|---|---|
|-y|全ての質問にyesと回答する|

|サブコマンド|説明|
|---|---|
|check-update|アップデート対象となるパッケージ一覧を表示|
|update パッケージ名|指定したパッケージのアップデート|
|install パッケージ名|指定したパッケージのインストール|
|remove パッケージ名|指定したパッケージのアンインストール|
|info パッケージ名|指定したパッケージの情報の表示|
|list|全パッケージ情報をリスト表示|
|repolist|リポジトリ一覧の表示|
|search キーワード|パッケージ情報をキーワードで検索|
|search all キーワード|パッケージ情報をキーワードで検索(パッケージ名、説明文)|
|grouplist|パッケージグループのリスト表示|
|groupinstall グループ|指定したグループのパッケージをインストール|

```shell
#パッケージのインストール
$ yum install nmap

#パッケージのアンインストール
$ yum remove nmap

#アップデート可能なパッケージの表示
$ yum check-update

# インストール済みの全パッケージを最新版にアップデート
$ yum update

# インストール済みのパッケージ一覧の表示
$ yum list

# パッケージ情報の表示
$ yum info nmap

# 指定したキーワードのパッケージ検索
$ yum search nmap
```

#aptについては後から記載予定...
※気が向いたら
自作Webフォームからkintoneへデータを登録する方法

# はじめに

ハッカソンでkintoneを使う際、よく`自作Webサイトから登録` というシナリオを耳にします。
クリックイベントで`axios`等を用いてデータをkintoneへ投げればいけそうなのですが、実は直接はやりとりができません。

> ▼ セキュアコーディング ガイドライン 【クロスドメイン制約】
https://developer.cybozu.io/hc/ja/articles/201919400#step6

> クロスドメイン制約のため、XHR(XMLHttpRequest) を使用したcybozu.comと外部サイトとの通信はできません。Access-Control-Allow-Origin ヘッダーは付与できません。

そのため、上記のシナリオを実現させるためには、<font color="red">**サーバを経由**</font> しないといけないわけです。

# サンプルコード

- html

Webフォームは普通に作ればOKです。リクエストの送信機能には `axios` を利用しています。

```html:index.html
<body>
  <label>テキスト</label>
  <input id="text" type="text">
  <div>
    <button id="submit">送信</button>
  </div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.js"></script>
  <script src="script.js"></script>
</body>
```

- script.js

```javascript:script.js
(() => {
  'use strict';

  document.getElementById('submit').onclick = () => {
    const params = {
      text: document.getElementById('text').value
    };
    axios.post("{Server's URL}", params);
  };
})();
```

- サーバ （Node.js）

```javascript:handler.js
'use strict';

module.exports.main = async event => {
  console.log(event);
  return {
    statusCode: 200,
    headers: {
      'Access-Control-Allow-Origin': '*'
    },
    body: JSON.stringify({
      message: '成功！'
    }),
  };
};
```

サーバに AWS Lambda を利用する場合、[Serverless Framework](https://serverless.com/) を使うととても楽です！！

```bash
# create dir and move
$ mkdir my_project;cd $_

# create aws lambda
sls create -t aws-nodejs

# ~
# edit serverless.yml and handler.js
# ~

# deploy
$ sls deploy
```

# おわりに

自作Webサイトからkintoneへデータを登録する場合は、こちらのやり方を参考にぜひお試しください〜
それでは！≧(+･` ཀ･´)≦
[python]gifの画像を合成してみた

Gifを一枚づつに分解すると、２枚目以降は差分しか保存されていないので、
「なら合成してしまおう」とpython3で合成するプログラムを書いてみました。

gif画像の分解に[ONOさんのブログ](https://www.tech-tech.xyz/gif-divide.html)のコード(opencv版)を使いました。

```python:gif_combine.py
import os
import cv2

img0 = cv2.imread("screen_caps\\0.png",-1)

print(img.shape)

size = img.shape[:2]

#透過箇所（緑）か
def isGreen(color):
    if color[0]==0 and color[1]==255 and color[2]==0 and color[3]==255:
        return True
    return False


if not os.path.exists("Combine"):
    os.mkdir("combine")

for i in range(308):
    img = cv2.imread("screen_caps\\"+str(i)+".png",-1)
    for x in range(size[0]):
        for y in range(size[1]):
            mask = img[x,y,:]
            if not isGreen(mask):
                img0[x,y,:] = mask 
    print("save num:"+str(i))
    print(cv2.imwrite("combine\\gif"+str(i)+".png",img0))
```

約500*400のサイズでもそれなりに時間がかかったので、最適化のご指南いただけると幸いです。
TypeScript メモ

#基本的なデータ型と宣言方法

```typescript
var a: string = ''
var b: number = 10
var c: boolean = false
var d1: string[] = ['hello', 'world', 'something']
var d2: number[] = [1, 3, 4]
var e: any //どんなデータ型でも格納可能
```


#関数の書き方

```typescript
//返り値がある場合
function add(a: number, b: number): number{
  return a + b
}

//返り値がない場合
function add(a: number, b: number): void{
  //処理内容記載...
}

```

通常の関数宣言だけでなく、式のように関数を書くことができる。

```typescript
// 通常の関数式
var addNormal = function(a: number, b: number): number{
  return a + b
}

// アロー記法
var addArrow = (a:number, b:number): number => {
  return a + b
}

// ワンライナー記法
var addArrowOneLiner = (a: number, b: number): number => a + b

console.log(addNormal(6, 10))$
console.log(addArrow(60, 100))$
console.log(addArrowOneLiner(600, 1000))$
```


#関数のオーバーロード

```typescript
function add(a: number, b: number): number //引数と返り値の組み合わせをシグナチャと呼ぶ
function add(a: string, b: string): string

function add(a: any, b: any): any{
  if (typeof a === "string" && typeof b === "string"){
    return a + ' ' + b
  }
  return a + b
}
```

#クラス
クラス定義
コンストラクタ
インスタンス化
動作確認

```typescript
class User {
  constructor(public name: string){
    this.name = name
  }

  sayHello(): void{
    console.log('hello ' + this.name)
  }
}
```

Getter/Setter
Userのプロパティに対するアクセスを制限するためにprivate修飾子をつける。

```typescript
class User {
  constructor(private _name: string){ //privateの変数には慣習的に「_」をつける
  }

  public sayHi(): void{
    console.log('hi! i am ' + this._name)
  }

  get name() {
    return this._name
  }

  set name(newValue: string){
    this._name = newValue
  }
}
```
#npm の html-pdf で何もファイルが出力されないのは、拡張子を .pdf にしていないからでは？

https://www.npmjs.com/package/html-pdf

# OK

```
html-pdf test/businesscard.html businesscard.pdf
```

# NG

```
html-pdf test/businesscard.html businesscard.xxx
```


# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2503








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
【OCI】oracle cloud -仮想クラウド・ネットワーク構築編(VCN)-【初心者向け】

# Oracle Cloud 仮想クラウド・ネットワーク

Virtual Cloud Network(VCN)
ネットワーク上に作る仮想の専用スペースです。

## 前回の記事でコンパートメントを作成しました。

コンパートメントの作成を見たい方はこちらから
[コンパートメント編](https://qiita.com/manaki079/items/1fa3e312f1bc43799c87)

## VCNの作成

左上のメニューからネットワーキング→仮想クラウド・ネットワークをクリック
![instance_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111276/b7417c9d-e38f-832a-642f-15320a0da12c.png)

左下のスコープ→コンパートメント→VCNを作成したいコンパートメントを選択
![instance_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111276/361ac9ee-4b66-40f8-7c37-1c7477a611e7.png)

コンパートメントが切り替わったら仮想クラウド・ネットワークの作成をクリック
![instance_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111276/fe6b4d09-29b4-bf3a-6122-eba1b8209ec0.png)


| 項目       | 概要|
|:-----------------|:-----------------|
| 名前             | 任意のVCN名を入力します。 |
| コンパートメントに作成           | 先ほど切り替えたコンパートメントになっているはずです|
| 仮想クラウド・ネットワークのみの作成 OR 仮想クラウド・ネットワークおよび関連リソースの作成 |セキュリティルールなど自分で用意したい人は上を選択、ちゃっちゃと仮想マシンを建てたい人は下を選択|
| CIDRブロック               |プライベートIPアドレスの範囲を決める |
| DNS解決             |VCNにDNSホスト名を使用するかどうか　基本チェック有りでいいと思う|
| DNSラベル          | 任意のDNSラベル名を入力します。 |
![instance_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111276/37db8a5a-aefa-d135-3062-08baea141eb0.png)
入力し終えたら仮想クラウド・ネットワークの作成をクリック
![instance_8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111276/7d1f95c9-ff7f-f2eb-55c6-31ce3ce481b6.png)

これでVCNの作成は完了
![instance_9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111276/a904e21b-64eb-37b2-11a5-1a176e89455d.png)


## 次回
サブネットの作成を行っていきます。

[サブネット編はこちら](https://qiita.com/manaki079/items/20d9aa3b47db3b39fddd)
Max8トレーニング (1) 四則演算と条件分岐

## ナンバーボックスの配置

・新規パッチを開く
`File → NewPacher`
・ナンバーボックスの配置
`Numbersを選択 → number(i)を選択`
・ロックとナンバーボックスの値を変える
`左下の鍵ボタンを押してロックをかける → number(i)をドラッグして値を変える`

<img src="https://tva1.sinaimg.cn/large/006y8mN6gy1g77zul3gnjg30k60gydoy.gif" alt="maxSample"  />



## 四則演算（+）

・Object →  「+ 10」と入力（+と10の間には半角スペースを入れる!）
・number(i)を選択 → オブジェクトを接続
・ロック → number(i)をドラッグして計算結果をみる

![maxSample_add](https://tva1.sinaimg.cn/large/006y8mN6gy1g780ly3qzeg30k60gy0z6.gif)



## オブジェクトの複製

・下2つのオブジェクトを範囲選択して`Control + D`で複製
・複製したオブジェクトをドラッグして位置を合わせる
・再び`Control + Dで複製`

![maxSample_dup](https://tva1.sinaimg.cn/large/006y8mN6gy1g7813vhqbag30k60gywlr.gif)



## 四則演算（ -, *, /）

・各オブジェクトの「+」をそれぞれ「-」「*」「/」に変更
・ロックして上の数字をドラッグし、計算結果を確認する

![maxSample_shisoku2](https://tva1.sinaimg.cn/large/006y8mN6gy1g7817s51kqg30k60gyjxl.gif)



## 条件分岐（＞）

・全選択して消去
・number(i)を配置 → Object →  「> 10」と入力（>と10の間には半角スペースを入れる!）
・Toggleを配置 → Toggleの下にnumber(i)を配置してつなぐ
・画面をロックしてnumber(i)をドラッグ、何が起こるか確かめる

![maxSample_dainari2](https://tva1.sinaimg.cn/large/006y8mN6gy1g781idmdtdg30k60gywot.gif)



## 条件分岐（＝＝, ＜）

・number(i)以下を範囲選択して`Control + D`（複製）
・位置を揃えて再び`Control + D`（複製）
・中央の「>」を「==」に、一番右の「>」を「<」に変える
・number(i)をドラッグした時の反応を確認

**➡条件に当てはまる時に「1」それ以外の時に「0」を出力します**

![maxSample_Joken](https://tva1.sinaimg.cn/large/006y8mN6gy1g781qghhnwg30k60gy115.gif)



## 条件分岐の応用（練習課題）

[こちらの記事](https://qiita.com/KNBK/items/135f31e405d2e16e0cbc#%E3%82%B5%E3%82%A6%E3%83%B3%E3%83%89%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%86%8D%E7%94%9F%E3%81%99%E3%82%8B%E3%83%91%E3%83%83%E3%83%81%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9)と今回の学習内容を合わせて、入力された数字が「10」の時に音を再生するパッチを作ってみて下さい
まずは何も見ないでトライしてみて、どうしても分からない場合は[こちらのパッチ](https://www.dropbox.com/s/dsjr4v6dz8wbf3a/soundKick.maxpat?dl=1)をみる
sbt assemblyで現れる" sbt-launch-lib.bash: line XX: XXXX Killed "

# sbt assemblyできない
GCPの無料枠インスタンス(たぶんLinux)を使っていた時の話。
sbt 0.13.xで`sbt assembly`でjarファイルを作ろうとした時、以下のメッセージが現れる（jarは生成されない）。

```
[info] Packaging /home/v2okimochi/...build.sbtのディレクトリ.../target/scala-2.12/xxx-assembly-0.1.jar .
..
/usr/share/sbt-launcher-packaging/bin/sbt-launch-lib.bash: line 41:  1698 Killed                  "$@"
```

[似たような議論](https://github.com/sbt/sbt/issues/3414#issuecomment-391376428)がGithub上で繰り広げられていた。

> I solved this issue I had with sbt-1.1.5.deb version by:

雑に「sbt 1.1.5だと解決できたよ」と言っているように見える。

# sbtのバージョンを上げたら解決
何ということもない、sbtの最新バージョン`1.3.2`で試したらjarができた。

どうして急にダメになったのだろうか。`google guice`のinjectを加えたあたりから怪しさがこみ上げる。

とはいえ[sbt 0.13はもはやサポートされていない](https://www.scala-sbt.org/0.13/docs/index.html)らしいので、まあバージョン上げましょうねが真なのだと思う。

> This version of sbt (sbt 0.13) is outdated and not supported!  
Please upgrade to the latest version in 1.x series as soon as possible.

# 具体的にどうやったか
## [sbt公式サイト](https://www.scala-sbt.org/download.html)から`sbt 1.3.2`の.tgzをダウンロードする。

```shell
$ wget https://piccolo.link/sbt-1.3.2.tgz
```

## 解凍する。~~毎回解凍方法を忘れる~~

```shell
$ tar -xzvf sbt-1.3.2.tgz
```

すると`sbt`ディレクトリが現れる。`sbt/bin/sbt`が、普段`sbt`コマンドで実行しているモノの正体たぶんmaybe。

リンクを張ったりアレコレは今回やらない。そのまま使ってしまう。

## 予めメモリ上限を付けておく
GCP無料枠なので`メモリがつらくきびしい`。
環境変数でjavaの使用メモリを制限する。
環境変数は`~/.bashrc`に書いとくと楽。

```shell:.bashrc
...
# 以下を追加（初期サイズ128MB, 最大サイズ200MB）
export _JAVA_OPTIONS='-Xms128m -Xmx200m'
```

過酷と名高いGCP無料枠インスタンス現場は
メモリが少ないと`ぬるぽ`で😇し、
メモリが多いと`There is insufficient memory for the Java Runtime Environment to continue.`で😇するのだ。

丁度よい落とし所は約200MBだった。

最後に`.bashrc`を反映する。

```shell
$ source ~/.bashrc
```

## assemblyする
いよいよ実際に`sbt assembly`する。
`build.sbt`があるプロジェクトディレクトリ（今回はScala-IshiiBot/としよう）でやる。
※sbtはホームディレクトリに置いた状態を想定している。

```shell
~/Scala-IshiiBot$ ~/sbt/bin/sbt assembly
```

`[success]`が出たら成功。
プロジェクトディレクトリの`target/scala-x.x/`に`xxxx-assembly-x.x.jar`ができているはず。

今回の例では`target/scala-2.12/slack-bot-scala-assembly-0.1.jar`である。

## jarの実行
プロジェクトディレクトリで以下のようなコマンドを打てば動く。

```shell
~/プロジェクトディレクトリ$ java -jar target/scala-x.x/xxx-assembly-0.1.jar
```
windows10でLaravel Homestead環境構築で共有フォルダが作成できない

# 概要
laravelのドキュメントを参考にHomestead環境を構築時に少し嵌ったのでメモします。
https://qiita.com/ricoirico/items/9745160bcf9983fa30ad
https://readouble.com/laravel/5.7/ja/homestead.html
上記を参考に`vagrant up`と`vagrant ssh`ともにうまく実行できたけど、　　
`Homestead.yaml`の共有フォルダ`~/code`が仮想環境(`vagrant ssh`先にフォルダが作成されない)に作成されませんでした。`vagrant up`時の出力をよく見ると`homestead: Unable to mount one of your folders. Please check your folders in Homestead.yaml`と出ていました。

# 解決方法
早速、解決方法から述べます。ローカルの共有フォルダ指定`folders: -map:`を絶対パスにすると共有できました。
他のファイルは`~`で参照できてるけどfoldersだけ参照できないみたいです。環境固有のバグですかね？
共有フォルダを設定するプログラムが違う権限で実行されていて共有フォルダの権限を755から777にすればうまくいけるかも？（試してませんｗ）

```Homestead.yaml(修正前)
folders:
    - map: ~/code
      to: /home/vagrant/code
```
```Homestead.yaml(修正後)
folders:
    - map: C:/Users/ユーザー名/laravel/Homestead/code
      to: /home/vagrant/code
```

# その他に共有できない原因
もう一つ嵌りがちなのが`vagrant up`前にローカルに共有フォルダを作成必要があるみたいです？
- `vagrant up`前にローカルに共有フォルダを作成する。作成していなかった場合は`vagrant destroy`と`vagrant up`で再構築してみてください。
- ファイルのパスが間違っている
- ファイル権限の確認
【IFTTT×ラズパイ】体重を記録＋グラフ化したものをLINE通知できるシステムを作った話（2/2）

## はじめに
本システムを作るに至った動機、必要な機器等は[前回の記事](https://qiita.com/ykoba16/items/55ae29f313ee75f3039b)をどうぞ！
前回はRaspberry Pi側の実装を紹介していきましたが、今回はRaspberry Pi以外であるIFTTT、GoogleSpreadSheet側を紹介していきます。

## 実装（IFTTT、GoogleSpreadSheet編）
### IFTTT 側
#### 6. IFTTTがGoogle Spread Sheetの体重表に体重値を追記する
　Raspberry Piからvalue1に日付情報、value2に体重値が送られてくるので、それをWebhookで受け取ってそのままGoogle Spread Sheetに書き込みます。IFTTT側の登録内容は以下のような感じ。予めGoogle Spreadsheetに"Spreadsheet name"に対応するシートを用意する必要があります。

　<img width="441" alt="スクリーンショット 2019-09-22 10.05.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431401/6aa7b31e-d21e-eb21-9d17-f79af689d1a8.png">

### GoogleSpreadSheet 側
こちら側ですがGoogleSpreadSheetのgs(Googleのマクロ)を利用します。

#### 7. GoogleSpreadSheetが体重表から体重推移グラフを作成する
グラフの設定を下記します。下記のような設定にすると、データを追加すると自動的にグラフも更新されるようになります。グラフのデータ範囲は1153行となっていますが、これはGoogleSpreadSheetの仕様上の限界の行数にしています（もっとスマートな指定の方法がありそう）。
<img width="1364" alt="スクリーンショット 2019-09-22 10.20.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431401/76d3f023-9c2b-cd0c-ac4a-a791ffd05eb5.png">

#### 8. GoogleSpreadSheetが体重推移グラフをLINEへ通知する
gsを用いて以下のような流れで処理していきます。gsのトリガーはシートの変更としています。

① 7.で作成したシートの取得
② LINEに通知するメッセージの作成
　　ちょっとした工夫として前回記録時との差分を出すようにしています。
③ LINEに通知

```javascript
function main() {
  sendGraphImage();
}

function sendGraphImage(){
  /* シートの取得 */
  var ss = SpreadsheetApp.openById('【スプレッドシートのID】')
  var sheet=ss.getSheetByName('sheet1');
  var charts = sheet.getCharts();
  
  /* POSTするメッセージと画像を作成 */
  var last_row = sheet.getLastRow()
  
  var current_weight = sheet.getRange(last_row, 2).getValue();
  var before_weight = sheet.getRange(last_row - 1, 2).getValue();
  
  var msg_current_weight = "\n本日の体重は" + current_weight + "でした。\n";
  var msg_compare_before = "前回との差は" + Utilities.formatString("%+.1f", (current_weight - before_weight)) + "です。";
  
  var post_msg = msg_current_weight + msg_compare_before;
  Logger.log(post_msg);
  
  var chartImage = charts[0].getBlob().getAs('image/png').setName("graph.png");
  
  /* POSTの実行 */
  var token = "【LINE API トークン】";
  var payload = {'message' : post_msg, 'imageFile' : chartImage};
  var options =
      {
        "method"  : "post",
        "payload" : payload,
        "headers" : {"Authorization" : "Bearer "+ token}  
      };
  UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options);
}
```

## おわりに
　既存サービスに少し手を加えるだけでそれなりに便利なシステムを作ることできる時代になったなあ、と思いました。スマート体重計なるものも出ていてIFTTT連携可能とのことですが、自分のオリジナルにチューニング（今回だと人感センサを使ったりとか）するなら自作したほうが勉強にもなるし良いのかなと（言い訳）。最後まで読んでいただきありがとうございました！何か感想等ありましたら、コメントお願いいたします！
Discord.jsを拡張しよう！

[Discord.js (v12)](https://discord.js.org/#/docs/main/master/general/welcome)の[Structures](https://discord.js.org/#/docs/main/master/class/Structures)クラスの紹介をしたいと思います。

# 注意

**これから紹介する機能は、v13.0.0で削除されました。**

- Discord.jsのバージョンは`11.5.1`ではなく`12.0.0-dev`
- 開発途中のバージョンで更新が活発（大きな変更には注意しよう）
- Node.jsのバージョンは`10.0.0`以上であること（安定版は`6.0.0`以上）

# インストール

```bash:npm
npm install discordjs/discord.js
```

# どうやって拡張するの？

[ドキュメント](https://discord.js.org/#/docs/main/master/class/Structures?scrollTo=s-extend)の例を見ればすぐに分かると思います。

```js
const { Structures } = require('discord.js');

Structures.extend('Guild', Guild => {
  class CoolGuild extends Guild {
    constructor(client, data) {
      super(client, data);
      this.cool = true;
    }
  }

  return CoolGuild;
});
```

これはGuildオブジェクトに`cool`というメンバ変数を追加しています。よって

```js:bot.js
const { Structures, Client } = require('discord.js');

Structures.extend('Guild', Guild => {
  class CoolGuild extends Guild {
    constructor(client, data) {
      super(client, data);
      this.cool = true;
    }
  }

  return CoolGuild;
});

const client = new Client();

client.on('message', (message) => {
  if (message.guild.cool) console.log('このサーバーはクール！')
})
```

こんなことができるようになる。

## 拡張するときの注意

### Clientのインスタンスを作る前に拡張しなければならない

ドキュメントにも書いてありますが、Clientのインスタンスを作る前に拡張しなければなりません。

# 参考

- [discord.js - Structures](https://discord.js.org/#/docs/main/master/class/Structures?scrollTo=s-extend)

# あとがき

サンプルコードが雑すぎて凄さが伝わらないような気もするけど（）
ちなみに他のオブジェクトも拡張できるよ！これを使っているフレームワークの[klasa](https://github.com/dirigeants/klasa)とか結構参考になると思う。

TypeScript使ってる場合は型定義を書く必要がある。
#javascript の標準関数をブラウザ、オンラインで簡単に動作確認・デバッグしたい時は MDN web docs のシミュレーターが良さげ？

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/ceil

![image](https://user-images.githubusercontent.com/13635059/65379983-96271300-dd0c-11e9-9d23-ffaf7d15fa3b.png)

こんな汎用シュミレータ、どこかにないのかな、とあるjavascript初心者より。

# まだまだWIP学習状態です
![image](https://user-images.githubusercontent.com/13635059/65380004-13eb1e80-dd0d-11e9-8d83-b8849a299dad.png)


# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2502








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Google colab: Glowの学習

[Glow: Generative Flow with Invertible 1x1 Convolutions](https://arxiv.org/abs/1807.03039)はTractableな写像を通して厳密なlog-likelihoodを計算可能にするFlow-based generative modelの一種である。　　
本論では、従来手法である[RealNVP](https://arxiv.org/abs/1605.08803)で用いられたpermutation処理の一般化である1x1 convolutionを導入する事で有意な性能改善を実現した。

今回、公開されている[実験再現repo](https://github.com/openai/glow)を試すために、Google colab上で動かせるようにした。
ipynbリンク：https://github.com/festa78/colab_experiments/blob/master/glow.ipynb

具体的には、

* Cuda versionに不整合があるため、インストールし直し
* TensorflowのversionなどのPython packagesのインストールし直し（Horovodは除く）
* HorovodやMPIなどの分散学習機能はGoogle colabではうまく動かなかったのでコードを弄って除去したFork repoを作成