OmniAICreator/Qiita-1.07M huggingface dataset:
[学習用]Carrierwave＋S3の画像投稿・保存でハマりまくったけど解決できたこと

![キャプチャ2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132580/5d1e17c2-b647-48d8-ddb3-f56167b6e3ec.jpeg)
gem 'carrierwave'
gem 'mini_magick'
gem 'fog-aws'
gem 'devise'
を追加しただけで、これだけ作れるRailsはすごいなと思いました。

#本題
S3に何故かアップロードできず、8時間もハマった結果、
無事S3へアップロードできたので忘れないうちにメモをしておく。

前提はCarrierwaveやImageは作ってある状態

# GemFile
```gem
gem 'carrierwave'
gem 'mini_magick'
gem 'fog-aws'
```
`gem 'fog'`  から　`gem 'fog-aws'` にする。

# carrierwave.rbの作成
```config/initializers/carrierwave.rb
CarrierWave.configure do |config|
  config.fog_provider = 'fog/aws' # 追加
  config.fog_credentials = {
      provider:              'AWS',                                       # required
      aws_access_key_id:     'アクセスキー',                      # required
      aws_secret_access_key: 'シークレットキー',  # required
      region:                'ap-northeast-1'
  }
  config.fog_directory  = 'S3のバケット名'                              # required
  config.asset_host = "https://s3.ap-northeast-1.amazonaws.com/S3のバケット名" # 追加
  config.fog_public     = false                                             # optional, defaults to true false
  config.fog_authenticated_url_expiration = 600                             # (in seconds) => 10 minutes
end
# 日本語ファイル名の設定
CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/
```

テストの為、「アクセスキー」「シークレットキー」を直書きだが、
あとでENV['UPLOAD_S3_APIKEY']などに変更してheroku config:setで見えない部分にKeyを保存しておくこと。

carrierwave.rbは作成しないと無いので、空ファイルを作成してコピペする。

## IAM作成
![IAM Management Console.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132580/11168af8-62ad-a1b9-246b-b9abff166493.jpeg)

- グループ作成する。
- グループの権限に AmazonS3FullAccess　を追加
- ユーザー作成　
- グループに今作ったユーザーを追加
- アクセスキーを作成してキーとシークレットキーを作成すると表示されるのでメモしておく。


## S3へ
S3でバケット名作成。
名前は何でもよいが、URLになったりフォルダ名になったり、指定したりと色々記述することがあるので、想定した名前が良い。


## S3でパブリックアクセス設定
![S3 Management Console (3).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132580/1bef0a20-956f-8f27-968b-69ecc1afa5d5.jpeg)


テストの時は左から　False　False　True　False　にして試したが
推奨通り全て　True　True　True　True　にしても問題なく保存できた。

## S3でバケットポリシー設定
![S3 Management Console (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132580/d6bc84b5-4f7d-4f47-4a2b-f16dd63dc4e5.jpeg)

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "statement1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::IAMで作ったユーザーのARNの番号16桁:user/IAMのユーザー名"
            },
            "Action": "*",
            "Resource": "arn:aws:s3:::S3のバケット名/*"
        }
    ]
}
```
"Version": "2012-10-17" になっているが、日付を変更する必要は無い。間違っても今日の日付にしない様に。

アプリから投稿した画像を削除すればS3の画像も削除される。

### バケットポリシーについて
試しにバケットポリシーを削除してアップロードしたが画像は正常に投稿できてS3に保存されていた。バケットポリシーは設定しなくても動作した。

バケットポリシーやアクセスコントロールは
https://qiita.com/ryo0301/items/791c0a666feeea0a704c
にまとめられているのでわからなくなったら読んでおくこと。
【Python】35歳＋営業職＋プログラミング経験なしが2週間でPythonを使って営業日報を効率化した話

# 結論（何を効率化したか）

CRM（顧客管理システム）から吐き出されるCSVから必要な情報（訪問先、訪問結果）を抽出し、上長に日報メールを送ることに成功

## 背景

営業した訪問先、訪問結果をCRMに入力している。一日に営業した訪問先と訪問結果を夕方、上長にメールで報告。

ただ、CRMに入力した内容を再度メールに打つのが***めんどくさい***。
コピペでも***めんどくさい***。
なぜなら、コピペするのにも1件、1件訪問先をクリックして訪問結果をコピーしなければならない。その日、10件回ったら10回繰り返さなければならないからだ。

ただでさえ、日中営業で回って疲れている状態で、夕方にこの作業を行うのが***しんどい***わけ。

## 全体の流れ

① 今日分を入力したCRMから一日の訪問結果をCSVでダウンロード
② pythonのプログラムを実行

以上（***以前に比べたらめちゃくちゃ簡単***）
APIとかあればもっと簡単にできるんだろうな・・・

## 実際のコード

```mail.py
from email.mime.text import MIMEText  # MIMETextモジュール読み込み
import smtplib  # smtpモジュール読み込み
import datetime  # 日付モジュール読み込み
import csv  # csvモジュール読み込み

data = []
with open("./crm.csv", encoding="shift_jis") as f:  # csvファイルを開く
     reader = csv.reader(f)  # csvのデータをリストで行単位で保有
     header = next(reader)  # ヘッダーを読み飛ばす
     for row in reader:  # 一行ずつのデータを取り出す
         data.append("・{}\n{}\n".format(row[2], row[9]))  # 訪問先と訪問結果を抽出

# SMTP認証情報
account = "gmailのメールアドレス"
password = "gmailのパスワード"

# 送受信先
to_email = "送信先のメールアドレス（上長のメールアドレス）"
from_email = "自分のメールアドレス"

# MIMEの作成
today = datetime.date.today() #日付を取得し代入
subject = str(today)+"報告" #日付を出力
message = "\n".join(data) #抽出したcsvデータを代入
msg = MIMEText(message, "plain")
msg["Subject"] = subject
msg["To"] = to_email
msg["From"] = from_email

# メール送信処理
server = smtplib.SMTP("smtp.gmail.com", 587)
server.starttls()
server.login(account, password)
server.send_message(msg)
server.quit()

```

このプログラムを実行すると一日の訪問先と訪問結果が上長にメールされる。
同じ内容を再度メールに打つこともなく、コピペをすることもなく。
あ〜簡単、幸せ！！

## まとめ

今までプログラミング経験もなく、Pythonを勉強し始めて2週間くらいしかたっていない。
ここまでできたのも、今は勉強するためのツールや情報がたくさんある。
どのように勉強したかはまた別の機会に投稿しようと思う。
***少しのアイデアとまずはやってみる***ということができれば、日々の業務もこんなに簡単に効率化される。

私がどうやって学習しているかは下記を参考
[【Python】35歳＋営業職＋プログラミング経験なしのPython学習方法（プログラミング経験なし向け）](https://qiita.com/1-row/items/6a67596bf5b7f624eba2)

## 参考にした情報

- [PythonでCSVの読み書き](https://qiita.com/okadate/items/c36f4eb9506b358fb608)
- [pythonで日付取得](https://qiita.com/tortuepin/items/b4231c587d37bb707f2a)
- [Pythonでメール送信](https://www.python.ambitious-engineer.com/archives/2034)
- [csvデータから特定の項目を抽出し、Gmailの本文（message）に入れて送信するにはどうしたらいいですか？](https://ja.stackoverflow.com/questions/53902/csvデータから特定の項目を抽出し-gmailの本文-message-に入れて送信するにはどうしたらいいですか)
もしもPureScriptのEffectがMonadでなかったら

```
$ purs --version
0.12.5
```

# 前置き

`Effect`はMonadなので例えば以下のようなコードが書けます。

```hs
main :: Effect Unit
main = do
  log "hello1"
  log "hello2"
  log "hello3"
```

do記法は`bind`の糖衣構文です。

```hs
main :: Effect Unit
main = log "hello1" >>= (\_ ->
  log "hello2" >>= (\_ ->
    log "hello3"
  )
)
```

## 問い

上記処理を再現する時、`Effect`はMonadである必要があるか？

1. Monadでなければならない。
2. Applicativeであれば十分。
3. Applyであれば十分。
4. Functorであれば十分。

## 答え

Applyであれば十分。

```hs
main :: Effect Unit
main = (\_ _ _ -> unit) <$> log "hello1" <*> log "hello2" <*> log "hello3"
```

# ApplicativeとしてのEffect

## ado記法

先ほどの例は`(\_ _ _ -> unit)`と書かなければならないので使い心地が悪いです。
一般に、Applicativeであることを許すとado記法(Applicative Do Notation)が使えます。

```hs
main :: Effect Unit
main = ado
  log "hello1"
  log "hello2"
  log "hello3"
  in unit
```

イメージ的には以下のように脱糖衣されます。

```hs
main :: Effect Unit
main = pure (\_ _ _ -> unit) <*> log "hello1" <*> log "hello2" <*> log "hello3"
```

実際には一般的なApplicativeスタイルの`map`と`apply`で脱糖衣されるようです。

## Traversable

```hs
class (Functor t, Foldable t) <= Traversable t where
  sequence :: forall a m. Applicative m => t (m a) -> m (t a)
```

`Effect`がApplicativeであることを許せば以下のようにも書けます。

```hs
main :: Effect Unit
main = traverse_ log ["hello1", "hello2", "hello3"]
```

# Monadの力

前の演算結果を使いたいときには結局`bind`が必要になります。

```hs
randomN :: Effect (Array Int)
randomN = ado -- in以外でx, y, zの値を使うことができない
  x <- randomInt 0 9
  y <- randomInt 10 99
  z <- randomInt 100 999
  in [x, y, z, x, z, z, y]

main :: Effect Unit
main = randomN >>= \x -> logShow x
```

実行結果例

```
[3,42,319,3,319,319,42]
```
今さら聞けないシリーズ (id: params[:id])って何？

#問題

```ruby
 User.find_by(id:params[:id])
```
**(id:params[:id])**と見て、
パッと何を意味しているかわかりますか？

#ヒント
コンソールのparametersの中に
ハッシュの**ような**形で書かれています。


#答え
**idの番号**を表しています。

（逆に答えるのが難しい）と
思った方もいるかもしれませんが、

では**どうやってこのidの番号が取れるのか？**
説明できますか？

#復習
###ハッシュ

```
hash = { キー①: 値①, キー②: 値② }
puts hash[:キー①]
値①が取り出せます。
```

###問題

```
hash = { id: 1, name: "Taro" }
1を取り出す場合は何て書く？
```

###答え

```
puts hash[:id]
```

続く
LibreOffice Version: 6.2.2.2 の新元号対応

# Microsoft Excel の場合。
これを書いている時点では

* Office for Mac では令和に対応済み。
* Office for Windows では非対応

という状況なんだけど、非対応の Windows版では「平成31年5月3日」の様になる。まあそうなるよね。

# LibreOffice 6.2 (Calc)の場合。

しかし LibreOffice Calc は違う。
手元の 6.2.2.2 では下図のとおりになる：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6854/30442602-7384-77c9-5f60-085982eb2266.png)

`N` とか `Na` とかになっている。
[窓の杜の記事]( https://forest.watch.impress.co.jp/docs/news/1181072.html )によると LibreOffice 6.2.3 は

> また、本バージョンでは新元号“令和”にも対応しているとのこと。たとえば「Calc」で“2019/05/01”という日付を和暦表示にすると、“令和1年5月1日”とプリントされる。

とのことなのだけれど、これを書いている時点では 6.2.3 は

> If you're a technology enthusiast, early adopter or power user, this version is for you!

とのことなので、まだ一般市民にはおすすめできない状態のようだ。

あと。
軽くヘルプを探った感じでは「元年」表記には対応していない模様。
【初めて学習した】サーバって何？からクライアント・サーバシステムについて

#はじめに
前回、前前回でなんとなくITインフラエンジニアの仕事内容、ミドルウェアについて、
学習しました。
今回はサーバについてまとめます。
至らない点がございましたら、ご指摘をして頂ければ幸いです。

#まずサーバって何？
サーバとは、「サービスを提供する役割がある計算機械」です。
具体的には、
LINEのアプリを開いたら、トークの画面が表示された。
twitterを開いたら、タイムラインが表示された。
※メイプルストーリーで広大なフィールドが表示された。

※メイプルストーリーとは、オンラインゲームのことです。

この３つは表示されているだけで、もう既に、
LINE、twitter、メイプルストーリーのサービスが提供されている状態です。
つまり私たちは画面が表示されているだけで、サービスをもうすでに受けているのです。
これがサーバです。

#続いてクライアント・サーバシステムとは？

私たちは単にサーバとは口にしませんよね。
具体的には、
LINEのサーバ、twitterのサーバ、メイプルストーリーのサーバと言いますよね。
そうです。
サービスを受けている利用者は、
LINEのサーバ、twitterのサーバ、メイプルストーリーのサーバを通して、
メッセージを送受信したり、ゲームができています。

それらのことを
クライアント・サーバシステムといいます。
どんなシステムか、
短くまとめますと、
「クライアント」と「サーバ」を利用するシステムです。

クライアント・サーバシステムの特徴について以下にまとめました。

#【特徴】クライアント・サーバシステム
１、データの処理はクライアントの端末上
　→クライアントが特有のデータを保持できる
　　具体的には、LINE上で自分の名前、自分のアイコンといったものが自分の端末上で修正できる。

２、Web3層構造
　→Webサーバ、APサーバ、DBサーバの３つからなる構造。
　　Webサーバとは、
　　→「静的コンテンツを見せること」
　　 「APサーバに動的コンテンツを要求し、返ってきた結果を見せること」
　　　この２つの役割があります。

上記2行は[ミドルウェア(Web、AP、DB)について知ろう] (https://thinkit.co.jp/article/11837)の2. Web(ウェブ)サーバ(図4)の4行目を引用しました。

　　APサーバとは、
　　→Webサーバから要求されたことに対して、動的なコンテンツで応対すること。
　　→DBサーバに必要であれば処理を要求して、その処理内容を編集して、動的コンテンツに付け足す。

　　DB
　　→APサーバの要求に対して、データベース言語を用いて、それをAPサーバに応対すること。


#メリット
・Web3層構造のため、セキュリティが高い
・システムがとまってもすぐに復旧ができる。

#デメリット
・物理サーバの購入にお金がかかる。

#まとめ
サーバとは、「サービスを提供する役割がある計算機械」
クライアント・サーバシステムとは、『「クライアント」と「サーバ」を利用するシステム』


#次代は仮想サーバシステム！？
仮想サーバについて学習したいと思います。


#参考・引用させて頂いたサイト
・[ミドルウェア(Web、AP、DB)について知ろう](https://thinkit.co.jp/article/11837)
・[LINEでメッセージが届けられるしくみ](https://ascii.jp/elem/000/001/235/1235153/)
・[Webシステムの基本を解説！その仕組みと導入のメリットとは？](https://hnavi.co.jp/knowledge/blog/web-system/)
Mybatis Generatorで日付型のフィールドをJava8のDateTimeAPIとして自動生成する方法

## Mybatis Generatorで日付型のフィールドをJava8のDateTimeAPIとして自動生成する方法

めちゃくちゃ簡単で。
generator-config.xmlに以下の記述を追加するだけ。

```generator-config.xml
<context>
  <!-- 中略 -->
  <javaTypeResolver>
    <property name="useJSR310Types" value="true"/>
  </javaTypeResolver>
</context>
```

javaTypeResolver要素を書く位置は、jdbcConnection要素またはconnection Factory要素の後であることに注意する。
MacでDockerの不要リソースを削除しストレージを開放する

# 問題
MacでDockerを使っているとどうしても不要なイメージやコンテナの残骸がたまり、ストレージを圧迫する。
試しに `docker system df` を叩いてみると40GB近く使っているようだった。こまめに落としたコンテナを削除していてもこれだ。

```bash
sot-mbp:clean_docker_resources sot528$ docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              152                 2                   37.57GB             35.79GB (95%)
Containers          4                   0                   35.8MB              35.8MB (100%)
Local Volumes       4                   0                   7.118MB             7.118MB (100%)
Build Cache         0                   0                   0B                  0B
```

# 解決策

まずは不要なもの根こそぎ削除する便利コマンドを叩く。

```bash
docker system prune
```

しかしまだまだ30GBほど容量を食っている。
古いイメージが残り続けているのが原因のため、直近で使用した10件を残して削除する。

```bash
docker rmi -f $(docker images | sed -n '10,$p')
```

# 結果
＿人人人人人人人＿
＞　スッキリ！　＜
￣Y^Y^Y^Y^Y^Y￣

```bash
sot-mbp:clean_docker_resources sot528$ docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              7                   0                   5.337GB             5.337GB (100%)
Containers          0                   0                   0B                  0B
Local Volumes       4                   0                   7.118MB             7.118MB (100%)
Build Cache         0                   0                   0B                  0B
```

# 環境
- macOS Mojave 10.14.3（18D109）
- Docker version 18.09.2, build 6247962
discord.pyのsend_messageメソッドでエラーになった話

久しぶりに暗号通貨用のスクリプトをいじって、Pypiの更新を適当にしてたらエラーが出たので書いてみます。
Discord.pyでメソッドの廃止があったようです（いつかは知らないけど

# 環境
- windows10
- python3.65


#原因
- https://discordpy.readthedocs.io/ja/latest/migrating.html#
- 上に詳しく書かれていますが、`client.send_message`が廃止されたようです。

```Python
# before
await client.send_message(channel, 'Hello')

# after
await channel.send('Hello')

```
- 他にもいろいろ変更ポイントがありそうでしたが、エラーが出なかったので見なかったことにしました。

# 修正後のソース
```py

@client.event
async def on_message(message):
    if message.content.startswith('/aaaa'):
        reply = 'reply_message'
        #Before
        #await client.send_message(message.channel, reply)
        #after
        await message.channel.send(reply)
```

- チャットBotでメッセージを貰って、リプライするところの実装です。
vue-chart.jsでデータが描画されない(再描画されない）

以下の順で確認すればよいかなと思います。

### データの指定の仕方は正しいか
そもそも間違ってたら描画されないよねというお話（当たり前）。

### mixinsにreactivePropを指定しているか

Chart.jsでは、データの変更に対してリアクティブに描画を変えるという機能がありません。
vue.jsでは、mixinsにreactiveProp or reactiveDataのいずれかを指定することでデータが更新されたらリアクティブ再描画を行います[^1]。

```vue
<script>
  import {Radar, mixins} from 'vue-chartjs'

  export default {
    extends: Radar,
    mixins: [mixins.reactiveProp],
    props: ['chartData', 'options'],
    mounted () {
      this.renderChart(this.chartData, this.options);
    }
  }
</script>
```


[^1]: https://vue-chartjs.org/guide/#updating-charts

### 実はchart.js側の問題でない場合も
今回自分が遭遇したケースです。
dataset自体は更新されているのに描画が更新されませんでした。

これはVueが新規に追加されたプロバティの追加を検知できないためでした。
新規に追加されたプロバティをリアクティブにするにはVue.setを使えば良いです[^2]。

[^2]: https://jp.vuejs.org/v2/api/index.html#Vue-set

```vue
ダメなパターンです。
理由は、rendar()メソッド内で新しく追加されたプロバティをVueが検知できないためです。

<template>

    <v-ons-carousel swipeable auto-scroll>
      <v-ons-carousel-item v-for="(item, itemIndex) in items" :key="itemIndex">
          <radar-chart :chartData="chartDataSets[itemIndex]" :options="chartOption" :styles="{'display':'flex', 'justify-content':'center'}"></radar-chart>
      </v-ons-carousel-item>
    </v-ons-carousel>

</template>

<script>
import Vue from 'vue';
import {_} from 'vue-underscore';
import RadarChart from '@/components/common/radarChart';

export default {
  data() {
    return {
      labels: [ 'label1', 'label2', 'label3' ],
      chartDataSets: {},
    }
  }

  methods: {
    rendar: {
      _.each ( datasets, (dataset, index) => ){
        this.chartDataSets[index] = {};
        this.chartDataSets[index].labels = this.labels;
        this.chartDataSets[index].datasets = [];
        this.chartDataSets[index].datasets.push( { data: dataset } );
      });
    },
  }

}
</script>

```

```vue
代わりにVue.set()を使用することで、Vueがプロバティの追加を検出できるようになります。

<script>
import Vue from 'vue';
import {_} from 'vue-underscore';
import RadarChart from '@/components/common/radarChart';

export default {
  data() {
    return {
      labels: [ 'label1', 'label2', 'label3' ],
      chartDataSets: {},
    }
  }

  methods: {
    rendar: {
      _.each ( datasets, (dataset, index) => ){
        this.chartDataSets[index] = {};
        this.chartDataSets[index].labels = this.labels;
        this.chartDataSets[index].datasets = [];
        this.chartDataSets[index].datasets.push( { data:  } );

        let obj = {};
        obj.labels = this.labels;
        obj.datasets = [];
        obj.datasets.push( { data: dataset } );

        Vue.set( this.chartDataSets, index, obj);
          
      });
    },
  }

}
</script>

```
PowerShellで改行コードを\nエスケープシーケンスに変換する

Azure Automation(PowerShell)で、SlackのIncoming Webhooksにメッセージを投稿するときに、改行コードを\nエスケープシーケンスに変換したくて調べたときのメモです。

* こんな環境変数があったとします。

```powershell
PS> Write-Output $text
aaa
bbb
ccc
```

* replaceして$textに設定し直します。

```powershell
PS> $text = $text -replace "`n","\n"
```

* エスケープシーケンスに変換されました。

```powershell
PS> Write-Output $text
aaa\nbbb\nccc
```

以上です。
【Unity】RenderTextureからTexture2Dの作り方

#今回やること
Cameraで描画されているものをTexture2Dに変換させる。

#用意するもの
- RendererTexture (ProjectWindowで右クリック > Create > RendererTextureで作成可能)
- Camera

#Script
```C#:CreateTexture.cs

     //このScriptはMainCameraにアタッチしてください

    public RenderTexture renderTexture;             //mainCameraにつけるRendertexture(アタッチしてね)
    public Texture2D kakunin;                       //ほんとに保存されているかの確認用
    Camera mainCamera;
	void Start ()
    {
        mainCamera = GetComponent<Camera>();
        kakunin = CreateTexture2D(renderTexture);
	}
	
    /// <summary>
    /// ここでTextur2Dに変換しているよ
    /// </summary>
    /// <param name="rt"></param>
    /// <returns></returns>
    Texture2D CreateTexture2D(RenderTexture rt)
    {
        //Texture2Dを作成
        Texture2D texture2D = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, false, false);

        //subCameraにRenderTextureを入れる
        mainCamera.targetTexture = rt;

        //手動でカメラをレンダリングします
        mainCamera.Render();


        RenderTexture.active = rt;
        texture2D.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
        texture2D.Apply();

        //元に戻す別のカメラを用意してそれをRenderTexter用にすれば下のコードはいらないです。
        mainCamera.targetTexture = null;
        RenderTexture.active = null;

        return texture2D;
    }

```
<img width="662" alt="1c7f98a706f84ae050cab8bb1942589c.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211130/5e739b03-f72d-980e-dd15-9a6bd3b0f108.png">

上のScriptをMainCameraにアタッチしてください。
作ったRendererTextureをアタッチし忘れに注意。

#注意！
この処理はそこそこ重いので毎フレームやることは推奨しません。
やるのであれば数フレームに一回や何かのボタンを押したら１度だけ動くようにするのがいいと思います。

#おわり
何か質問などがある方はコメントください。
PythonでPATHを取得する

###前提
windows10
実行ファイル名：test.py
ディレクトリ構成：C:\Dev\hoge\test.py

###実行ファイル含めた絶対PATHを取得するとき

```
os.path.abspath(__file__)
>>> C:\Dev\hoge\test.py
```

###実行ファイルのディレクトリへの絶対PATHを取得するとき

```
import os
pwd = os.getcwd()
os.path.abspath(pwd)
>>> C:\Dev\hoge
```
もしくは

```
os.path.dirname(os.path.abspath("__file__"))
>>> C:\Dev\hoge
```

###dirname, basename, abspathについて
####os.path.dirname()

```
os.path.dirname(__file__)
>>> C:\Dev\hoge

os.path.dirname(__pwd__)
>>> C:\Dev
```

####os.path.basename() 

```
os.path.basename(__file__)
>>> test.py

os.path.basename(__pwd__)
>>> hoge
```

####os.path.abspath() 

```
os.path.basename(__file__)
>>> C:\Dev\hoge\test.py

os.path.basename(__pwd__)
>>> C:\Dev\hoge
```




###実行ファイル名を取得するとき
pathではないのですが、メモとして...

```
os.path.basename(__file__)
>>> test.py
```
```
a = __file__
print(a)
>>> test.py
```
プログラミング学習記録62〜マントラップ〜

##今日やったこと
- 昨日の続き（情報セキュリティについて学ぶ）

接続元のIPアドレス毎に接続回数をカウントし、一定時間内にアクセス回数が指定数を超えると、そのIPアドレスを一定時間ブロックするmod_evasiveというものがあることを知りました。
DoS攻撃対策ですね。

あと、物理的に情報を守る「マントラップ」というものを知りました。
マントラップとは、サーバールームの扉が二重になっていて、小部屋になっている1つ目と2つ目の扉の間の空間のことです。

1つ目の扉をロックしないと2つ目の扉を開けることができないため、ロック方法がわからないと2つ目の開け方を知っていても開けられないという仕組みです。

また、マントラップに人が2人以上いると2つ目の扉を開けることができないそうです。
RPGの仕掛けにありそうですね笑

ここまで物理的にも守られていたら、より安心できるのかなと思いました。

そして、最後の講義でAIやIoT、ブロックチェーンといった最近話題になっているものについて取り上げられていました。

やはり、この辺の分野は面白そうだな〜と改めて感じました。

明日は講義に加えて、ドットインストールの方も進めていきたいと思います。

おわり
【Rails】パラメーター値の取得（paramsメソッドの使い方）

フォーム情報を取得してインスタンスを生成する、というのはアプリケーションの醍醐味です。

このフォームから送られた値を取得するための`params`メソッドについて、つまづくことが多かったので、簡単に整理します。

# 例

オリジナルアプリ制作時のパラーメータを題材にしています。

```
Parameters: {"utf8"=>"✓", 
"authenticity_token"=>"6YAg0qEsGyxdHWJspI1f2sgzrztYo5cZhSkRHGBgLrVEHvMLdo3xBkJznCFlOIc/650K8ZntJVDWIZejLdQd9g==", 
"post"=>{"product_id"=>"1", "title"=>"おいしい", "rate"=>"5", "content"=>"素晴らしい商品"}, 
```

まず、Parameterは上記のように格納されています。

言わずもがな、`"キー"=>値`という形式です。

Postモデルのインスタンスである`post`はキーとして機能しています。

`post`というキーに対してハッシュで`{"product_id"=>"1", "title"=>"おいしい", "rate"=>"5", "content"=>"素晴らしい商品"}`という値が保存されているわけです。

ややこしいですよね。

# 基本

postの中の値`product_id`をPostモデルより取得しインスタンス変数を生成する場合を考えます。

```
@post = Post.find(product_id: params[:product_id])
```

# 応用

postの中の値'product_id'をProductモデルで取得しインスタンス変数を生成する場合を考えます。

前提として、ProductモデルとPostモデルは一対多の関係性にあります。

```
@product = Product.find(id: params[:post][:product_id])
```

パラメーターからProductモデルを探索す場合、まずは、キー値の[:post]を指定し、次にハッシュ値の中のキー値[:product_id]を指定する必要があります。

この時、[:post]を指定してあげないと、下記のようなエラーが出るので注意ですね。

`ActiveRecord::RecordNotFound in PostsController`
`Couldn't find Product without an ID`
代入演算子と演算子まとめ/文字と数字

前回:https://qiita.com/New_enpitsu_15/items/ff7bd650f3e439060a8f
次回:https://qiita.com/New_enpitsu_15/items/2198c693932ca6460fd6
目次:https://qiita.com/New_enpitsu_15/private/479c69897780cabd01f4

プログラミングをしていると、
ある変数にその変数を操作した値を代入したいことがあります。
たとえば、

```Python
count = 0
#countに0を代入
print(count)
#0

count = count + 1
#countにもともとcountに入っていた値+1を代入
print(count)
#1

count = count + 1
print(count)
#2
```

といった感じです。

でもこれ、countと2回書かなくてもいいんです。

#代入演算子

```Python
count = count + 1
```

は

```Python
count += 1
```

と書き直すことができます
それに、こっちのほうが`countに1を足す`という操作としては直感的ですね。

加えて、__代入演算子は__(おそらく)__すべての演算子に対応__しています。

例えば、
`x`を`2`で割り、その値をそのまま代入したいときは

```Python
x /= 2
```

と書くことができますし、
二乗したいときは

```Python
x **= 2
```

と書いてやれます。

```
[変数] [演算子]= [値...]
```

は

```
[変数] = [変数] [演算子] ([値...])
```

と同義と覚えておきましょう。

---

```Python
x += 1+1
x -= 1+1
x *= 1+1
x /= 1+1
#以上はそれぞれ以下と同義
x = x + (1+1)
x = x - (1+1)
x = x * (1+1)
x = x / (1+1)
```

#演算子まとめ

演算子は、数値、文字列ごとに違った役割が定義されています。

####数値

|演算子|例|挙動|
|:-:|:--|:--|
|+| a + b | aにbを足す |
|-| a - b | aからbを引く |
|*| a * b | aにbを掛ける |
|/| a / b | aをbで割る |
|%| a % b | a÷bの余剰 |
|//| a // b | a÷b小数切り捨て |
|**| a ** b | aのb乗 |

特殊:`-a`で変数aの正負を反転させてくれます。

####文字列

|演算子|例|挙動|
|:-:|:--|:--|
|+| a + b | aとbを結合する |
|*| a * n(数値) | aをb回繰り返す |

#エラー？文字と数字

```
>>> 1 + "1"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>>
```

数値をそのまま文字列に結合、
もしくは文字列を数値としてそのまま計算しようとするとエラーになります。
(そのような演算は定義されていないのです)

文字列を数値として扱いたいのなら`int()`で囲ってあげましょう。

```Python
1 + int("1")
#2
```

数値を文字列として扱いたいのなら`str()`で囲いましょう。

```Python
str(1) + "1"
#'11'
```

こうして、文字列と数値を相互に変換することができます。

#参考

http://www.tohoho-web.com/python/operators.html
TestCoroutineContextを使ってdelayやtimeoutの絡むCoroutineのテストをする

coroutineでタイムアウトを取り扱うようなテストをしようとした時に詰まったのでメモ
# 準備
今回はざっくりこんなコードがあった場合を考える

```kotlin
class Sample {
    // テストしたいコード
    suspend fun methodWithTimeout(suspendItem: SuspendItem): Int?{
        return withTimeoutOrNull(100L){
            suspendItem.someAsync()
        }
    }
}

class SuspendItem {
    // ランダムにdelayして値を返すような関数を考える。テスト時はこちらをmockすることを考える
    suspend fun someAsync(): Int {
        delay(Random.nextLong(10000L))
        return 10
    }
}
```

# テストを書く

mockには今回`mockito-kotlin`を利用している。
正常系を考える場合は下記のように特に考えずにmockすれば良い

```kotlin
@Test
fun methodWithMock() {
    val s = mock<SuspendItem>{
        onBlocking {
            someAsync()
        } doReturn 10
    }
    runBlocking {
        val result = Sample().methodWithTimeout(s)
        assertEquals(10, result)
    }
}
```

そしてタイムアウトを考える場合、`Thread.sleep`などを考えたくなるがこれはうまくいかない

```kotlin
// 駄目なケース
@Test
fun methodWithMock_invalid() {
    val s = mock<SuspendItem>{
        onBlocking {
            someAsync()
        } doAnswer {
            Thread.sleep(10000)
            10
        }
    }
    runBlocking {
        val result = Sample().methodWithTimeout(s)
        assertEquals(null,result) // 通らない！
    }

}
```

## 解法：TestCoroutineContextを利用する

どうすれば良いのか色々調べると`TestCoroutineContext`を利用すれば良いと判明した

* [test-coroutine-context](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.test/-test-coroutine-context/)
* [mockito-kotlin#311](https://github.com/nhaarman/mockito-kotlin/issues/311#issuecomment-459265712)

こんな感じになる

```kotlin
@Test
fun methodWithMock_withTestCoroutineContext() {
    val context = TestCoroutineContext()
    runBlocking(context) {
        val job = GlobalScope.launch(context) {
            val s = mock<SuspendItem> {
                onBlocking {
                    someAsync()
                } doAnswer {
                    context.advanceTimeBy(10L) // 時間を進める
                    10
                }
            }
            val result = Sample().methodWithTimeout(s)
            assertEquals(10, result)
        }
        job.join()
        assertEquals(true, job.isCompleted)
    }
}
```
```kotlin
@Test
fun methodWithMock_withTestCoroutineContext_timeout() {
    val context = TestCoroutineContext()
    runBlocking(context) {
        val job = GlobalScope.launch(context) {
            val s = mock<SuspendItem> {
                onBlocking {
                    someAsync()
                } doAnswer {
                    context.advanceTimeBy(20000000L) // タイムアウトするぐらい時間を進める
                    10
                }
            }
            val result = Sample().methodWithTimeout(s)
            assertEquals(null, result) // Timeoutしてnullが返ってきた！
        }
        job.join() // joinを忘れるとテストが走らずにpassしてしまうことに注意
        assertEquals(true, job.isCompleted)
    }
}
```

ひとまずこれで十分に動いたが、下記などは理解が浅いので未解決な箇所として残っている。

* `GlobalScope.launch`以外のscopeなどでは上手く動かすことができなかった。
* `runBlocking`に`context`を渡さないとデッドロックが起きる？のかうまく動かなかった

おそらくもう少しシンプルに書く手法がありそうだが、今回は切り上げた。
AWS CDKでFnを使う


CloudFormationでよくお世話になる`Fn::XXX`。
これをAWS CDKで使う場合、以下のように書きます。

```typescript
import * as cdk from '@aws-cdk/cdk';

cdk.Fn.conditionIf('IsProduction', 'Linear10PercentEvery1Minute', 'AllAtOnce').toString()
```

`@aws-cdk/cdk`のプロパティに`Fn`があり、その中にメソッドとして実装されています。
具体的に渡すべき値やその後の処理などについては型定義ファイルを見ると良いでしょう。

## ENV

```
$ cdk --version
0.28.0 (build 3ba2622)
```
今さらだけどCanvasを触ってみた

# 背景・同期

今さらかもしれませんが、初めてCanvasを使う機会があったため、備忘録も兼ねて投稿します。

# Canvasを使ったアニメーション

Webフロントの技術でアニメーションを実現する方法はいくつかありますが、Canvasを使ったアニメーションは無限ループする処理の中で画面を再描画するというものです。

1. canvas要素からgetContextでコンテキスト情報を取得する。
2. requestAnimationFrameという関数に自分自身をコールバックとして渡すループ関数を作成する。
3. ループ関数の最初でコンテキストのclearRectで画面を初期化する。

requestAnimationFrameは古いブラウザでは未対応のものもあるので、対策としてpolyfilを用意すると良いです。

```js
// requestAnimationFrame未対応のブラウザ対策
window.requestAnimFrame = (function() {
  return (
    window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.oRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    function(callback) {
      window.setTimeout(callback, 1000 / 60);
    }
  );
})();

// Contextを取得
const canvas = document.getElementById('example');
const ctx = canvas.getContext('2d');

// ループ処理
loop();
function loop() {
  window.requestAnimFrame(loop);
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  // ここにアニメーションの処理を書く
}
```

# Canvasへの描画

矩形やパス、画像などを描画するためのメソッドがコンテキストに用意されているので、それを使って画面に描画します。

```js
// 矩形の描画
// fillRect(x, y, width, height)
ctx.fillRect(0, 0, 100, 100);

// パス（円弧）の描画
// arc(x, y, radius, startAngle, endAngle)
ctx.beginPath();
ctx.arc(10, 10, 50, (-90 * Math.PI) / 180, (90 * Math.PI) / 180);
ctx.closePath();
ctx.fill();

// 画像の描画
// drawImage(image, dx, dy, dw, dh)
const img = new Image();
img.src = '/path/to/image.png';
ctx.drawImage(img, 10, 10, img.width, img.height);
```

アニメーションを実装するには、これらの要素の位置をインクリメントして徐々に移動させます。

```js
let x = 0;
loop();
function loop() {
  window.requestAnimFrame(loop);
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

  // 矩形の移動
  x++;
  ctx.fillRect(x, 0, 100, 100);
}
```

# Ease-In / Out の実装方法

アニメーションでよく Ease-In / Out を使いますが、Canvasではこれらを自分で実装する必要があります。

```js
function easeIn(p) {
  return p * p;
}
function easeOut(p) {
  return p * (2 - p);
}

// 変数の初期化
const duration = 100;
const change = 100;
let x = 0, elapsedFrames = 0;
loop();
function loop() {
  window.requestAnimFrame(loop);
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

  // 経過フレーム数を記録する
  elapsedFrames++;
  if (elapsedFrames > duration) {
    elapsedFrames = 0;
  }
  // 経過フレームの割合からxを計算する
  x = change * easeIn(elapsedFrames / duration);
  ctx.fillRect(x, 0, 100, 100);
}
```

# まとめ

- Canvasでは画面を丸ごと再描画することでアニメーションを実現している。
- getContextで取得したオブジェクトに、画像や矩形を描画するメソッドが用意されている。
- 描画する位置やサイズを計算してアニメーションを実現する。
- Ease-In / Out は独自のメソッドで実現できる。
CentOS7 yum install MariaDB-server 超遅い場合対策

vi /etc/yum.repos.d/mariadb.repo

```config

[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.3.7/centos7-amd64/
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
--------------------- 
↓
↓
↓
↓

[mariadb]
name = MariaDB
baseurl = http://mirrors.ustc.edu.cn/mariadb/yum/10.3/centos7-amd64/
gpgkey=http://mirrors.ustc.edu.cn/mariadb/yum/RPM-GPG-KEY-MariaDB
gpgcheck=1
--------------------- 

```
gitコマンドではcloneできるのにSourceTreeでクローンができない

# gitコマンドではcloneできるのにSourceTreeでクローンができない

開発チームに新たなメンバー（A氏）が加わることになり、さっそくPCに、SourceTreeやらをインストールしてもらうことになりました。

A氏「クローンしようとすると、こんなん出ますー」

```
fatal: unable to access '（リポジトリのURLです！）': The requested URL returned error: 403
Completed with errors, see above
```

何番煎じかわかりませんが、解決法を忘れないうちに記事にします！
ちなみにリポジトリのURLはHTTPSです。SSHではありません。

# そもそもパスワード入力画面がでない

クローンしようとしても、そもそもパスワード入力画面がでませんでした。
認証情報がキャッシュされているのでしょうか・・・

# gitコマンドではcloneできる

SourceTreeは、利用しているGitを

- Embedded（SourceTreeが内臓しているGit）
- System（OSにインストールしたGit）

のどちらかに切り替えることができます。

gitコマンドではcloneできるということは、EmbeddedのGitを利用しているっぽいですね

# 認証情報を探す（Embeddedの場合）
以下に認証情報がキャッシュされています

## Windowsの場合
SouceTreeのメニューバー → `ツール` → `オプション` → `認証` タブ 

こちらに、過去に認証をしたことのあるリポジトリのホストと、認証情報の一覧が表示されます。

## Macの場合
SouceTreeのメニューバー → `SourceTree` → `環境設定` → `高度な設定` タブ 

こちらに、過去に認証をしたことのあるリポジトリのホストと、ユーザー名の一覧が表示されます。

## キャッシュを消そう

キャッシュされた認証情報の中から、クローンできないリポジトリの認証情報を探し出します。

- 東京リージョンのCodeCommitなら `git-codecommit.ap-northeast-1.amazonaws.com`
- GitHubなら `github.com`
- BitBucketなら `bitbuclet.org`

見つけたら、その認証情報を削除します。

再度、クローンを試みると、パスワードの入力画面が表示されます！！

# さいごに

無事にA氏のPCでもクローンができました！よかった！

## （おまけ）GitがSystemの場合
以下に認証情報がキャッシュされています！

### Windowsの場合
`コントロールパネル` → `ユーザーアカウント` → `資格情報マネージャー` → `Windows 資格情報` タブ

### Macの場合
`Launchpad` → `その他` → `キーチェーンアクセス` → サイドバーの `パスワード`
rails test が機能しない時に取った対処法　cannot load such file -- minitest/reporters (LoadError)

初心者がRails Tutorialの４章で遭遇したエラーについてお話します。


4.1.2のカスタムヘルパーの項のリスト 4.4「Homeページのタイトル確認用にテストを更新する」という場面で更新を行いました。その後rails testの指示があったのでその通り入力しましたが、テストが実行されず、以下のエラーが出てしまいました。

```
mac-no-MacBookPro:sample_app mac$ rails test
Starting sample_app_db_1 ... done
2019-04-19 09:02:17 WARN Selenium [DEPRECATION] Selenium::WebDriver::Chrome#driver_path= is deprecated. Use Selenium::WebDriver::Chrome::Service#driver_path= instead.
Running via Spring preloader in process 22
2019-04-19 09:02:25 WARN Selenium [DEPRECATION] Selenium::WebDriver::Chrome#driver_path= is deprecated. Use Selenium::WebDriver::Chrome::Service#driver_path= instead.
/app/db/schema.rb doesn't exist yet. Run `rails db:migrate` to create it, then try again. If you do not intend to use a database, you should instead alter /app/config/application.rb to limit the frameworks that will be loaded.


/usr/local/bundle/gems/bootsnap-1.4.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:33:in `require': cannot load such file -- minitest/reporters (LoadError)
``` 

rails db:migrateの入力が要求されますが、入力しても rails test後のエラー表示が消えませんでした。

下の文章で「cannot load such file -- minitest/reporters」と記述され、minitestがロードされていないことが分かります。

そこで、以下の文をGemfileに書き加えました。

```
gem 'minitest', group: :test
gem 'minitest-reporters', group: :test
```


書き込みが終わった後、インストールすることで解決しました。


```
$ bundle install --without production
```
JavaScriptから始めるプログラミング（HTMLでHello Worldを表示させるまで）

最近JavaScriptを改めて触ったらできることが多く、自分が0からプログラミングの勉強をするなら
JSが手軽に弄れて楽なんじゃないかなーと思ったから記事を書く
## あんた誰
めちゃくちゃ昔のEcmaScriptを弄る仕事をしている人

変数宣言はvarのみ！

だからJavaScriptはよくわかりまてん
これから勉強していきます

## なぜJavaScriptから始めるのか
GoogleChromeや、Firefoxと言ったブラウザさえあればすぐに開発環境が整えられる為
環境構築で無駄な時間を使わなくてもいいしデバッグが容易にできる

また、ES6からはclassにも対応しており、もし他の言語を始めたときにもすんなり入っていける
んじゃね？って思ったから


## どうやって書くの
一番簡単な書き方としてはGoogleChromeやらFireFoxやらを起動して、（Internet Explorer?知らない子ですね・・・）
F12を押してConsoleタブをクリック
その後

```javascript:console

alert("Hello World")
```
打つとポップアップが表示される
ね？簡単でしょ？
まぁこれじゃ味気ないので・・・HTML形式でそれっぽく書いてみる。


## おすすめのエディタ
流石にメモ帳で書くのは見づらいので、おすすめのエディタを紹介
最近はVisual Studio Codeを使っています。
設定方法は[こちら](http://krs1.hatenablog.com/entry/2019/01/23/102737)
設定方法と言っても動かすだけなら設定しなくても大丈夫なはず・・・

## HTMLでHello Worldを表示させる
HTML上でJavascriptを動かすには二種類ある（もっとあったらごめん）

・ HTMLに直接記載する
・ 外部からJavascriptを読み込む

今回はHTMLに直接書く

まずはHTML5のテンプレート記載
文字コードは今回UTF-8で

```html:HelloWorld.html
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
</head>
<body>
</body>
</html>
```

勉強していくとそのうち出てくるけどHTMLは上から読み込まれていくから
javascriptはBody部分に書く
見たいな事が書かれている記事が出てくる。
なんやねんそれ・・・ってなるだろうけどつまりこういうこと

```html:HelloWorld.html
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
</head>
<body>
<script language="javascript">
alert("Hello World");
</script>
</body>
</html>
```

scriptタグ自体は色々なところで宣言できるし実行できるけど、
ページの描画処理以外でJavaScriptを読み込ませると、今はどうでもいい処理まで走ってしまう為
ブラウザ側での描画までが遅くなってしまうという理由からこいう事が書かれている。
うまくJavaScriptが動かなかったりしたときはこの辺の原因もあるかもなので、覚えておくと得。


まぁそれはそれとして、ファイルを保存してからファイルをブラウザで開くと、
Consoleで実行した時と同じようにalertがでる。

さぁここからJavaScriptを使ったプログラミングの勉強が始まる・・・
Laravel バリデーション　memo*

このように、空白や文字数オーバーの時にエラーを表示させる方法。


![スクリーンショット (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209256/a18c01c0-4585-3055-8e86-f8d31ee5a801.png)


`resauce/views/items/create.blade.php` のフォームの上に下記の部分を追加する。

```create.blade.php

    @if ($errors->any())
        <div class="alert alert-danger">
            <ul>
                @foreach ($errors->all() as $error)
                    <li>{{ $error }}</li>
                @endforeach
            </ul>
        </div>
    @endif

//以下にフォームのコード>
```

コントローラーのファイルを以下のように編集

```ItemController.php
public function store(Request $request)
    {
        $request->validate([
            'name' => 'required|max:10', //ここでは入力必須、10文字以下と指定
        ]);
        Item::create([
            'name' => $request->input('name'),
        ]);
        return redirect()->route('items.index');
    }
```



完成！
Oracle Blockchain Platform Cloud Service（OBPCS）で、外部システムと連携してみた

# はじめに
@maato さんからのご指摘いただいたので、今回から「OBCS」あらため「OB **P** CS」とタイトルを変更しています。
https://twitter.com/maato/status/1118901373200818176

# 内容
今回の内容ですが、[前回記事（Oracle Blockchain Cloud Service（OBCS）で、独自チェーンコードの作成|デプロイ|実行する）](https://qiita.com/nobkovskii/items/401b9d45d27bb9004e8f)で作成したチェーンコードを、GUIからポチポチ叩こうじゃないか。という内容になります。

もう少し詳しく書くと、
GUI（express+ejs）から、チェーンコードをインストールしたREST Proxyに対して、Query投げて、その結果をGUIに表示する。
となります。
REST Proxyさんがいるから、こういった内容もラクラク実現可能。

## 使うやーつ
* Node.js
* express
* ejs
* request
* basic-auth-connect
* axios
* OracleCloudのログインID/パスワード
* REST ProxyのURL
* こころばかりの「やるぞ」というきもち

# 実践
いざ、記事にしようと思いましたが、「書くこと無くね？」となりましたので、恐れ多いですが、[Github](https://github.com/nobkovskii/obpcs_sample_system)のReadmeを参考にしてください・・・・。

## はまりぽいんと？
私の場合、コマンド発行時のBASIC認証の記述に戸惑いました。
どうやらHeaderで定義してあげないといけないようで、私はずっとBodyで定義していました。

# おわりに
いままでと比べて、ものごっつ手抜き感があることを、お詫び申し上げます。

さて、次回はどうしたものかな。

以上です。ありがとうございました。
もうレイアウトずれない、テキストボックスの余白を設定する方法 - Googleスライド

# テキストボックスの余白が広くてレイアウトしにくい

Googleスライドを使用していると、いまいち使いにくいツールがあるんですね。
**テキストボックス**です。
<img width="126" alt="スクリーンショット 2019-04-19 17.48.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75329/a8391ed3-5c02-1788-39a7-5a2418cefb2b.png">

めっちゃ使うツールなんですが、いまいち使いづらいんです。
どうしてか、それは**余白が広い**から。
<img width="553" alt="スクリーンショット 2019-04-19 17.49.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75329/56f9caa4-0f8d-0ca9-98ce-e1dfe12e6c25.png">

これでとても問題になるのは、他のオブジェクトに揃えてレイアウトしたいとき。
<img width="397" alt="スクリーンショット 2019-04-19 17.53.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75329/d690d75e-9d52-f041-ac68-2883b2f78030.png">
バウンディングボックスを基準に整列するので、テキスト自体の表示は、すこしずれてレイアウトされてしまいます。
これをなんとかしたい。

## ちなみにKeynoteの場合

Keynoteでもテキストボックスと同様の、「ラベル」がありますが、こちらの余白はそんなに広くない。
<img width="372" alt="スクリーンショット 2019-04-19 17.59.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75329/48c9244d-5127-c4e0-b9a7-a08f67b3a724.png">
これだと比較的レイアウトしやすい。

# テキストボックスのパディングを0にする

テキストボックスを置いたら、速攻でパディングを0で設定します。
方法は以下の通り。

テキストボックスを選択した状態で、「書式設定オプション」をクリック。
<img width="200" alt="スクリーンショット 2019-04-19 17.41.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75329/e4eff5ba-2089-f4e7-c4d8-04aebdde1a52.png">

「テキストの適合」の項目にある、「パディング」をすべて0で設定するだけ。
<img width="312" alt="スクリーンショット 2019-04-19 17.42.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75329/67be759a-a86f-6627-8622-ad8dfa7e4152.png">

揃いました。
<img width="560" alt="スクリーンショット 2019-04-19 17.42.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75329/8a18dd44-1e3f-5dd4-4bcc-d8e0137ee7a2.png">

これで、もうレイアウトのズレに苦しむことはない！

## ちなみにKeynoteの場合

「テキストインセット」の設定を0ptにします。
<img width="408" alt="スクリーンショット 2019-04-19 17.45.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75329/64dd2831-adfe-f0c8-2182-fb0a89dd6e42.png">

# 余談

クリエイティブ系のツール（XD, Illustratorなど）は、基本的には設定しない限りテキストインセットは0なわけですよ。
どうしてドキュメント系のツールって余白がデフォルトで付いているんでしょうね……。
そのほうが効率的なのかな…？
Laravel ペジネート memo*

このページの下のようなページネーションという機能です。
ここでは１つのページに５つだけ表示して、それ以降は次のページに・・・



![スクリーンショット (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209256/510a52ab-0d93-2aca-850d-f295dc38d418.png)



編集するのは、２つのファイル



１つ目↓

コントローラーに　**paginate(表示したい数)**　を指定する。


```ItemController.php
    public function index()
    {
        $items = Item::paginate(5);  //　()の数字は表示したい要素の数
        return view('items.index', compact('items'));
    }
```


２つ目↓

```index.blade.php
@extends('layouts.app')
@section('title', '商品一覧')
@section('content')
 {{ link_to_route('items.create','新規登録',[],['class'=> 'btn btn-primary'])  }}
<table class="table table-striped">
    <thead>
        <tr>
            <th>ID</th>
            <th>商品名</th>
        </tr>
    </thead>
    <tbody>
    @foreach($items as $item)
        <tr>
            <td>{{  link_to_route('items.show',$item->id,['item' => $item->id]) }}</td>
            <td>{{$item->name}}</td>
            <td>{{ link_to_route('items.edit', '編集', ['id' => $item->id], ['class' => 'btn btn-default']) }}</td>
            <td>
                {{ Form::open(['route' => ['items.destroy', $item->id], 'method' => 'delete']) }}
                {{ Form::submit('削除', ['class' => 'btn btn-danger']) }}
                {{ Form::close() }}
            </td>
        </tr>
    @endforeach
    </tbody>
</table>
 {{ $items->links() }}  //この一行を追加★！
@endsection
```


完成！
コンパイルは同じOS上でしようね

Docker初心者です。

## GoでHTTPサーバーを建てようとしたときのこと

下のDockfileをもとにGo言語製のHTTPサーバーをDockerコンテナ上で実行しようとしたところエラーが発生した。

参考記事
[golangでdockerをはじめる ~ goのwebサーバーをdockerでたててみた ~](https://qiita.com/vankobe/items/f4c09e8e4b580651b568)

```dockerfile
FROM golang
MAINTAINER tositeru
ADD ./main.go /go/src/server/main.go
RUN go install server

FROM alpine
COPY --from=0 /go/bin/server .
EXPOSE 8080
CMD ["./server"]
```

エラー内容はこちら

```bash
docker logs test
> standard_init_linux.go:207: exec user process caused "no such file or directory"
```

見た感じコンパイルしたバイナリがうまくコンテナ内にコピーできていない感じなので、とりあえず確認をしてみる。

なんだろビルド中のエラーかなと思い`RUN`コマンドでファイルを確認、ついでにカレントディレクトリも。

```dockerfile
FROM golang
MAINTAINER tositeru
ADD ./main.go /go/src/server/main.go
RUN go install server

FROM alpine
COPY --from=0 /go/bin/server .
EXPOSE 8080
RUN ls
RUN pwd
CMD ["./server"]
```

結果は省略するけど、ファイルは無事コピーされており、カレントディレクトリも正しい位置にあった。

何度か確認のためイメージを作っては消してを繰り返していくうちに、いやいや`bash`を起動するほうが簡単に確認できるでしょ、と気づき`CMD`を`["bash"]`に変えた所、なんとエラーが発生。

ここであれ、Ubunutuとは環境が違うの？と気がつく。

## Linuxディストリビューションって微妙に違うところがあるから困るよね

と言う訳で調べた所、alpineでは`ash`を代わりに使うようでそれを使うようにしたら問題なくコンテナ内に入れた。

ファイルもコピーされており、何が原因なのかわからないとので検索してみたら、どうやらコンパイルしたバイナリが依存しているライブラリにアクセスできていないのが原因とのことで、次のコマンドを`ash`上で実行してみたら問題なくバイナリを実行できるようになった。
~~OSが違う環境でバイナリ化しているからそりゃそうだ~~

[こちらの記事](https://stackoverflow.com/questions/34729748/installed-go-binary-not-found-in-path-on-alpine-linux-docker)

```bash
mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
```
上でも解決できるそうだが異なるOSでコンパイルしていてなんか怖い感じがあるので、ビルドする環境もalipneに変えて最終的には下のようなDockfileに。

```dockerfile
FROM golang:1.12.4-alpine3.9
MAINTAINER tositeru
ADD ./main.go /go/src/server/main.go
COM ["go", "install", "server"]

FROM alpine
COPY --from=0 /go/bin/server .
EXPOSE 8080
RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
ENTRYPOINY ["./server"]
```
これで問題なし！

## 終わりに

ちなみに今回のエラーには関係ないがDockerfileは[Use multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/)という機能を使っていて、サーバーとして機能するコンテナにはGoのソースコードを含まないようにしている。

ローカルでビルドしたものを取り込むという形でもいいかもしれないけど、試し試しでやっていって作業がしやすい方にしていこうかなと。

検証中のイメージの作成/削除が地味に面倒だったのでスクリプト化していったほうがいいのかもしれないとか、
デプロイするときフロントエンド側のリソースも含めるようにしないといけないとかあるので、
作業を進めていく内に解決していこうと思う。
selenium.common.exceptions.WebDriverException: Message: 'chromeDriver' executable needs t o be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/homeが出た

環境:windows10 home

解決策:sizeを指定することを忘れない


driver.set_window_size(1350, 640)を追加したら正常に動いた。
WMPlayer上のUbuntuで時刻が9時間ずれる件


調べてみるといろいろな要因があり、それぞれ解決方法が異なるようだ。
自分の環境では以下の方法で修正できた。

```:/etc/adjtime
0.0 0 0.0
0
LOCAL
```

```bash
$ sudo hwclock -s
```
PHPでURLが存在しているか確認する

#概要
タイトルのとおり、あるURLが存在しているかを確認したいときに使った方法です。

#コード
`file_get_contents` に引数をつけて、最初の1バイトだけ読み込んで判断しています。

```PHP
if(@file_get_contents('https://xxx/xxx/xxx', NULL, NULL, 0, 1)){
	//ファイルあり処理
}else{
	//ファイルなし処理
}
```

##参考
https://www.softel.co.jp/blogs/tech/archives/4766

#おまけ　PHPでファイルダウンロード

```PHP
<?php
//ダウンロード元URL
$url = 'https://xxx/xxx/xxx';
//保存ファイル名
$filename = 'saved.zip';
if(@file_get_contents($url, NULL, NULL, 0, 1)){
	//ダウンロード処理
	header('Content-Type: application/force-download');
	header('Content-Disposition: attachment; filename="'.$filename.'"');
	readfile($url);
}else{
	//ファイルなし処理
	header('Content-Type: text/html; charset=UTF-8');
	echo 'エラーが発生しました。ファイルが存在しません。';
}

```

URL先のファイルサイズの取得はできていませんので、ダウンロード中のパーセンテージでの進捗はとれません。

これをいれればよさげですが、未検証です。
http://www.muzin.org/wp/webprogramming/php/file-size_52/
論文の図を作るときの参考

# 書いてる人はどういう人？
博士後期課程2年の大学院生（2019年4月時点）。
専門は太陽物理学。
主に用いる研究手法は、Pythonを使った太陽観測画像の画像処理です。

# なんのための記事？
論文の図を作るときに、よく参考にするサイトのまとめ。
主に自分の備忘録のためです。

# URL リスト
### Matplotlib
- [Thumbnail gallery] (https://matplotlib.org/gallery.html)

図のサムネイルギャラリー。作りたい図の雛形を探す。
![gal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334854/44757dac-9b56-2e22-a3f2-727011a7d210.png)

- [Twin plot](https://matplotlib.org/gallery/subplots_axes_and_figures/two_scales.html#sphx-glr-gallery-subplots-axes-and-figures-two-scales-py)

左右のy軸に違う値を表示させたいとき。
<img width="643" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334854/951f3d94-57a6-6079-8d6f-65b89df25054.png">

- [Marker](https://matplotlib.org/api/markers_api.html#module-matplotlib.markers)

plotするときののマーカー一覧。
![marker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334854/c26df247-fc41-d23f-1591-98f96020c2d4.png)

- [Line style](https://matplotlib.org/examples/lines_bars_and_markers/line_styles_reference.html)

plotするときのline style 一覧。
![line_styles_reference.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334854/d90db06b-4618-88c6-6b1c-fc45cb7ec3ad.png)

- [Hatch 図](https://matplotlib.org/gallery/shapes_and_collections/hatch_demo.html#sphx-glr-gallery-shapes-and-collections-hatch-demo-py)

Hatch図の書き方。
<img width="342" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334854/4423a921-a0a9-5dfe-f255-9c12fdaf65a4.png">

- [Textのfontなど](https://matplotlib.org/api/text_api.html#matplotlib.text.Text)

Text（plotのlabelなども含む）のkeywords 一覧。
<img width="357" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334854/03506db4-9936-a4f6-bc72-d6c20b5005b4.png">

- [Color map](https://matplotlib.org/tutorials/colors/colormaps.html#sphx-glr-tutorials-colors-colormaps-py)

カラーマップ一覧。
<img width="372" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334854/29b30bc8-8903-8a48-f557-37f2ca390f54.png">

- [Colors](https://matplotlib.org/examples/color/named_colors.html)

plotの際のcolors一覧。
![color_matplotlib.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334854/a117cac9-1cf0-cf80-34d8-1093c7ad2694.png)
Apex Design Patterns(Strategy)

#1.Strategyの概要
戦略パターン（別名ポリシーパターン）は同じ問題に対して複数の解決策を提供する。
実行時に1つの解決策を選択する。

**UML構造図**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/430b9fb8-f2b0-d734-1b1c-763c9d18a213.png)

#2.実装例
##2.1.Strategyインターフェース作成
```java

public interface Strategy {
    Integer operation(Integer num1, Integer num2);
}
```
##2.2.OperationAddクラス作成
```java

public class OperationAdd implements Strategy{
    public Integer operation(Integer num1, Integer num2) {
       return num1 + num2;
    }
}
```
##2.3.OperationSubstractクラス作成
```java

public class OperationSubstract implements Strategy{
    public Integer operation(Integer num1, Integer num2) {
       return num1 - num2;
    }
}
```

##2.4.Context クラス作成
```java

public class Context {
    public class NameException extends Exception{}
    private static Map<String, Strategy> strategyMap = new Map<String, Strategy>();
    
    static {
        strategyMap.put('OperationAdd', new OperationAdd());
        strategyMap.put('OperationAdd', new OperationSubstract());
    }
    
    public static Integer executeStrategy(String strategyName, Integer num1, Integer num2){
        if (!strategyMap.containsKey(strategyName)) {
            throw new NameException(String.format('strategyが存在しません。({0})', new String[]{strategyName}));
        }
        
        Strategy strategy = strategyMap.get(strategyName);
        return strategy.operation(num1, num2);
    }
}
```

##2.5.Client
```java

System.debug('10 + 5 = ' + Context.executeStrategy('OperationAdd', 10, 5));  
System.debug('10 - 5 = ' + Context.executeStrategy('OperationSubstract', 10, 5));
```
#3.参照資料
- [Apex_Design_Patterns](https://developer.salesforce.com/page/Apex_Design_Patterns)
- [设计模式](http://www.runoob.com/design-pattern/design-pattern-tutorial.html)
Apex Design Patterns(Singleton)

#1.Singletonの概要
単一のトランザクションコンテキスト内で一度だけインスタンス化する。
ガバナー制限及びリソースの多重使用を避ける。

主なポイント：
　・コンストラクタを private とする
　・Singletonインスタンス変数宣言および初期化
　・Singletonインスタンス取得用公開メソッド

**UML構造図**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/eb10741e-91a2-7328-8608-dbe09a962404.png)

#2.実装例
Apex に static 変数の life cycle はトランザクションです。
java のように synchronized を考慮しなくても大丈夫です。

Singletonインスタンスの初期化は２つの方法があります。
　 ・eager-initialization
　 ・lazy-initialization

``` java:eager-initialization
public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton (){}

    public static Singleton getInstance() {
     return instance;
    }
}
```

``` java:lazy-initialization
public class Singleton {
    private static Singleton instance;
    private Singleton (){}

    public static Singleton getInstance() {
     if (instance == null) {
         instance = new Singleton();
     }
     return instance;
    }
}
```
#3.参照資料
- [Apex_Design_Patterns](https://developer.salesforce.com/page/Apex_Design_Patterns)
- [设计模式](http://www.runoob.com/design-pattern/design-pattern-tutorial.html)
WSLでNuxt.jsのgenerate時に91％で止まる

# generateが止まる
題名通り、自分はWindowsのWSL(Ubuntu18.04)を利用して開発を行っています。
たまにgenerateが重いときはあったのですが、今回完全に91％で止まるようになったので調査しました。

[Nuxt.jsのissue](https://github.com/nuxt/nuxt.js/issues/2921)にて同じ悩みを抱えている方がいたためすぐに解決しました。


# Pluginのインストール
まずは圧縮用のツールのプラグインである[terser-webpack-plugin](https://github.com/webpack-contrib/terser-webpack-plugin)をインストールします。

``` Node.js
npm i -D terser-webpack-plugin 
```

# configファイルの編集
インストールしたterserを使うようにconfigファイルを編集

``` nuxt.config.js
import TerserPlugin from 'terser-webpack-plugin'
module.exports = {

//省略

  build: {
    optimization: {
      minimize: true,
      minimizer: [
        new TerserPlugin({
          cache: true,
          parallel: false
        })
      ]
    }
  }
//省略
}
```

# 終わりに

何かあったときは落ち着いてissueを見る。