OmniAICreator/Qiita-1.07M huggingface dataset:
GO111MODULE=onなプロジェクトでDockerのビルド時間を短くした工夫

# はじめに

Go1.11から採用の[Go Modules](https://blog.golang.org/modules2019)(vgo)なプロジェクトにて、Dockerのビルドが遅かったのをキャッシュ利用で一応解決できた話。

# 順を追って

## はじめの状態

下記のような構成

```
.
├── Dockerfile
├── go.mod
├── go.sum
└── main.go
```

```Dockerfile:Dockerfile一部抜粋
COPY . ./
RUN CGO_ENABLED=0 GOOS=linux go build -o binary # 遅い！
```

Goコードの中では大きなOSSプロジェクトライブラリを利用しているので本コードを改修するたびにDockerビルドにて対象パッケージをダウンロードして遅い！

## 次にvendorをレポジトリに入れてみた

下記のコマンドでパッケージたちをvendorとしてレポジトリに組み込んでみました。

```
$ go mod vendor
$ tree
.
├── Dockerfile
├── go.mod
├── go.sum
├── main.go
└── vendor
    ├── package1
    ├── package2
```

```Dockerfile:Dockerfile一部抜粋
COPY . ./                                                   # ここの通信コストが大きくなってしまった
RUN CGO_ENABLED=0 GOOS=linux go build -mod=vendor -o binary # ここは速くなったけど
```

これでパッケージを毎回ダウンロードしないのでビルド時間はたしかに短くなった。
しかしレポジトリが巨大になってしまいました。
そして、このプロジェクトではDocker-Machineのリモート接続でDockerを扱っているのでローカルからリモートへの通信コストがvendorのせいでエグいことになってしまいました。
(そもそも`.dockerignore`もまともに記載していなかったのでこれはこれで対応。)

## 解決策 パッケージダウンロードなイメージレイヤを設けてキャッシュ利用

vendorは削除しました。
他言語のプロジェクトと同様な戦略でパッケージに関わる部分を先にダウンロードするイメージレイヤを作ることでキャッシュを活用することにしました。

```Dockerfile:Dockerfile一部抜粋
ENV GO111MODULE="on"  # Go Modulesを使うと明言する
COPY go.mod go.sum ./ # パッケージ用メタファイルだけコピー
RUN go mod download   # メタファイルに変更がなければキャッシュ利用できる

COPY . ./
RUN CGO_ENABLED=0 GOOS=linux go build -o binary
```

`go.mod`に修正が入らない限り`RUN go mod download`はキャッシュが利用されるので、一番はじめのビルド時間の遅さは解決できました。
また、新しいパッケージを利用しはじめてそれが`go.mod`に反映されていなくても`go build`が代わりにダウンロードするので問題なくイメージがビルドされます。

# 最後にDockerfileの全体感

Dockerfileの全体としては以下のような感じにしています。
マルチステージングの機能を利用して最終的にできあがるイメージは最小になるよう努めています。

```Dockerfile:Dockerfile
FROM golang:1.12.5-stretch as builder

WORKDIR /workdir

ENV GO111MODULE="on"
COPY go.mod go.sum ./
RUN go mod download

COPY . ./

RUN CGO_ENABLED=0 GOOS=linux go build -o binary

FROM alpine:3.8

WORKDIR /root/

# Multi stage build function of Docker
COPY --from=builder /workdir/binary .

CMD ["./binary"]
```
AtCoderにSwiftで挑戦するときの標準入出力

AtCoderにSwiftで挑戦しようとしました。
まだAtCoderのことよくわかっていないのですが、とりあえずSwiftのバージョンは未だに２．２みたいです。
Swiftは今バージョン5まで来たので、2.2なのは結構キツイです。
僕は今年からSwift勉強しはじめて、入り口はバージョン４なので、過去のバージョンアップで変更された部分はよく把握していないのですが、
ざっと見る限りバージョン２から３に上がったときの変更が結構エグかったのかな、という印象で、
メンテされてないSwiftコードは軒並みそのままだと動かなくなってるように見えます。
なので、Swift ２．２でやるとなると、その古い書き方を調べないといけなくて、しんどいです。
C++勉強しろや、ってことなんですかね。。。

# 詰まった部分
標準入力を受け取って、ブランクで値を分割するところですが、下記のコードだとコンパイルエラーになります。

```swift:components(separatedBy)

let input_line: String = readLine()!
let split: [String] = input_line.components(separatedBy: " ") //ブランクで区切られている場合
```
これはSwift2.2にはcomponents(separatedBy:)ではなかったからです。

# サンプルコード
練習問題を解いた例を載せます。

[practice contest](https://atcoder.jp/contests/practice)

```swift:practice_contest
import Foundation
 
var input_lines = [String]()
let row = 3
for i in 0..<row {
    input_lines.append(readLine()!)
}
 
let a = Int(input_lines[0])!
 
let split = input_lines[1].componentsSeparatedByString(" ") //components(separatedBy:)と実質同じ
let b = Int(split[0])!
let c = Int(split[1])!
 
let s = input_lines[2]
 
print((a + b + c), s)
```

# splitでやる
charactersに対して、splitメソッドを使ってやる方法もあります。

[AtCoder に登録したら解くべき精選過去問 10 問を Swift で解いてみた](https://qiita.com/cielavenir/items/b90a94dce60a620fa2dc)

こちらもSwift2.2では記法が若干違うので、辛さ的にはあまり変わりませんね。

# 関連
Swift3.0以降はこちらが参考になるかと。
[paizaの問題をSwiftで挑戦するときの標準入出力](https://qiita.com/eg_19_/items/402dc68a0e0d2c6686b9)

# おまけ
Twitterやってます。エンジニアの知り合いが全然いないので、積極的につながりたいです！
よろしければフォローお願いします。

https://twitter.com/eg_19_
Leetcode #16: 3Sum Closest

```swift
func threeSumClosest(_ nums: [Int], _ target: Int) -> Int {
    if nums.isEmpty {
        return 0
    } else if nums.count == 1 {
        return nums[0]
    } else if nums.count == 2 {
        return nums[0] + nums[1]
    }
    let nums = nums.sorted()
    var sum = nums[0] + nums[1] + nums[2]
    for i in 0..<nums.count-2 {
        var start = i+1
        var end = nums.count-1
        while start < end {
            if abs(nums[i] + nums[start] + nums[end] - target) < abs(sum-target) {
                sum = nums[i] + nums[start] + nums[end]
            }
            if nums[i] + nums[start] + nums[end] == target {
                return target
            } else if nums[i] + nums[start] + nums[end] > target {
                while start < end && nums[end] == nums[end-1] {
                    end-=1
                }
                end-=1
            } else {
                while start < end && nums[start] == nums[start+1] {
                    start+=1
                }
                start+=1
            }
        }
    }
    return sum
}
```
KindleにPDFデータを入れて読む方法

#はじめに
少し前の話になりますが、技術書典が大変盛り上がっていましたね。私は予定があって参加できず、本当に（×100）残念でした涙。次は絶対参加します。

さて、技術書や技術同人誌などを購入することが増えると、購入した技術書をkindleで読みたくなることがあると思います。私自身もそうでした。
ただ、いざやろうとすると、あれ？これってどうするんだっけ？？と思うことが多かったので自分用メモとして、やり方をおいておきます。よかったら参考にしてください。

# 自分のKindle用メールアドレスの確認の仕方
自分でダウンロードしたPDFをKindleで読む場合、PCとKindleをコードでつなげたりするのではなく自分用KindleのメールにPDFデータを送るという作りになっています。~~めんどくさいから作り変えてくれないかな。~~（調べたら端末を直接繋いでもできるみたいでした。ただ、その端末のみでの使用になるので、他の端末でそのファイルを見ようと思っても見ることはできません）

## 1.Amazonのページを開く
https://www.amazon.co.jp
ここです。
![スクリーンショット 2019-05-11 9.38.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237008/9661d765-48dd-72e1-ae69-be30d84260df.png)

## 2.右上のリストにある『アカウント＆リスト』の『コンテンツと端末の管理』をクリック
![スクリーンショット_2019-05-11_9_38_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237008/e7764f1e-b159-7b71-5844-7bbf0488878f.png)

## 3.設定パーソナル・ドキュメント設定を開きます
![スクリーンショット_2019-05-11_9_52_33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237008/1483c64c-cdd0-6a9e-4c6f-adf5eba5107d.png)
ここにあなたのKindleとかかれたKindle用のメールアドレスが表示されているはずです。

# PDFの送り方
上記で確認したメールアドレスにPDFのファイルを添付して、送信します。
タイトルに『変換』といれるとPDF形式ではなく、Kindleで読みやすい形にしてくれますが（線が引けたり）。文字化けしてしまう時もあったので、どうしたら良いか解決したら追記します。

# 送れない場合
- ファイルのサイズが大きすぎると送れません。圧縮サービス等を使ってサイズを小さくしましょう。
- 送るメールアドレスを登録していないと送れません。パーソナル・ドキュメント設定にある承認済みメールアドレスに自分の使用しているメールアドレスがあるか確認しましょう。ない場合は追加しましょう。
OpenCVとNumpyでPDF内の写真を抽出する

以下のようなpdf内にあるカラーの写真を切り取る必要があったので、備忘録的にまとめておきます。
（なお、当方プログラミング初心者なので間違いがあれば優しく指摘していただけると助かります。。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243483/ad259fc9-e64a-43db-93f5-eb80eda5e06d.png)


おおまかな流れとしては
 - 写真の四隅の座標を把握する。
 - 座標で切り取る。
の二つだけです。



まず、必要なモジュールをインポートし、画像を読み込みます。

```
import cv2
import numpy as np
from PIL import Image

image = cv2.imread('pdfが置いてあるパス')
```
↑（訂正）imreadはpdfに対応していないようなので、pngなどに変換します。

次に読み込んだ画像を[BGRからHSV空間に変換(マスク）します](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_colorspaces/py_colorspaces.html)。
写真はカラーであることから、色が付いているものを検出するためです。
今回は彩度（Satulation)の範囲を10〜255としました。

```
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) 

upper = np.array([250, 255, 250])
lower = np.array([0, 10, 5])
mask = cv2.inRange(hsv, lower, upper)
```

次に、写真の[境界](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_contours/py_contours_begin/py_contours_begin.html#id4)を見つけていきます。
また、検出された境界に緑色の線を引いていきます。

```
#　マスクされた画像の中から境界を見つけ、一番大きいものを保持する
(mask, cnts, hierarcy) = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
c = max(cnts, key=cv2.contourArea) 
c_sort = sorted(cnts, key=cv2.contourArea)
c2 = c_sort[-2]

# 境界を最適化する
peri = cv2.arcLength(c2, True)
approx = cv2.approxPolyDP(c2, 0.01 * peri, True)
epsilon = 0.05*cv2.arcLength(c,True)
approx = cv2.approxPolyDP(c, epsilon, True)
epsilon2 = 0.05*cv2.arcLength(c2,True)
approx2 = cv2.approxPolyDP(c2, epsilon, True)

# 境界を緑の線で描く
cv2.drawContours(image, [approx], -1, (0, 255, 0), 4)
cv2.drawContours(image, [approx2], -1, (0, 255, 0), 4)
```

ここで今の境界を見てみます。

```
cv2.imshow("Image_mask", image)
```

![green](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243483/d627456e-5475-5d06-37cb-db1cc51e3c44.png)

下の写真は四角になっていますが、上の写真は四角になっていませんでした。
そこで、四隅の座標だけ取得するため、[boundingRect](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_contours/py_contour_features/py_contour_features.html?highlight=boundingrect)を使います。

```
x,y,w,h = cv2.boundingRect(c)
x_2 = x+w
y_2 = y+h
image = cv2.rectangle(image,(x,y),(x_2,y_2),(0,0,255),2)
x2,y2,w2,h2 = cv2.boundingRect(c2)
x2_2 = x2+w2
y2_2 = y2+h2
image = cv2.rectangle(image,(x2,y2),(x2_2,y2_2),(0,0,255),2)
```

これで、四隅の座標が取得できました。
あとは、これらの座標で切り取るだけです。

```
im = Image.open('pdfが置いてあるパス')

im_crop = im.crop((x, y, x_2, y_2))
im_crop.save('/保存する場所/保存名.png', quality=95)

im_crop = im.crop((x2, y2, x2_2, y2_2))
im_crop.save('/保存する場所/保存名.png', quality=95)
```

これで無事に二つの写真を抽出することができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243483/cc52fb26-f37c-a6e3-dd84-62f8c8c59272.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243483/ce4fbbc5-98f0-5c4c-d510-297a059144be.png)


背景画像にマスクした画像を合成する、というものはあったのですが、
単純に切り取る方法が見つからなかったので、残しておこうと思いました。
OpenCVの導入にはちょうどいいのかもしれません。
rubyで数字比較ゲームを作った

おはようございます。

今日は数字比較ゲームを作ってみました。

<b>仕様</b>
一桁目が1~20の数字と二桁目が1~10の数字の２つの数字を持ったカードが複数枚ある。
一枚目を親としそれ以降を子とし、それぞれを比較していく。
一桁目が小さい方を勝ちとする。
一桁目が同じだったら二桁目を比較する。
二桁目は大きい方を勝ちとする。
子が何回勝ったかを返す
例 

```rb
a = <<~TEXT
12  8 #親
15  9 #子
 4 11 #子
12 19 #子
12  4 #子
TEXT

=> 2
```

<b>コード</b>

```rb
FORMAT = /(\d*) (\d*)/

def high_low_check(card_number)
  card = card_number.scan(FORMAT).map { |array| array.map(&:to_i) }
  card[1..-1].map { |array|
    if array[0] < card[0][0]
      'win'
    elsif array[0] == card[0][0]
      'win' if array[1] > card[0][1]
    end
  }.count('win')
end
```

正規表現で各カードを配列に入れて比較していきます。
if文の中が似たような比較があってあまりDRYじゃないな〜という印象ですがどう治せばいいか分からなかったので、
もし分かる方いたら教えて頂きたいです💦
AWS ASS(ソリューションアーキテクトアソシエイト)に合格した

AWS ASS(ソリューションアーキテクトアソシエイト)に合格したので勉強内容や感想を共有しようと思います。

## 基本情報
受験日：2019/05/11
受験場所:大阪
PearsonVueでの受験

## 事前知識
開発職のエンジニアとして3年半くらいの業務経験。
基本情報技術者合格程度の全般的な知識はある。
業務でAWSをほぼ使っていない。
Udemyの『手を動かしながら2週間で学ぶ AWS 基本から応用まで』を視聴済。

## 勉強内容
[『AWS認定資格試験テキスト AWS認定 ソリューションアーキテクト-アソシエイト』](https://www.amazon.co.jp/dp/B07R1H87Y1/)
模擬試験
AWS INNOVATE 2019のセッション
あと、わからないところを適宜ググった

## 勉強期間
12日間（25時間くらい）

## 結果
739/1000(ギリギリ！)

全65問でトータル1000点なので設問別に重み付けがないとすれば1問15点くらい。
あと2問間違えてたら落ちてました。

## 感想
GWの空き時間にAWS INNOVATEのAWS ASSセッションを視聴したら興味がでたので受験してみました。
試験対策は黒本の評価が高かったのは把握していましたが、以前受講したUdemyの『手を動かしながら2週間で学ぶ AWS 基本から応用まで』がとても良かったので、その講師の金澤さんが共著の一人として最近上梓した『AWS認定資格試験テキスト AWS認定 ソリューションアーキテクト-アソシエイト』を使うことにしました。
わかりやすく書かれていましたが、試験本番では本書以外からの出題もそこそこあった印象でした。
本書の中で挙げられているBlackBeltなどの追加の勉強も必要かと思います。

公式の模擬試験はテキストを2周したくらいで受験しました。
試験形式に慣れるためにもやってよかったかと思います。
結果は84%の正答率でした。
正誤結果や解説はないので受験しながら設問をスクショして自分で調べる必要があります。

ピアソンでの受験だったからか他の体験記であるような監視はなかったです。
本番の設問は事前に解いたものより難しく感じました。
時間はたっぷりあるので時間をかけて臨みました。
いまいち言っていることが理解しきれなかったり解答を特定しきれないときは何度か英語表示に切り替えて理解した問題もありました。

無事合格しました。AWSの思想や構築のベストプラクティス、主要サービスについての基礎知識や気をつける点は理解できた気がします。
引き続き座学だけでなく実際に動かしてみて理解を深めていきたいと思います。
Leetcode #15: 3 Sum

```swift
func threeSum(_ nums: [Int]) -> [[Int]] {
    if nums.count < 3 {
        return []
    }
    
    let nums = nums.sorted()
    var result = [[Int]]()
    var start = 0
    var end = 0
    var sum = 0
    
    for i in 0..<(nums.count - 2) {
        if i == 0 || (i > 0 && nums[i] != nums[i - 1]) {
            start = i + 1
            end = nums.count - 1
            sum = 0 - nums[i]
            while start < end {
                if nums[start] + nums[end] == sum {
                    result.append([nums[i], nums[start], nums[end]])
                    while start < end && nums[start] == nums[start + 1] {
                        start += 1
                    }
                    while start < end && nums[end] == nums[end - 1] {
                        end -= 1
                    }
                    start += 1
                    end -= 1
                } else if nums[start] + nums[end] < sum {
                    start += 1
                } else {
                    end -= 1
                }
            }
        }
    }
    
    return result
}
```
ElixirでJSONPathライクに階層の深い構造から値を取り出す

# はじめに
とある事情で、階層の深ーいデータ構造をErlang/Elixirで扱うことになりました。
ここから特定のデータを取り出す方法について、少し調査が必要だったのでまとめます。

# サマリ
- 1階層ごと辿るなら`Kernel.get_in/2`が基本
  - `Access.at/1`を使うと途中にlistがあっても無問題
- JSONPathの記法を使いたい場合や、途中階層を飛ばして孫要素以降を取り出したい場合のためにはGithubやHexにいくつかのライブラリが見つかったが、いずれも機能は限定的

# やりたいこと
https://hexdocs.pm/elixir/Access.html#module-nested-data-structures に倣って、次のようなデータ構造を例に挙げます。

```elixir

user = %{
  name: "john",
  languages: [
    %{name: "elixir", type: :functional},
    %{name: "C", type: :procedural}
  ]
}
```

例えば深いJSONをパースするとこのようなデータ構造になると思います。

特徴としては、下記のようなものが挙げられます。

- 1つのルート要素が複数の子要素を持ちうる
- そのまた子要素もありうる
- 親要素はmapかもしれないし、listかもしれない

ここから特定のデータ、例えばJSONPathでいう`languages[0].name`を取り出すことを考えます。

# パイプラインを用いる
まず思いつくのがこの方法でした。

```elixir
iex(3)> user |> 
...(3)> Map.get("languages") |> 
...(3)> Enum.at(0) |> 
...(3)> Map.get("name")
"elixir"
```
ただし、この場合は存在しないkeyやindexを指定すると怒られるので、指定しうる場合は気をつける必要がありそうです。

```elixir
iex(4)> non_programmer = %{
...(4)>   "name" => "jane",
...(4)>   "languages" => []
...(4)> }
iex(6)> non_programmer |> 
...(6)> Map.get("languages") |> 
...(6)> Enum.at(0) |> 
...(6)> Map.get("name")
** (BadMapError) expected a map, got: nil
    (elixir) lib/map.ex:437: Map.get(nil, "name", nil)
```

Mapに対しては、`Access.get/2`を使えば`nil`に対する呼び出しやkeyが存在しない場合に`nil`を返してくれます。

```elixir
iex(7)> non_programmer |> 
...(7)> Access.get("languages") |> 
...(7)> Enum.at(0, nil) |> 
...(7)> Access.get("name")
nil
```

# `Kernel.get_in/2`を使う
[公式ドキュメント](https://hexdocs.pm/elixir/Kernel.html#get_in/2)をみると、

```elixir
iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> get_in(users, ["john", :age])
27
```
のようなmapのkeyを指定する方法や、

```elixir
iex> all = fn :get, data, next -> Enum.map(data, next) end
iex> get_in(users, [all, :age])
[27, 23]
```
のように、keyに関数を渡す方法が記載されていました。
後者の方法を使うとlistのindexの指定もできました。

```elixir
iex(6)> at_0 = fn :get, data, next -> data |> Enum.at(0) |> next.() end
iex(7)> user |>
...(7)> get_in(["languages", at_0, "name"]) |>
...(7)> IO.inspect(label: "get_in w/ func")
get_in w/ func: "elixir"
"elixir"
```

また、`Access.at/1`を使うと、上記のようなlistの特定要素を取得する関数を生成してくれるので、普段はこれを使うのが良さそうです。

```elixir
iex(8)> user |> get_in(["languages", Access.at(0), "name"])
"elixir"
```

# 外部ライブラリを使う
`get_in/2`である程度柔軟に深い階層の値を取り出すことができるようになりました。ただ、心のどこかから

- JSONPathのように簡潔な記述で指定したい。。
- JSONPathの`..`のように、孫要素以降を列挙したい。。

という声が聞こえてきて、外部ライブラリで提供されていないか調べてみました。

- [jsonpath](https://github.com/coderdan/jsonpath/blob/master/lib/jsonpath.ex)
- [remap](https://hex.pm/packages/remap)

のあたりが見つかりましたが、前者は`..`に非対応、後者はlistのindex指定に非対応と、ちょっと機能が少ない印象を受けました。

# まとめ
`Kernal.get_in/2`と`Access.at/1`の併用が便利

# メモ
[remap](https://hex.pm/packages/remap)の実装が、Elixir初級者の私にはとても参考になりました。自分でJSONPathライブラリ書いてみようかな。。
2つのExcelファイルの値の差異を抽出する

前回の続き、値の違いを抽出します

```python
import pandas as pd

df_NEW = pd.read_excel("NEW_file.xlsx").fillna("null")
df_OLD = pd.read_excel("OLD_file.xlsx").fillna("null")

df_DIFF = df_OLD.copy()

for row in range(df_DIFF.shape[0]):
    for col in range(df_DIFFshape[1]):
        value_OLD = df_OLD.iloc[row,col]
        value_NEW = df_NEW.iloc[row,col]
        if value_OLD == value_NEW:
            df_DIFF.iloc[row,col] = df_NEW.iloc[row,col]
        else:
            df_DIFF.iloc[row,col] = ("{}→{}").format(value_OLD,value_NEW) #値が違う場合、{古い値}→{新しい値}のように書き換える

writer = pd.ExcelzWriter("DIFF_file.xlsx",engine="xlsxwriter")

df_DIFF.to_excel(writer,sheet_name="DIFF")
df_NEW.to_excel(writer,sheet_name="NEW")
df_OLD.to_excel(writer,sheet_name="OLD")

workbook = writer.book
worksheet = writer.sheets["DIFF"]

#以下フォント、色の処理
gray_fmt = wookbook.add_format({"font_color":"#E0E0E0"})
highlight_fmt = wookbook.add_format({"font_color":"#E0E0E0",
                                     "bg_color":"#B1B3B3"})

worksheet.conditional_format("A1:ZZ10000",{"type":"text",
                                           "criteria":"containing",
                                           "value":"→",
                                           "format":highlight_fmt})

worksheet.conditional_format("A1:ZZ10000",{"type":"text",
                                           "criteria":"not containing",
                                           "value":"→",
                                           "format":gray_fmt})

#保存
writer_save()
```
新たなファイルとして出力しました、違いが一目でわかるようになってると思います
2019-05-12 Design > wwwをURLから消す > Scipy Lecture Noteの例 > リンクを載せた数千の情報はゴミと化す


Qiitaで記載したScipy Lecture Notesの情報をみようとしたらドキュメントを開けない。

調べると以下の変更がされていた。


変更前

```
https://www.scipy-lectures.org/
```

変更後

```
https://scipy-lectures.org/
```

### 影響

変更前のアドレスで記載された数千の情報がゴミと化す。
2019-05-12現在、google検索で4,420件の情報。google検索であがらない情報もこれに加わる。
（一部のリンクは転送がかかるのか、開くことができるものもあるが。）

その影響を考慮した上で必要な対処だったのだろう（きっと）。

一旦公開した情報。
そこから派生する情報がある。
その情報も含めて配置場所変更するどうかをを考えることは、エンジニアとして考慮すべき事項であると感じている。


### 関連

- [2018-03-21 技術情報およびデータを失う技術 + 2019-04-07追記](https://qiita.com/7of9/items/75c0e5b94eeb605197b5)
Chatロボット#03Intnetを拡張してみる


前回まで：
>Chatロボット#01Dialogflowを登録しよう
https://qiita.com/soup01/items/83e5d53bb526c986797d
Chatロボット#02DialogflowとLineを繋がりましょう
https://qiita.com/soup01/items/ea225ecc793ca525b66d

今回はまずDiagflowの仕組みについて少し簡単な説明しますね。
まずいままでこんな感じでやりました。つまり私がこんにちわ！をLINE@に入力し、LINE@は私のメッセージをそのままDialogflowに渡しします。、DialogflowがテキストがどんなIntentに該当にするのかを調べます。前回の例ではこんにちわというIntentに該当するので、その中に設定された”こんにちわ！私はAIロボットです！”という返事をLINE@に返す。
つまり、LINE、Skype、Slackなどはこの場合は単なるチャット機能の画面に過ぎません。
会話の機能として動いてるいるのはDialogflowです。
![flow1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/40f2e338-05a1-56e8-287f-b8d46fc37670.jpeg)

次はLINE@とDialogflowの間を接続する仕組みはWebhookと呼ばられています。その仕組は一番的なしくみでこれを使うことによって下記の図のようにLINE@だけではなくSkype、Slackなどにも簡単に接続することができます。
もちろん、対話AIーつまり会話機能する方はDialogflowだけではなく、IBM Wastsonとか自家のプログラムとか…なども可能です。
![flow2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/58799133-d3f6-0598-a103-0f569dfc9359.jpeg)

#前回のIntentを拡張する
まずDiagflowのところにクリックします。
![digflow30.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/5903f6a8-0e00-d2fa-1c4f-d7f28c994cc6.jpeg)
次はちょっとだけ返事を伸ばしてみよう！名前を聞きましょう。
![digflow31.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/c3000742-3003-1f80-d1ae-e931e004b72f.jpeg)
次はAdd Follow-up Intentをクリックします。
![digflow32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/c13978da-f246-d6cc-1efb-358469d04deb.jpeg)
ここでDroplistが出てきてたくさん選べますが、Customを選びます。できた…と思ったらIntentsの名前は禁止の文字が使われてるよ！怒られます。ここではじめまして！→Welcomeに変更します。
![digflow33.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/00f1c19a-3ffa-fa41-558b-4269cc761228.jpeg)
そうすると、Follow-up intentができましたね！
![digflow34.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/32f31d4a-bd1a-043c-ebb8-441130d10f47.jpeg)
Traning phrasesのところにて適当な答えを入れよう。
![digflow35.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/1b233e07-9c8f-3e48-eac5-70a3ef9084f0.jpeg)
名前のところダブルクリックしたらDropdown listが出てきます。
![digflow36.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/c501e9f6-7508-c386-ae84-8b7c9eac5141.jpeg)
色、URL Link、日付など様々がありますが、今回なにがくるのかわからないので、@sys.anyにします。
![digflow37.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/69125c1b-99c5-2fc0-6638-193a362600f3.jpeg)
ここでは、まず@sys.anyというパラメータが設定され、このパラメータを使用したいときは$anyを使えばOK。つまり覚えてた情報がこのAIロボットに喋らせたいときはこの”$”を使います。
![digflow38.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/2d959ff2-e21f-cf21-9483-e675c13501e0.jpeg)
簡単な返事をしてみます…
![digflow39.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/c2c2c57d-372a-a488-4a4c-36a0dc474191.jpeg)
試してみますね。いけそうですね！
![digflow40.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/ddbbe6c2-e964-b3e6-3e84-9572bd332709.jpeg)
![digflow41.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154661/3f2f6892-7595-a823-9e0d-97bf9696a0ee.jpeg)

お疲れ様です。ー
composite pattern

# composite pattern

swift の uiview

## ケース

部分の集まりで全体が構成されてるとき
部分と全体を表現して、クライアントからは同一として扱いたいとき

## 結果
### pros
クライアントは複雑な構成のオブジェクトも簡単に扱える。
扱う種類が簡単に増やせる。

### cons
全体にとけ込めない特別な要素は増やしにくい。
ので事前の洞察が大切。

## 実装対象

要素(component)のinterface
Component interfaceを満たす子を保持できるCompositeの実装
(Component interfaceを満たす子を保持できないLeafの実装)
子がないcompositeをleafとすればleafは必要ない。

## 難しさ
Leafを作るとすると、addやremoveといった子を操作するインターフェイスを
componentかcompositeのどちらに持たせるかが分岐。
componentに持たせるならLeafはadd, removeを空のメソッドとして実装する必要がある。
シンプルに無駄である。
compositeに持たせるなら、Leafに対してadd, removeを呼び出せないので、部分と全体を同一に扱えなくなる。interfaceが異なるため。
この場合、子を扱う前にcomposite型への変換を試み、確認しなければならない。

Leafを作らない場合は例えば、Compositeがコンポジションとして、ノードとしての要素を別に保持するとか。UIViewとCGRectみたいな

あとは子供の順番に意味を持たせるかの分岐もある。

## example
UIviewの例があるので省略
Visualforce ページでLightning風のエラーメッセージを表示する

Salesforceでエラーメッセージを表示する際、Lightningのデザインを使うときのメモ書き。
lightningStylesheets="true"にすることで使用できる。

### 完成表示イメージ

![Visualforce ErrorMessage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230829/efc6fae3-8571-9574-9628-ed95e8ef31bc.png)

#### 手順１
Salesforceを開く

#### 手順２
開発コンソールを開く

#### 手順３
File　-> New -> Visualforce Page を選択。
ファイル名に適当な名前をつけ以下のソース貼り付けて保存。

```java
<apex:page lightningStylesheets="true">
<apex:pageMessage severity="Error" summary="Error message on page" strength="1"/>
<apex:pageMessage severity="Confirm" summary="Confirm message on page" strength="1"/>
<apex:pageMessage severity="Info" summary="Info message on page" strength="1"/>
<apex:pageMessage severity="Warning" summary="Warning message on page" strength="1"/>
</apex:page>
```

#### 手順４
設定からVisualforceページを選択。先程作成したVisualforceを選択して、プレビューで確認。
［Python］PyGMTをMacに入れた備忘録

##1. PyGMTとは
地球科学分野で定番の地図描写ソフトGMT(The General Mapping Tools)を、Pythonで使えるようにしたものです。
インストールに手間取ったので、備忘録として。


##2. 環境
macOS Mojave 10.14.4
Mac mini (2018)
クリーンインストール済

##3. PyGMTのインストールまでに必要なもの
Homebrew
Anaconda
GMT6

##4. HomebrewとAnacondaのインストール
[こちらの記事](https://qiita.com/aical/items/2d066801a7464a676994)を参照して、HomebrewのインストールとAnaconda環境の用意をした。Python(Anaconda)のインストールでは、

`Python version 3系を使いたい方`

を参照した。

##5. GMT6のインストール
Homebrewを使う。

ターミナルを開けて以下のように入力する。

```ruby:Terminal
brew install gmt
```

これでGMT6のインストールはおしまいです。

(2020/12 追記。GMTのデフォルトのバージョンが6になったので、GMT6のインストールが楽になりました。以前の文章は参考までに残しておきます)

~~GMT中文社区（GMT中国語コミュニティ）の有志の方が、brewでインストール可能にするrbファイルを配布しているので、ありがたく利用させてもらいます。~~

~~GMT中文社区HP内の[GMT6 的安装: 正式推出前体验 GMT6](https://gmt-china.org/blog/install-gmt6/)へ移動する。
[GMT6 的安装: 正式推出前体验 GMT6](https://gmt-china.org/blog/install-gmt6/)の`macOS平台`項目にある~~

~~`gmt6.rb`~~

~~をダウンロードする。~~

~~その後ターミナルを開き、`gmt6.rb`のあるディレクトリへ移動したら~~

```ruby:Terminal
brew install --HEAD get6.rb
```

~~を実行する。~~
~~今回はマシンにGMT5が入っていなかったため、これだけでGMT6のインストールは終わり。~~



##6. PyGMTのインストール
Anacondaを使ってインストールする。
[こちらのHP](https://estuarine.jp/2019/03/pygmt/)の手順で行い、特にエラーが出なければインストール成功。

しかし

```ruby:Terminal
conda activate pygmt
```
を実行した時に、`CommandNotFoundError`が出現した時が厄介。

自分の場合は、`.bash_profile`が格納されているホームディレクトリへ移動し

```ruby:Terminal
open .bash_profile
```
上の操作を実行して`.bash_profile`を開き、


```ruby:TextEdit
. /Users/<ユーザー名>/.pyenv/versions/anaconda3-X.X.X/etc/profile.d/conda.sh
conda activate pygmt
```

この2行を追記後、忘れずターミナルを再起動した。
これで`conda activate`が実行できるようになった。

あとは同様に[HPの指示](https://estuarine.jp/2019/03/pygmt/
)に従えば、インストール完了。

##7. 参照元
PyGMT:Installing
https://www.pygmt.org/dev/install.html

HomebrewのインストールからpyenvでPythonのAnaconda環境構築までメモ
https://qiita.com/aical/items/2d066801a7464a676994


GMT中文社区
https://gmt-china.org
GMT6 的安装: 正式推出前体验 GMT6
https://gmt-china.org/blog/install-gmt6/

PyGMT for Windowsのインストールとテスト
https://estuarine.jp/2019/03/pygmt/


conda activate の CommandNotFoundError への対処方法
https://qiita.com/peaceiris/items/e41488096e765269c93c
2つのexcelファイルの差分がいかほどか確認する

業務にて、2つのファイルの値の差分を求める必要がでてきたため2つの自動化プログラムを作成しました。

値が違うセルの数がいくつあるか調べる

```python
import pandas as pd
import numpy as np

df_New = pd.read_excel("NEW_file.xlsx").fillna("null")
df_OLD = pd.read_excel("OLD_file.xlsx").fillna("null")

compare_values = df_New.values == df_OLD.values

rows.cols = np.where(compare_values)

diff_count = 0

for item in zip(rows,cols):
    diff_count += 1

print(diff_count)
```
コメントを書くべきか？（中級者向け）

コーディングに慣れてきて、リーダブルに書けるようになってくると「あれ、コメントってひょっとして邪魔なだけじゃない？」という考えが首をもたげることがあります。
この考えはそのまま発展すると「完璧にコーディングするとコメントはなくなる」という思想に変化していきます。
あまり世間には顔を出しませんが、こういった思想の方は少なからずいるのではないかと思います。予想ですが。どれだけハイエンドの人でも書かない人いませんか？アレです。

そういう人に向けて「でもやっぱりコメントは必要だよ」と説得してみたいと思います。

## 完璧には書けない
マシン語は別ですが、プログラミング言語は言葉で表現します。
そして言葉というのは曖昧なものです。
曖昧なもので、しかも2,3単語で正しい意味を表現するのは不可能と言っていいです。

## ソースコード上に書けないものがある
もちろん、極力意図に反しない使われ方をしないように設計するべきですが、それでも書けないものがあります。
特に複雑なもの、ビジネスロジック、いつどこで利用されるものか、どのように使用してほしいか（deprecatedとかも）

## 仕様は変化する
ある時には一意に決まったものが、後々一意に決まらなくなるケースがあります。
その修正時に全てを変更できればいいですが、それでは修正のたびに全ソースを確認する必要が出てしまいます。極力冗長にして、ヒントを残しておく方が後に改修する人に優しいです。

## 「ソースコードを読めば分かる」は危険
「どのように使用されているか」の関係を見ればわかるから、コメントは要らないと感じるかもしれません。
しかし関係だけでは意味を正しく切り取ることはできません。

例えば
Xは哺乳類である。
Xは言葉を話す。
Xは二足歩行する。

この時Xが人間だと推測するかもしれませんが、ひょっとしたら雇用者かもしれません。

さらに、ソースは変化します。一部の関係は追加・削除・変更されたりするかもしれません。

## 「コメントが間違ったまま放置されても動くから怖い」「メンテされないリスク」
どちらかというと、コメントはコードより仕様書に近いものです。
「仕様書が間違ったまま放置される」
「仕様書がメンテされない」
よりも
「仕様書がない」
ほうが怖くないですか？

また、コメントはバージョン管理上にあると思いますが、仕様書は大抵バージョン管理上にありません。不具合があった時、どちらのほうが原因を遡りやすいかは分かると思います。
それにコメントはおそらくPull Requestの時にレビューされると思います。そういう意味でもプログラマーにとってありがたい仕様書の一部なのではないでしょうか。

もちろんコメントを過信するのは危険で、書いてあるコードをチェックしなければならないのは当たり前だと思います。「コメントも完璧でなければならない」ではなく「ヒント」程度に考えるとどうでしょうか。

## 「コメントは自動テストできないから不安」
まず自動テストできたら安心というのが危ない気がしますが。
上記で書いたように、コメントは仕様書と考えてみましょう。
仕様書も自動テストはできません。現状、目視で確認するよりありません。

でも一般的な仕様書よりは、コードと一対一で対応しているので間違っているかの確認は取りやすいと思います。

## 次に触る人が完璧だとは限らない
「この程度のコード理解できて当たり前」はやめましょう。
誰だって慣れない時期はあるんです。

## というか、OSSには大体コメント書いてますよ
有名なライブラリとかSDKとか、中を見たら大体コメントびっしり書いてますよ。
コメント不要論に行き着いたなら、彼らが間違ってるか、貴方が間違ってるかのどっちかです。

## というか、リーダブルコードにもっとちゃんと書いてますよ
虎の威を借る
https://www.oreilly.co.jp/books/9784873115658/

## コメントがないと考古学が始まる
コメントがない案件を引き継ぐと、その瞬間に考古学が始まります。プログラマーが何人居たか、誰がいつ編集したか、どういう意図で編集したか、誰に訊けるか、現状の仕様はどうか、仕様に変更はあったか。

ようやく一つの光が見えた頃には1日が終わっています。
「進捗どうですか？」「進捗ダメです」
死にたい・・・

## コメントを書いてもしょうがない場所

でも全部にコメント書くのってムダっぽい感じしますよね。わかります。
特に「そのコメント書いても情報量増えてないし、分かりやすくもなってないし、冗長にも書けない！」と言える場所は不要かと思います。

## どこにコメントを書くべきか

リーダブルコードを読んでください。詳しく書いています。

だと投げやりすぎるので、最低限欲しい場所を。

### 宣言（特に説明が必要そうなもの）
変数、クラス、その他の宣言。
ここに書かないとノーヒントになるので非常に厳しいです。

### インターフェイス
そこにコメントが書かれていると「これをまず読めばいいんだな」とわかります。無駄なコードを読まなくていいです。

### 紛らわしい部分
言語だから曖昧な部分は出ます。

### 全体像、俯瞰的なこと
残念ながら現在の言語では、複数のモジュールを俯瞰的に表示することはできません。

### 意図、お気持ち、メッセージ
注意書き。難しいこと。伝えたいこと。優しさ。

# まとめ

書いてよ（懇願）
Vue.js と Bulma でボタンにアクションつけるやつ

# 今日は、これをやりました

Bulma と Vue.js でボタンのべたなアクションどうやんのかなと

- マウスの Hoover でボタンが反応するやつ
- 入力値をAPIに渡して返ってくるまで待つみたいなやつ

![button-action.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32540/89749d1f-fb5b-4ad7-917d-aa01c1cb113b.gif)

Bulma が用意してくれている `class` を Vue でいじるだけで簡単にできた

# HTML

```html
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css">

<div id="button" class="section">
  <div class="field has-addons has-addons-right">
    <div class="control">
      <input class="input is-large" type="text" v-model="name" placeholder="wassap?">
    </div>
    <div class="control">
      <a
        class="button is-large is-danger"
        v-bind:class="buttonStatus"
        v-on:mouseover="mouseover"
        v-on:mouseleave="mouseleave"
        @click="loading(); api()">
        Hey!
      </a>
    </div>
  </div>
</div>
```

# JS
```javascript
var vm = new Vue({
  el: '#button',
  data: {
    name: '',
    buttonStatus: {
      'is-focused': false,
      'is-loading': false,
    }
  },
  methods: {
    mouseover: function () {
      this.buttonStatus["is-focused"] = true
    },
    mouseleave: function () {
      this.buttonStatus["is-focused"] = false
    },
    loading: function () {
      this.buttonStatus["is-loading"] = true
    },
    api: function() {
      // pretending api call which takes 5sec.
      setTimeout(function() {
        console.log(vm.name)
        vm.buttonStatus["is-loading"] = false
      }, "5000");
    }
  }
});
```

これだけで、なんとなくアプリがいい感じになってくるので不思議。UI 結構大事やな

# CODEPEN

[CODEPENで動くやつをここに貼っときます](https://codepen.io/narutaro-the-reactor/pen/arZLja)

Cheers,
[RPGツクールMV]データベースでアクターの名前を変えてもセーブデータには反映されない

# 概要

RPGツクールMVのデータベースとセーブデータに関する話

例えばアップデートでキャラクタの名前を「ハロルド」から「アレックス」に変更したい！
となった場合、データベースの名前を「アレックス」に変えても、既にプレイしている人のセーブデータから読み込むと「ハロルド」のままになってしまいます

RPGアツマールなどに投稿して継続してアップデートしていくようなゲームの場合、これだと困る場合があります

# なぜか

* データベースに入力したアクターの名前は`Game_Actor`の`_name`に入る
* セーブデータには`Game_Actor`がまるごと保存される
* 続きから遊ぶ場合、`Game_Actor`にはセーブデータの情報が入る

イベントから名前を変更できるようにするためと思いますが、ゲーム中に名前を変える必要がない場合にはセーブデータで持っていない方が都合が良いです

# 実装を変更する

プラグインとして実装して以下のように挙動を変更します

```{javascript}
(function() {

// ===============================================================
// 名前(name)は$dataActorsを参照して自身で持たないように
// ※ゲーム中での書き換えはできないので注意
// ===============================================================

// ---------------------------------------------------------------
// internal定義
// ---------------------------------------------------------------

var internal = {}
// 不要な情報を削除
internal.lightenGameActor_ = function(actor)
{
    delete this._name
}

// ---------------------------------------------------------------
// Game_Actor上書き
// ---------------------------------------------------------------

// Game_Actorで持たない情報を削除
var _GameActor_initMembers = Game_Actor.prototype.initMembers
Game_Actor.prototype.initMembers = function() {
    _GameActor_initMembers.call(this)
    internal.lightenGameActor_(this)
};

var _GameActor_setup = Game_Actor.prototype.setup
Game_Actor.prototype.setup = function(actorId) {
    _GameActor_setup.call(this,actorId)
    internal.lightenGameActor_(this)
};

// name
Game_Actor.prototype.name = function() {
    return $dataActors[this.actorId()].name;
};

Game_Actor.prototype.setName = function(name) {
    // 何もしない
};

})();
```

* 元々メンバで持っていたものを削除する
* `name()`は`$dataActors`から取得するようにする
   * データベースで入力したものが参照されます
* `setName()`では何もしないように変更する


名前`_name` 以外に下記のメンバに対しても同様の実装を入れておくと、
これらもセーブデータに入ったものでなくデータベースの方を参照するようになります

* プロフィール `_profile`
* 2つ名 `_nickname`
* 歩行キャラ `_characterName` `_characterIndex`
* 顔 `_faceName` `_characterIndex`
* [SV]戦闘キャラ `_battlerName`


## 注意点

* `Game_Actor.prototype.setName` で何もしなくなるため、イベントから「名前の変更」を行えなくなります
   * 「名前」以外のメンバに対しても同様の実装を入れると、これらもイベントからの変更ができなくなります

# おわりに

継続してアップデートするゲームというのも多くなってきていると思います。その時に、プロフィールにちょっと誤字があった…とかの不具合を治そうとすると、ゲームからはデータベースを参照してもらう形の方が良かったりします
ただしそれらを変更するイベントのコマンドは使えなくなりますので、どちらの形がよいかはゲームの仕様次第になると思います
AWS/VPCの概要

##AWSでVPCの概要を説明します！

VPCとは、Virtual Private Cloud の略で、AWS専用の仮想ネットワークのことです。

※[VPCについて](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/what-is-amazon-vpc.html)

AWSにネットワークを構築するイメージですね。
VPCは作るだけでは無料のようですが、オンプレミスのネットワークとの接続をしたりなんかするとお金が発生します。

AWSの公式サイトより、VPCでネットワークを構築するとこんな感じになります。

![default-vpc-diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203857/5637ef96-ede0-1c08-3b85-55f5ad84b148.png)

VPCではネットワークを、細分化することができます。
これがサブネットと呼ばれるものです。

開発チームはサブネット1、運用チームはサブネット2．．．のように社内ネットワーク内でもあるチームしか触ることができない環境を構築する場合や、
また、外部との接続があるネットワーク、内部との接続のみのネットワークを構築する場合に役に立ちます。

サブネットではCIDERブロックを分割して使用します。
CIDERブロックとは、IPアドレスの表記方法のことです。
範囲を指定してIPアドレスを指定することができます。

詳しくは
[VPC構築におけるIPアドレス周りのこと](https://tech.librastudio.co.jp/index.php/2016/08/17/post-932/)
の記事に書かれています。

そして、指定したIPアドレスの範囲がサブネットになります！
C#コードのPlantUmlのクラス関係図をpythonで自動作成してみた

# C#コードのPlantUmlのクラス関係図をpythonで自動作成してみた

Qiitaは初めての投稿で色々とまだまだですが、投稿することに意味がある気がしてきたので始めてみる。
（恥ずかしながら、Qiitaをキータと読むことも、１ヶ月前に知りました笑)

###※コードをたまに記載していますが、まだまだ修行中なので何かあればアドバイスお願いします。



###きっかけ
アルバイト先でコードの整理を頼まれました。
なんやかんやあってコードの保守が難しくなった模様。
そのためのステップとして、まずはPlantUmlを使ってコードの流れを掴みたい！
とのこと

しかしコードの量が多すぎてまだまだ未熟な私にはとても手に負えない分量。

とあらば機械に任せてしまうのが得策では？と考えて自動化スクリプト？を作ってみました。



### コードの仕組み

1.ファイルを走査する

```python:
for curDir, dirs, files in os.walk(main_folder_path):
    for file_ in files:
        if file_.endswith('cs'):
            file_path = curDir + "/" + file_
```


2.宣言されたクラス名とnewされたクラス名をそれぞれ取得する

ー＞汚すぎるのでまだ見せれません笑
綺麗に書けたらまた投稿します

3.宣言されたクラス名とnewされたクラス名をPlantUmlにまとめる


```python:
class PlantUml_Factory():
    def __init__(self):
        self.PlantUml_code = ""
        self.PlantUml_code += "@startuml salt\n"
        
    def register_file__class(self,classname_lst,new_class_lst,file_):
        file_ = file_.replace(".","")
        file_ = file_.replace(" ","")

        add_code = ""
        add_code += "\n"
        add_code += "file {}".format(file_) + "{\n"
        for class_inherit in classname_lst:
            for class_ in class_inherit:
                add_code += "   class {} ".format(class_) + "" + "\n"
            
            if len(class_inherit) != 1:
                add_code += "\n"
                add_code += "   "
                add_code += "<-".join(class_inherit)
                add_code += "\n"
            
        add_code += "}\n"
        self.PlantUml_code += add_code
        
    def Construct(self):
        self.PlantUml_code += "@enduml"
        return self.PlantUml_code

```
ここの部分はまだまだ綺麗になりそうですねー...
アドバイスあればお願いします！



4.あとは出力のみ
あとは各々の方法でPlantUmlのコードを作成するのみ！


###これからの野望
1.newされたクラスも関係図に組み込みたい！
2.関数とか変数とかもどうにか表示してみたい！
3.全体図だけでなく、１部分だけの図も作りたい！
余りは切り上げとする商の説明

@drkenさんの[AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～](https://qiita.com/drken/items/fd4e5e3630d0f5859067)
内で、aをbで割った時の商(余りは切り上げとする)は次の式の商に等しいことが述べられています。

```math
\frac{a+b-1}{b}
```
この式についての情報は検索しても特に見つからなかったのでここで説明を試みます。
この式に名前はついているのでしょうか？端数処理の一種でしょうか。。
知っている人がいたら教えてください。

## 目次

|章|タイトル|備考|
|---|---|---|
|0.|[引用](#0-引用)||
|1.|[Javaコード実装](#1-Javaコード実装)||
|1.1.|[数式変換](#11-数式変換)||
|2.|[手順](#2-手順)||
|3.|[その他](#3-その他)||

#0. 引用

以下、該当箇所の引用。
>**【コメント】**
倍数判定はもっと広くとらえると「余りを求める処理」です。というのも「2 で割り切れる」というのは「2 で割った余りが 0 である」ということを意味するからです。
>
発展的話題として「余りを切り上げる処理」があります。例えば、「17 人を 3 人ずつグループに分けて、余ったところは 1 つのグループとしたときに何グループできるか」という問題を考えると、
>
17 ÷ 3 = 5 あまり 2
>
で、3 人グループが 5 個と、余った 2 人によるグループが 1 個できるので、合計 6 個のグループができます。一般に、「a 人を b 人ずつグループに分けると何グループできるか？」は
>
+ a が b で割り切れるとき: a/b
+ a が b で割り切れないとき: a/b + 1
>
になります。しかし実はこれをまとめて **(a + b - 1) / b** と簡潔に書くことができます。今後頻繁に使うことになるテクニックなので習得しておきたいところです。

#1. Javaコード実装
まずは余りがあるかないかで場合分けするコードを書いてみます。

```Java:Java
public class Main {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        //b≠0,aとbは整数
        int a = sc.nextInt();
        int b = sc.nextInt();
        int q = 0;
        
        if(a % b != 0){
            q = (a/b) +1;
        }
        else{
            q = a/b;
        }
        System.out.println("余りを切り上げた商は" + q);
    }
}
```

式を使うとif文がなくなって次のようになります。

```Java:Java
public class Main {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();
        int b = sc.nextInt();
        int q = 0;
        
        q = (a+b-1)/b;
        System.out.println("余りを切り上げた商は" + q);
    }
}
```
#1.1. 数式変換
式は次のように変形できる。

```math
\frac{a+b-1}{b}=\frac{a-1}{b}+1
```

① $\frac{a}{b}$に余りがある時は$\frac{a-1}{b}$と$\frac{a}{b}$の商は同じなので、商についてのみ考えると次の等式が成り立つ。

```math
\begin{align}
\frac{a+b-1}{b}&=\frac{a-1}{b}+1\\
&=\frac{a}{b}+1
\end{align}
```

② $\frac{a}{b}$に余りがない時は$\frac{a-1}{b}$の商は$\frac{a}{b}$の商より1だけ小さいので、商についてのみ考えると次の等式が成り立つ。

```math
\begin{align}
\frac{a+b-1}{b}&=\frac{a-1}{b}+1\\
&=(\frac{a}{b}-1)+1\\
&=\frac{a}{b}
\end{align}
```

①、②は場合分けして書いたコードと同じものである。
#2. 手順
手順で説明すると、

+ a個をb個ずつのグループに分けていく
+ 端数か否かに関わらず最後のグループから1個を引く
+ b個を含むグループの数を数え上げる ($\frac{a-1}{b}$の余りを切り捨てた商を求める)
+ その結果に1を足す

#3. その他

公式をパッと見ただけでは覚えられない人 ~~(私です)~~ が競技プログラミングをやっていく際の参考になれば嬉しいです。
herokuでアプリケーションエラーが起きた時の対処（初心者向け）

```
rails version：Rails 5.2.3
Docker version：18.09.2
```

<br/>
`heroku`をDockerにインストール

```
# dockerコンテナをdeployするためのプラグインをインストール
heroku plugins:install heroku-container-registry

# herokuのコンテナレジストリにログイン
heroku container:login

# 新しいappを作成
heroku create

# Railsが動く`web`のビルド済みdockerコンテナをdeploy
heroku container:push web

# postgresqlアドオンの無料プランを追加
heroku addons:create heroku-postgresql:hobby-dev

# DBセットアップ
heroku run rails db:migrate

# herokuのバージョンを確認する
heroku --version

# herokuへデプロイ（「--force」をつけないとエラーが起きる方は下記参照）
git push heroku master --force
```
参考記事
[docker-composeでRailsを開発しCircleCI 2.0でテストしてHerokuにdeployする](https://qiita.com/Kesin11/items/47079bc7f659e71b694c)


<br/>
`heroku`にデプロイをしたら、アプリケーションエラーが発生してしまった。

```
git push heroku master
```
<br/>
なので、末尾に`--force`を追加して、強制的に今の状態で更新するようにしたら無事に反映された。

```
git push heroku master --force
```

今後herokuにデプロイする場合は、上記のように末尾に`--force`を追加するようにします。
MicrosoftFlowを使ってみた

#MicrosoftFlow
まずは試しに![flow.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415030/ba4bacdd-2610-cffe-347a-82c74be828cd.png)

を使ってみた

次は自分でカスタマイズしてみたい
Ruby初心者が勉強会に参加してみた（全７回）第１回

（noteにまとめたものをこちらにも。）

スクールに行ったこともなければ、

今まで独学（今年１月〜）で勉強していたので

緊張とドキドキが混じりつつ、

株式会社X-HACK主催の

【全７回】Ruby / Vue.js「ゼロから」ウェブサービスを作る【初心者向け | 個別指導あり】に

題名通り、今年１月からRubyの勉強をし始めた初心者が勉強会に参加してきました。



##・Rubyのバージョンを指定する
rbenvでRubyのバージョンを2.4.1に統一。

rbenvについては書籍読んだりする中で出てくるし

実際ポートフォリオ作成の時に、

なんとなくで使っていたけど、

rbenvとはrubyのバージョンを管理する仕組みで、

一つのマシンで好きにバージョンを入れて切り替えることができるもの。

と、改めて認識出来ました！

変更に当たっては、以下のURLの元変更しました。

https://qiita.com/_am_/items/c1dbeb11f40bbbac8fd9



##・パスの概念
パスはファイルやフォルダの場所を示した文字列のことで、

どの階層からでも呼び出せるようにしたい！というのがパスの概念というか目的。

$ echo $PATH


##・シェルコマンド
ここは講義内容とは別で補足でお話していただいた内容で、

便利なのでは！？と個人的に気になりました。

というのも、git.shの中に、

gitコマンドをまとめて入れれば

`$ sh git.sh`
で実行するだけで良いというもの。



##・二進数
コンピュータは０と１での処理しか出来ない。

プログラミングとは

一言で言えば２進数でできるデータ処理。

データをコンピュータにどうやって処理させるかというのを
プログラミングで指示しているということ。

ここは凄く勉強になりましたし、

色紙を使ったワークショップが楽しかったです。

（内容としては、０と１だけを使ってどのように相手に色とその配置を伝えるかというもの）



＝＝＝＝＝＝＝＝＝

全て細かく書いてしまうとかなり長くなるので、

この辺にして

他にも色々勉強になるお話をしていただいたり、

実際の現場内での経験上のお話などなど・・

正直時間が経つのもあっという間でした。



全７回を通してどれだけ成長できるかは、

自分次第だと思うので

この環境に甘んじず、自分でも引き続き勉強していきたいと思います。
ML-AgentsをGoogle Colab上で学習させる

google colaboratoryを使うと無料で学習させられるので、セッションが途切れないようにするためにブラウザを起動する必要はありますが、自分のローカルPCのリソースを利用したくないときに便利です。

UnityのML-Agents（に限らないですが）の学習をさせる上で、こうすると便利だなと思ったことをまとめてみました。

## ML-Agentsのinstall

```python
!git clone https://github.com/Unity-Technologies/ml-agents.git -b 0.8.1
!pip install ./ml-agents/ml-agents/
```

versionは各自使っているバージョンをあわせてください。

## Google Driveをマウントする

せっかく長い時間学習させたのに成果物をダウンロードする前にセッションが切れて初期化、、、なんてことがあると悲しいですよね。

また、実行を停止したときに、学習済みモデルが生成される前に処理が終わってしまうこともあります。

そこで、**Google Driveをマウントして逐一ドライブ上で保存する** ようにしましょう。

```python
from google.colab import drive
drive.mount('/content/drives') #もしくは好きなパス
```

これをセル上で実行するだけで、認証画面に飛び、コードを入力するだけでドライブをマウントできます。これで/content/drives/"My Drive"　以下にGoogle Driveの内容がマウントされている状態になるので、

```python
%cd /content/drives/"My Drive"/  
```

とかでディレクトリを変えて内部で実行すると、学習途中のファイルが保存されます。

頻繁に保存するために、mlagents-learnを実行する際のオプションで`--save-freq=10000`みたいに頻度を上げておくと不慮の事故を避けられるのでおすすめです。

## envとconfig.yamlをgithubで管理する

ML-Agentsで学習させる上でenvをbuildし直したり、configファイルをいじると思うのですが、それらをまとめてgithub上で管理しておき、Colab上で毎回クローンして利用すると便利です。

## Tensorboardを利用する

別のノートブックを作成して、学習させているランタイムと同じランタイムを指定して次のコードを実行すると、tensorboardがcolab上で出力されて便利です、と言いたいところなのですが、、、

```python
%load_ext tensorboard.notebook
%tensorboard --logdir /content/drives/"My Drive"/summaries
```

セッションがクラッシュして、リアルタイムに見ることが私が試した限りでは今の所できませんでした。

[こちらの記事](https://qiita.com/tomo_makes/items/b3c60b10f7b25a0a5935)によると同じランタイムに複数のノートブックで使えそうなのですが、どうも上手くいきません。

tensorboardが見れないとRewardの平均と標準偏差からしか学習の進行状況がわからないのでだいぶ不便です。

どなたかうまいやり方をご存知でしたらぜひ教えてくださいませ、、、 :bow:
ポートフォリオ『CodeJin_BOOK123』使用解説

＊アプリ名が登録商法に引っかかる可能性があるようなので変更しました。
　ご指摘ありがとうございます！
　

# Codejin_BOOK123
これまでに読んだ技術本を  
・ タイトル  ・ おすすめポイント  ・ 画像  
 の３点で簡潔にまとめてユーザー間でシェアするアプリです。  

## 使い方の説明  
・テストユーザーでログイン  
・記事を投稿するために「新規登録」ボタンをクリック  
→新規記事投稿ページの入力フォームに、  
 おすすめの読んだ本のタイトル、おすすめポイント、画像の３点を書き込む。  
・投稿者一覧ページに新規記事が追加される。  


![ezgif.com-video-to-gif (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378334/81ba5791-5046-a5b6-0792-ea0ef55babea.gif)



・記事を編集・削除するには  
→記事一覧ページの編集ボタンをクリック 

![ezgif.com-video-to-gif (4).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378334/641f93c8-8c6a-dc03-3184-561fa5bec5be.gif)


・記事の検索するには
→名称もしくは登録日時を入力し検索ボタンをクリック。

![ezgif.com-video-to-gif (5).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378334/f7414321-4378-e24a-9e1f-9cf4397a5fc5.gif)
   

## 主な機能    

■ユーザー管理機能  
・新規ユーザー登録機能  
・ユーザー詳細表示機能  
・ユーザー一覧表示機能  
・ユーザーアカウント編集・削除機能  
・ユーザーログイン、ログアウト機能  
■投稿記事管理機能  
・新規記事投稿機能  
・記事詳細表示機能  
・記事への画像アップロード機能  
・記事編集・削除機能  
・記事一覧表示機能  
・記事検索機能  
■ユーザー・記事・検索結果一覧のページネーション機能    

## 使用技術  
・開発環境  
ローカル for Mac  
・テスト環境  
RSpec(システムテスト、結合テスト・機能テスト)  
・本番環境  
Heroku  
・DB  
Postgresql  
・フロント開発  
Bootstrap  
Slim     
・画像アップロード機能  
Active Storange  
・ページネーション機能  
kaminari  
・検索機能  
ransack  
・CSV形式のファイルのインポート、エクスポート  
・Ajax  
投稿記事削除           


## 依存関係  

 Rails: 5.2.3  
 Ruby: 2.5.1  
 Bootstrap: 4.3.1  
 RSpec 3.8
builder pattern

# builder pattern
obejectのセットアップ過程を切り出す。

## ケース

オブジェクトの内部表現が
多岐にわたるときや
構造が複雑なとき。

## 結果
### pros
生成したいオブジェクトの内部表現が切り出され、変更が容易になる。

### cons
ない。

## 実装対象

生成したいオブジェクト(product)の内部表現を変更するインターフェイス(Builder)
生成したいオブジェクト(product)の内部表現を変更するオペレーション(ConcreteBuilder)
Builderインターフェイスの使い方を実装するクラス(Director)

## example

Roomを作る例。

```
protocol RoomBuilderProtocol {
    // sideCount 角形の床を設置する
    func buildFloor(at story: Int, sideCount: Int)
    func buildWall(for side: Int)
}

class RoomBuilder: RoomBuilderProtocol {
    func buildFloor(sideCount: Int) {
        room.floor = Floor(sideCount: sideCount)
    }

    func buildWall(for side: Int) {
        let wall = Wall()
        room.walls.append(wall)
        room.floor.setWall(wall, for: side)
    }

    var room = Room()
}

class Director {
    func constructNormalRoom(builder: RoomBuilderProtocol) {
        // 四角形の床
        builder.buildFloor(sideCount: 4)
        // 全面に壁を設置
        builder.buildWall(for: 0)
        builder.buildWall(for: 1)
        builder.buildWall(for: 2)
        builder.buildWall(for: 3)
    }

    func constructStrangeRoom(builder: RoomBuilderProtocol) {
        // 5角形の床
        builder.buildFloor(sideCount: 5)
        // 1面にだけ壁を設置
        builder.buildWall(for: 0)
    }
}

let builder = RoomBuilder()
let director = Director()
director.constructNormalRoom(builder: builder)
let normalRoom = builder.room

let builder2 = RoomBuilder()
director.constructStrangeRoom(builder: builder2)
let strangeRoom = builder2.room
```

Directorクラスはbuilderのインターフェイスを利用するだけに留まっている。
最終成果物はdirectorから取得するのではなく、builderから取得することに注意。
GoogleカレンダーからGASを経由してChatWorkに時間指定で投稿する

参考
https://qiita.com/y_minowa/items/39db8ca5bffc9c440caf

--ポイント--
・予定開始時刻になるとChatwaorkに投稿する
・GASスクリプトを一分毎に起動するようにする
・GASにチャットワークのライブラリを読み込む
・投稿内容は本文のみ
・グーグルカレンダーは本人のものを使用する

```gaschat.gs
// グーグルカレンダーの題名にこのキーワードがあると投稿する
var GASCHATKEY = 'GASCHAT';
// チャットワークのトークン
var CHATWORK_TOKEN = '';
// チャットワークのルームナンバー
var ROOM_ID = '';

function myFunction() {
  main();
}

function main() {
  var calendars = CalendarApp.getAllCalendars();
  var text = Utilities.formatDate(new Date(), 'JST', 'yyyy/MM/dd') + "\n";

  for(i in calendars) {
    var calendar = calendars[i];
    var events = calendar.getEventsForDay(new Date());
    var date = new Date();
    // 時刻を取得
    var ctime = Utilities.formatDate( date, 'Asia/Tokyo', 'HH:mm');
    for(j in events) {
      var event = events[j];
      var title = event.getTitle();
      var body  = event.getDescription();
      var start = toTime(event.getStartTime());
      var end = toTime(event.getEndTime());
      if (title.indexOf(GASCHATKEY)== -1)
      {
        continue;
      }
      if (start !== ctime)
      {
        continue;
      }
      text = body + '\n';
      SendToChatWork(text);
    }
  }
}

function toTime(str){
  return Utilities.formatDate(str, 'JST', 'HH:mm');
}

function SendToChatWork (mes)
{
    var client = ChatWorkClient.factory({token: CHATWORK_TOKEN});
  client.sendMessage({room_id: ROOM_ID, body: mes});
}
```
UnicodeとUTF-8の違いを雰囲気で理解する

## はじめに

文字コード関連の解説を読んでいてると、よく分からない用語(`符号化``文字集合`など)と細かい数字の羅列(`E9``AC``B1`など)が出てきて、頭がごちゃごちゃになってしまいます。

この記事では、なるべく細かくなりすぎずに、`Unicode`と`UTF-8`の違いを理解することを目的としています。


## Unicodeとは

Unicodeとは、`符号化文字集合`の一種となります。`符号化文字集合`は、__「文字」に「数値」を割り当てたものの集まり__のことを言います。以下のように表すことができます。

> <img width="1079" alt="スクリーンショット 2019-05-11 23.22.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2278/0a173131-017f-3f44-168b-449a4f2df87d.png">
> 「[Unicode一覧 0000-0FFF](https://ja.wikipedia.org/wiki/Unicode%E4%B8%80%E8%A6%A7_0000-0FFF)」 (2018年7月1日 (日) 02:58 UTC) 『ウィキペディア日本語版』

表の「左にある数値」と「上にある数値」を組み合わせて、一つの文字を対応付けさせています。

例えば、アルファベットの"A"は、以下のように対応付けさせることができます。

<img width="1081" alt="スクリーンショット 2019-05-11 23.09.10のコピー.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2278/a4abc4f6-ee7a-1d5e-cc7b-0d94b3f2f413.png">
`U+0041` は、`コードポイント`と呼ばれています。`コードポイント`は__文字の住所__というイメージになるでしょうか。


## UTF-8とは

UTF-8は、`文字符号化方式`の一種となります。
`文字符号化方式`とは、`コードポイント`を__「何バイトで」「どのように表現するか」を決めている方式__です。
UTF-8は、__Unicodeのコードポイント__を表す方式です。

UTF-8の場合は、最初の１２８文字は1バイトでコードポイントを表現しています。その後の文字は、2〜4バイトで表現しています。
まとめると以下のようになります。

| コードポイント | 数値表現 | 何バイトで | どのように表現するか |
|---|---|---|---|
| U+0000〜U+007F | 0xxxxxxx | 1バイト(8ビット) | "0"始まり |
| U+0080〜U+07FF | 110xxxxx 10xxxxxx | 2バイト(16ビット) | 1バイト目は"110"始まり<br>2バイト目は"10"始まり |
| U+0800〜U+FFFF | 1110xxxx 10xxxxxx 10xxxxxx | 3バイト(24ビット) | 1バイト目は"1110"始まり<br>2バイト目以降は"10"始まり |
| U+10000〜U+10FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | 4バイト(32ビット) | 1バイト目は"11110"始まり<br>2バイト目以降は"10"始まり |

コードポイントの範囲ごとに使用しているバイト数が違ってきています。また、各バイトの最初の桁の数値が固定されています("0"始まりなど)。
このような取り決めをしているのが、`文字符号化方式`なのですね。


## UTF-16やUTF-32についても

UTF-8以外に、UTF-16やUTF-32もあります。これらも`Unicodeのコードポイント`を表す方式です。
それぞれ「何バイトで」の違いと「具体的な表現」をまとめると以下のようになります。

| 方式 | 何バイトで | 文字"A"の表現 |
|---|---|---|
| UTF-8 | 1〜4バイト | 41 |
| UTF-16 | 2バイト、または4バイト | 00 41 |
| UTF-32 | 4バイト固定 | 00 00 00 41 |

同じUnicodeのコードポイントでも、表現する方法が違っているわけですね。
「どのように表現するのか」については、話が難しくなりそうなので、この記事では取り扱いません。


## まとめ

- `Unicode`は、「文字」に「数値」を割り当てたものの集まり(文字符号化集合)
    - 割り当てた「数値」は`コードポイント`と呼ばれる
- `UTF-8`は__Unicodeのコードポイントを「何バイトで」「どのように表現するか」__を決めている方式(文字符号化方式)
    - UTF-16やUTF-32も同様

以上の流れで解説させていただきました。
`Unicode`と`UTF-8`の関係を雰囲気で捉えることができれば、詳細な話があったとしても「今どの部分の話なのか」を念頭に置いておくことができるので、頭の混乱を避けられます。
また、他の文字コードについても似たような関係があるので、他の文字コードを勉強するときにも理解の助けになるのではないでしょうか。


## 参考

- https://ja.wikipedia.org/wiki/Unicode
Autodesk Inventor と３Dプリンタを使って簡単な小物づくり

##安価な3Dプリンタで造形できる小物を簡単に設計する

使用CAD　Autodesk Inventor
[過去の投稿 簡単なパーツ作り](https://qiita.com/mat-MUNET/items/ac23c5c4b504af4c28fb)の続きです。
今回は、安価な3Dプリンタでの造形を念頭に簡単なケースを設計します。
![Assembly1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355420/ce4ab558-b0bb-e8aa-725b-934d1f4485e1.jpeg)

マイコンボードなどのケースなどに応用できると思います。
###ベース　スケッチ~モデリング
![1_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355420/6f4c021f-99fb-9545-9a14-0f821c7a3300.png)

基本の形となる長方形をスケッチします。
寸法は、後ほど取り付けるパーツに合わせて60×50に設定します。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355420/38b58a43-6bf2-0961-c4bd-f3c52baf6d4d.png)
スケッチしたら3Dモデルタブから押し出しを選択して、3D化します。

##穴あけ
次に60×50の平面を選択し、穴を開けます。
先にスケッチで長方形を描き、寸法を指定します。
この角を基準に穴を開けます。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355420/03bd098b-2060-892a-a56b-f43c13fd8efb.png)

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355420/73aa2d4b-8259-1809-1608-50f045e8e58e.png)

##シェル
穴が空いたら、後にはめるパーツの大きさをくりぬきます。
スケッチします。サイズは50×40です。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355420/33f4571f-5d4c-1178-dd71-7ce020563054.png)
押し出しを使ってくりぬきます。
深さは6mmに設定します。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355420/adf564e0-bb69-40fc-8367-823a6c331df7.png)
３Dモデルから「シェル」を選びます。
先ほどくりぬいた面を選択します。
「シェル」を使うとモデルを植木鉢のようにくりぬいてくれます。
厚みを5mmに設定します。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355420/add71b88-4a8b-d4ca-db89-919fdda31657.png)

##フィレット
各エッジをフィレットします。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355420/ad864f58-938e-8ca0-2496-139515fe1a9d.png)
丸い柱のようなものが出来ましたが、その内側にあるエッジをフィレットしていきます。
4か所とも行います。

![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355420/44e569e2-32e8-eb6a-d799-9688f2b7cf96.png)
角（エッジ）をどんどんフィレットしていきます。

##基本モデル完成
![10_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355420/8226b959-ed18-0840-83ce-d7d631df008b.png)
なんとなく出来ました。

次は、[過去に作ったパーツ](https://qiita.com/mat-MUNET/items/ac23c5c4b504af4c28fb)とアセンブリを行ってみたいと思います。

アセンブリについて
[Autodesk Inventor のアセンブリ方法について] (https://qiita.com/mat-MUNET/items/81965045b8e32e7a0fd7)