OmniAICreator/Qiita-1.07M huggingface dataset:
191230_About,学習記録

##このブログは何？
30代IT業界未経験のankimoがWebデザインを仕事とする為、**2019年12月から始めた勉強**の「学習記録」「アウトプット」のBlogです。

##なんか目標とかあるの？
（１）2020年4月までにWebデザイン・コーディングを仕事としてお金を稼ぐ。
（２）2020年4月にWeb業界へ転職(給与面の折り合いがつけば)。

##そもそも君の名は？
・`名前`：ankimo
・`年齢`：30代
・`住処`：都内某所
・`学歴`：中堅私立の生物系学部。院卒（生命科学修士）。
・`現職`：製薬系のサービス業、と言えば伝わる人には伝わるはず(メーカーではない)。
・`職務内容`：契約締結等の事務作業から営業まで多岐にわたる所謂なんでも屋。
・`webデザイン勉強理由`：
**↓**大学時代より興味があったが”独学のモチベーション保てず””激務・薄給のイメージ”より勉強進まず。
**↓**時は経ち現在、現職の伸び率(会社及び自己スキル的両面とも)に不安を覚え転職活動開始。
**↓**転職エージェントより製薬×IT系の職種を紹介され、言われるがままProgateにてJava勉強開始。
**↓**「お、そういえばWeb系になりたい時期あったな・・・(HTML講座ポチー)」
**↓**「おもろい」
**↓**気がつけばProgate修了及びデイトラを進めつつ今に至る。Javaは最早触っていません。

##もう2020年だけど2019年12月の勉強内容は？
Progateを見る限り、12/02よりHTML/CSSの勉強を始めている。

・`Progate`：HTML/CSSは修了。Javascriptは3章まで。現状Stop。
・`#30DAYSトライアル`：1stのDay18まで。現在はポートフォリオ作成中。
※BootstrapのYoutube模写は[Bootstrap 4 フロントエンド開発の教科書](https://amzn.to/2ZDsZOp)第9章にて代替中。
→**なぜ？**：ただただ動画を写経し続ける苦痛に耐えきれなかった為。
・`デザイン`：[ノンデザイナーズ・デザインブック](https://amzn.to/354Ywu1)読了。
・`Udemy`：[未経験からプロのWebデザイナーになる!400レッスン以上の完全マスターコース](https://www.udemy.com/course/web-design-master/)開始。
→**なぜ？**：Photoshopに触れたい・ワイヤーフレームについて学べる・年末セールの波

1日約1h以上、土日は約4h取れていたと思うので52hくらいTotalでやっている筈。
キリが悪いので、Total:55hをスタート地点とします(大雑把)。


##じゃあ早速今日の積み上げ報告を。
【Time】
Today：2h(この記事書くのに1h位かかりましたがノーカン)
Total：57h
TotalDays:29days
(2019/12/02より)

【Contents】
**（１）[Bootstrap 4 フロントエンド開発の教科書](https://amzn.to/2ZDsZOp)：第9章**
・モーダル/タブ型ナビゲーション/カードの作製
-タブ型ナビゲーションの1を作成後2以降をコピペした際、activeまでコピペしてしまいbottomにアホみたいにスペースが空いてしまい、解決に大変苦労した。
-タブが「コーヒー」「モーニング」「ランチ」「ケーキ」に分かれていたが、実際のカフェであればこれら項目に結構な数のバラツキが現れると思うので、レイアウトが綺麗にならない気がした。であれば別個にメニューのPageを作ったほうが良い・・？

**（２）Udemy：[未経験からプロのWebデザイナーになる!400レッスン以上の完全マスターコース](https://www.udemy.com/course/web-design-master/)**
-ワイヤーフレームの作り方
・視線の動き方：WebはF型が多いとのこと。
→**なぜ？**：「レイアウトの領域が決められているものはZ型で見ることで全体像を把握したくなる」「レイアウト領域が決まっていないWebサイト(恐らく1画面に全ての情報が表示されていない為？)はF型で具体的な内容を把握するように動く」という違いと私は推測しました。下記に推測に至ったサイトを記しますので、参考までに。
（参考1：[Webコンテンツを読む視線の軌跡は“F”を描く](https://u-site.jp/alertbox/20060417_reading_pattern)）
（参考2：[ウェブと紙のデザイン考察　―視線の動き編― 紙はZ型、WebはF型](https://jirei.bzlog.jp/webdesign01/)）

##締めの言葉
以上です。
これからどうぞ宜しくお願い致します。

***
以下勉強時間積み上げのテンプレート

【Time】
Today：xxh　
Total：xxh
TotalDays:xxdays
(2019/12/02より)

【Contents】
**（１）勉強した大項目**
-勉強した詳細1
-勉強した詳細2

**（２）勉強した大項目**
-勉強した詳細1
-勉強した詳細2

**（３）勉強した大項目**
-勉強した詳細1
-勉強した詳細2
[macOS][Kotlin]開発環境を用意する

<p>仕事でAndroidアプリケーションをKotlinで開発しているので、macOSでKotlinを試してみる。</p>

<p>KotlinといえばAndroidStudioでAndroidアプリケーションをプログラミングだと思うが、macOS上で動作するKotlinで書かれたプログラムを動かしたいので、開発環境としてIntelliJ IDEAを使うことにする。IntelliJ IDEAはUltimate EditionとCommunity Editionがあるか、Kotlinプログラミングの学ぶ目的なら、Community Editionで大丈夫だ。JetBrains社のWebサイト (https://www.jetbrains.com/ja-jp/idea/download/#section=mac) からダウンロードしよう。</p>

<img width="264" alt="download.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12540/f2b68e42-a4f0-846e-83ac-90ad12145294.png">

<p>IntelliJ IDEAが入手できたら、Java仮想マシンで動作するプログラムのプロジェクトを生成する。</p>

<img width="367" alt="新規プロジェクト.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12540/e7efd188-0de7-7488-000a-2f30fdc4f8a9.png"><br />
<img width="390" alt="Kotlin_JVM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12540/ef00f1ce-cd3b-8d69-2a1e-6a49e329bd6c.png"><br />
<img width="390" alt="Project name.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12540/ecf53db0-4803-b86a-3c7e-7d8acac425eb.png">

<p>この状態では、Kotlinのソースファイルは作られていないので、srcフォルダを右クリックして、New > Kotlin File/Class を選択して、Kotlinファイルを生成する。</p>

![NewFile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12540/0bfa3e08-bb11-039a-01dc-d5f4d7b0ceaf.png)

<img width="203" alt="Kotlin File.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12540/b0dc4769-6811-c20d-5b8b-20127495542d.png">

<p>そして、hello, worldを印字するコードを書く。</p>

<pre><code>fun main(args: Array<Strubg>) {
    println("hello, world")
}
</code></pre>

<img width="454" alt="run.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12540/3010c822-3c55-9c26-afcc-7cf8e053caaf.png">

<%=image 5, 'run', nil, [907,589]%>

<p>hello, world と印字されている。</p>

【関連情報】
<a href="https://cocoa-kanto.connpass.com/">Cocoa.swift</a><br />
<a href="https://www.facebook.com/groups/cocoa.kanto/">Cocoa勉強会 関東</a><br />
<a href="http://www.bitz.co.jp/weblog/">Cocoa練習帳</a><br />
ubuntu で samba で home ディレクトリを公開する

# ubuntu で samba で home ディレクトリを公開する

ubuntu 19.10 で確認

## samba をインストール

```
sudo apt install -y samba
```

現在のログインユーザーを samba ユーザーとして追加

```
sudo pdbedit -a $USER
```

## firewalld をインストール

```
sudo apt install -y firewalld
```

## firewall で samba を許可

```
sudo firewall-cmd --add-service=samba --permanent
sudo firewall-cmd --reload
```

## smb.conf を編集して home ディレクトリを有効化する

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

```
$ diff smb.conf.orig /etc/samba/smb.conf
175,177c175,177
< ;[homes]
< ;   comment = Home Directories
< ;   browseable = no
---
> [homes]
>    comment = Home Directories
>    browseable = no
181c181
< ;   read only = yes
---
>    read only = no 
196c196,197
< ;   valid users = %S
---
>    valid users = %S
>    users = %S
```

## 設定ファイルを反映

```
sudo systemctl restart  smbd nmbd
```

## 再起動後に自動的に samba が起動するように設定

```
sudo systemctl enable   smbd nmbd
```

## (オプション) mDNS をインストールして `ホスト名.local` でアクセスできるようにする

`ホスト名` は linux のホスト名に読み替えてください。

※ 関連記事 [ubuntu での mDNS(=multicast DNS) の有効化方法](https://qiita.com/m-tmatma/items/7668afea91aff4fbfa85)

### avahi-daemon をインストール

```
sudo apt install -y avahi-daemon
```

### mDNS を許可する

```
sudo firewall-cmd --add-service=mdns  --permanent
sudo firewall-cmd --reload
```

## アクセス方法

`\\xxx.xxx.xxx.xxx\username` または `ホスト名.local\username` でアクセスできる。
【micro:bit 2019】micro:bit で BLE ＋ UART による文字列の送受信（29記事目）

この記事は 12/30 に執筆して、後から 「[micro:bit Advent Calendar 2019 - Qiita](https://qiita.com/advent-calendar/2019/microbit)」の 12日目 へと登録した記事です。

今年のアドベントカレンダー用に書いた記事の 29記事目で、micro:bit Advent Calendar に登録した記事としては 10記事目になります。

## はじめに

micro:bit で BLE ＋ UART を使うために調査や通信テストを試した話の記事です。

## 公式の情報を見てみる

### デバイスの準備

micro:bit の BLE通信周りの情報をググっていてでてきた、以下のページを見てみます。

●micro:bit Bluetooth Low Energy serial UART : Support
　https://support.microbit.org/support/solutions/articles/19000062330-using-the-micro-bit-bluetooth-low-energy-uart-serial-over-bluetooth-

ページ内を読み進めて行くと、[サンプルプログラムへのリンク](https://makecode.microbit.org/_iTvAi1DUw2kg)がありました。
（※「Here is an example program that uses the uart.」と書かれた部分です）

サンプルを参照し、以下のようなプログラムを準備しました。
<img width="459" alt="Microsoft_MakeCode_for_micro_bit_BLE_UART_MC.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/0cb60591-321f-d016-c3f5-91ae76f753b4.jpeg">

そして、さらに下へ進むと、以下のような記載がありました。

> This example program can be used with any UART app that follows the Nordic UART protocol, but the example above was tested on Android with [Serial Bluetooth Terminal](https://play.google.com/store/apps/details?id=de.kai_morich.serial_bluetooth_terminal).

上記の micro:bit のプログラムのサンプルは、Nordic UART プロトコルを使ったどんなアプリとも通信できるものの、動作テストは以下の Androidアプリで行った、とのこと。

●Serial Bluetooth Terminal - Google Play のアプリ
　https://play.google.com/store/apps/details?id=de.kai_morich.serial_bluetooth_terminal

<img width="499" alt="Serial_Bluetooth_Terminal_-_Google_Play_のアプリ.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/7c68adb2-725c-2940-de26-6a9bd3e8500e.jpeg">

こちらを実際に試してみます。

### 端末を BLE接続

micro:bit は上記のプログラムを書き込んでおくだけで、とりあえず OK です。

そして、上記の Androidアプリがインストールされた端末を準備します。
ここから Androidアプリを以下の手順で操作していきます。
![図1-A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/f2efe303-4877-6005-dcc7-2bdfae82afe3.png)
![図1-B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/0ba7fc27-3b23-9d48-f3d6-958e5b172e13.png)
上記の手順4）の「※」の部分で位置情報利用の許可を求めるダイアログが表示された場合、許可するようにしてください。詳細は省きますが、これは BLE利用のために必要となります。

上記で、端末が無線接続された状態になりました。

### 文字列の送受信を試す

以下が、実際に動作させた際の様子です。
最初は、スマホアプリから「ble」という文字列を送信しており、micro:bit側は受信した文字列を LED上に表示しています。
またその後の動作は、micro:bit側で Aボタンを押すと、「BLE UART!」という文字列がスマホアプリへ送信される、というものです。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">micro:bit で BLE での UART 、<br>Androidアプリとの間で文字列の送受信をさせた時の動画。 <a href="https://t.co/78g95Y4yl5">pic.twitter.com/78g95Y4yl5</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1211647242840367105?ref_src=twsrc%5Etfw">December 30, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

想定通りの挙動を確認できました。

## おわりに

今回、参照したページから 2つほど技術面の詳細情報が書かれたと思われるページへのリンクがあｒり、それらは別途、見てみようと思います。
PHP 逆ポーランド記法

## 逆ポーランド記法とは
- 被演算子の後ろに演算子を表記する演算記法。
- 後置記法（Reverse Polish Notation, RPN）という。
- 10+20  →  10 20 +

## 主な手順
- 式を一つ一つ分割し、演算子以外であればスタックに積む(PUSH)。
- 演算子であればスタックから数字を取り出す(POP)。
- 演算結果をスタックに積む。

```php
<?php
function calcRPN($str)
{
    // 式を空白文字でトークンに分割する
    $tokens = preg_split('#\s+#', trim($str));
    $stack = []; // スタックを準備
    foreach ($tokens as $t) {
        // 数値
        if (preg_match('#^[0-9\.]+$#', $t)) {
            $stack[] = floatval($t);
            continue;
        }
        // 四則演算
        $b = array_pop($stack); //スタックの末尾から要素を取り除く
        $a = array_pop($stack);
        switch ($t) {
            case '+':
                $c = ($a + $b);
                break;
            case '-':
                $c = ($a - $b);
                break;
            case '*':
                $c = ($a * $b);
                break;
            case '/':
                $c = ($a / $b);
                break;
            case '%':
                $c = ($a % $b);
                break;
            default:
                return "error";
        }
        $stack[] = $c; //演算結果をスタック末尾に入れる
    }
    return array_pop($stack);
}

$str = '10 20 30 * + 40 - 50 +';
echo calcRPN($str); //620
```
リーマンサット・プロジェクト　新春アドベントカレンダー2020

趣味で宇宙開発を行う団体「[リーマンサット・プロジェクト](https://www.rymansat.com)」がお送りする新春アドベントカレンダーです。
12月のアドカレは記事が埋もれちゃってねぇ、ということで1月にやります。

こちらはそのインデックス記事です。

・人工衛星や宇宙に関する投稿が出てくるかは未知数です。（追記：結構あります）
・リーマンということで平日だけの投稿になります。

| 日付 | 投稿者 | タイトル |
|:--:|:--|:------------------|
| 1/6(月) | @rsp-dgkz | [またしてもショートケーキを作った話](https://qiita.com/rsp-dgkz/items/83268377f8309ddb10f3) |
| 1/7(火) | @hokke_mirin | [LTのススメ](https://qiita.com/hokke_mirin/items/d6020e10078e3640c95d) |
| 1/8(水) | @mepsteindrive | [初心者エンジニアがRSP-01ソフト開発に参戦した結果: 学びと所感](https://qiita.com/mepsteindrive/items/202b57175ad6e8dfca6c) |
| 1/9(木) | @Gan0803 | [第一回RSP杯チキンレース　参戦レポート](https://qiita.com/Gan0803/items/94d1f106268a3408874c#_reference-ec29fc01f380fde469c7) |
| 1/10(金) | @yohachi | [開発環境の１つであるVSCodeの開発環境についてチラ見してみる](https://qiita.com/yohachi/items/c4e142544ff3da02921a) |
| 1/14(火) | @KingBritain | [航空機の流体力学（２次元翼のポテンシャル解法）](https://qiita.com/KingBritain/items/9b238ce9be7ad5212a5a) |
| 1/15(水) | @prestissimo2020 | [趣味の宇宙開発の広報のおしごと](https://qiita.com/prestissimo2020/items/8ce47bd5461ce025abcb) |
| 1/16(木) | @kohei0302 | [BluePillのmbed VSCode開発環境を構築してみた](https://qiita.com/kohei0302/items/6aa927907fe868ef0b50) |
| 1/17(金) | @ytakuro0926 | [C# & Unityで小型衛星姿勢制御ツールを作ってみた①](https://qiita.com/ytakuro0926/items/f50990c0eeb27c0f6649) |
| 1/20(月) | @OzoraKobo | [RSP-00「激レア」開発記 制作の軌跡](https://qiita.com/OzoraKobo/items/e87131a29ad26166f75f) |
| 1/21(火) | @Ushinji | [バーチャル地球儀上で国際宇宙ステーションの現在位置が分かるアプリの開発](https://qiita.com/Ushinji/items/76d4901658bce767df36#_reference-abcd1c6c26a2cd6afe13) |
| 1/22(水) | @ukisoft | [社外の開発コミュニティに参加してみての感想](https://qiita.com/ukisoft/items/f8c958838fb7563c6130) |
| 1/23(木) | @akatuki97 | [太陽系の運動をシミュレーションしてみる](https://qiita.com/akatuki97/items/e2b7cf221a360a2f6324) |
| 1/24(金) | @kentani | [ラズパイ使って、外からでもテレビを消せる様にしてやる！](https://qiita.com/kentani/items/e19927030c1b1da05196) |
| 1/27(月) | @rhiro | [PlantUMLを使った宇宙服のモデリング](https://qiita.com/rhiro/items/df6d04b7a953e14b1064) |
| 1/28(火) | @KaitosLab | [エンジニアでない私が「技術広報」をたちあげてみたワケとアウトリーチ](https://qiita.com/KaitosLab/items/f63642766507b8b6791b) |
| 1/29(水) | @lemonade787 | [オワコンからの脱出-Wordpressでオウンドメディア作成](https://qiita.com/lemonade787/items/18b56b4379e1e8e21c63) |

リーマンサット・プロジェクトは「普通の人が集まって宇宙開発しよう」を合言葉に活動をしている民間団体です。
他では経験できない「宇宙開発プロジェクト」に誰もが携わることができます。
興味を持たれた方はこちら [https://www.rymansat.com/join](https://www.rymansat.com/join) からお気軽にどうぞ。
JupyterNotebookでの「No module named '〇〇'」エラーの対処法｜!pipでインストールしよう！

JupyterNotebook初心者向けの記事です。
※記事内のミスがありましたら、コメントにてお教えください。

##事象：No module named 'pandas'のようなエラーが発生
```python
import pandas as pd
```
のようなコードを実行し、

```python
ModuleNotFoundError     Traceback (most recent call last)
<ipython-input-23-7dd3504c366f> in <module>
----> 1 import pandas as pd

ModuleNotFoundError: No module named 'pandas'
```
のエラーが発生したとき。

##原因：モジュールがjupyternotebook上にインストールされていない
実行しようとしていたモジュール（numpyやpandasなど）が、jupyternotebook上でインストールされていない可能性があります。
※terminal上や、その他IDEでインストールしていても、jupyternotebook上でモジュールを動かしたいときは、別途インストールが必要です。

##対処法：!pip installでインストールし直し

```python

!pip install pandas
```
``!pip``というコマンドを使って、モジュールをインストールし直しましょう。「!」を先頭につけることで、jupyternotebook上でも、システムコマンドを実行できます。

##結果：Successfully installed 〇〇と出ていれば成功

```python
Collecting numpy
Downloading https://files.pythonhosted.org/packages/7c/cd/5243645399c09bb5081e8d2847583f7a6b7cca55eb096a880eda0b602d4d/numpy-1.18.0-cp36-cp36m-macosx_10_9_x86_64.whl (15.2MB)
     |████████████████████████████████| 15.2MB 48kB/s eta 0:00:016
Installing collected packages: numpy
Successfully installed numpy-1.18.0 
```
このようにインストールが完了すれば成功です。

<img width="452" alt="スクリーンショット 2019-12-30 19.51.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559399/b5abc8a6-cd4e-8dcf-7957-a21164b5b975.png">

再インストール後は、↑のように再度使いたいモジュールを`import`を使って呼び出してみてください。
【Rails】NoMethodError (undefined method `current_sign_in_at' for #<User:XXXXXXXXXXXXXX>):

## はじめに
Railsでgem **devise_token_auth**を導入時に発生した内容です。

Eメール認証の確認をしようと、
`http://localhost:3000/api/v1/auth/sign_in`
にPOSTリクエストを出すと以下エラーが発生しました。

```shell:
Started POST "/api/v1/auth/sign_in" for ... Processing by ... DeviseTokenAuth::SessionsController#create as JSON
...

Completed 500 Internal Server Error in 311ms (ActiveRecord: 17.4ms | Allocations: 7912)

NoMethodError (undefined method `current_sign_in_ip' for #<User:...>):
```
※rails serverより抜粋。

このエラーに対して、自分がうまくいった解決法を残します。

## 環境
```yaml
OS: macOS Catalina 10.15.1
Ruby: 2.6.5
Rails: 6.0.2.1
```
## 結論：`user.rb`を修正

### Before

```ruby:app/models/user.rb
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  include DeviseTokenAuth::Concerns::User
end
```
↓
### After

```ruby:app/models/user.rb
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  include DeviseTokenAuth::Concerns::User
end
```
`:trackable`を削除すると無事に通るようになりました。

## おわりに
最後まで読んで頂きありがとうございました:bow_tone1:

どなたかの参考になれば幸いです:relaxed:

## 参考にさせて頂いたサイト（いつもありがとうございます）
- [devise_token_auth/README.md at master · lynndylanhurley/devise_token_auth · GitHub](https://github.com/lynndylanhurley/devise_token_auth/blob/master/docs/usage/README.md)
- [ruby on rails - Devise error: undefined method `current_sign_in_ip’ - Stack Overflow](https://stackoverflow.com/questions/33008187/devise-error-undefined-method-current-sign-in-ip)
【Human Interface Guidelines】Modality機能 和訳

モバイルアプリを設計する上で、モーダルウィンドウ機能についてiOSの推奨を理解しましょう。
「[Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/ios/app-architecture/modality/)」のModalityの章について紹介します。
モバイルアプリは、ユーザーの実現したい目的のために画面が遷移していくことが基本です。
（AppStoreでは特定のアプリ詳細ページに遷移して、アプリをインストールする目的のためなど）
しかしユーザーにメッセージを伝えるために、一時的にユーザーストーリー（想定する画面遷移）から離脱したい場合があります。
その際に、ユーザーに不快感を与えることなく、実装することが求められます。


## 前提

モーダルウィンドウ機能は、ユーザーの現在開いているコンテンツとは独立しており、一時的に表示するためのデザイン手法です。
そのため、モーダルウィンドウを閉じるための明示的なアクションが必要となります。
コンテンツをモーダル表示することにより、以下が実現します。

- ユーザーがモーダル画面で完結するタスクや関連した設定項目に集中することが可能
- ユーザーが重要な情報を確実に受け取り、必要に応じて次の行動を促すことが可能

iOSは利用用途別に「Alerts」、「Activity Views (Share Sheets)」、「Action Sheets」を提供しています。
アプリで独自のモーダルコンテンツを表示するために、iOS13以降では以下の表示スタイルをサポートしています。
![iphone-Modality.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168714/4d211bcf-ad1b-5782-e796-f13f3fc36b9f.png)


### Sheet
シート表示形式は、カードのように前のコンテンツを部分的に覆うように表示されます。
そのため、覆われていない部分は暗くすることで、操作を無効化することを明確にします。
カードで覆われていない部分は、前のコンテンツを表示しておくことで、中断しているタスクを思い出せるようにします。
シートの閉じ方は以下の方法があります。

- 画面の上部から下にスワイプする
- シートのコンテンツが一番上にスクロールされた状態で、任意の箇所から下にスワイプする
- 閉じるボタンを押す
単純なタスクのみを一時的に行わせるために、前の操作内容を想起させるための非没入型コンテンツ表示に適しています。


### Full Screen
全画面表示形式は画面全体を覆います。
前のコンテンツが完全に覆われてしまっているため、意識を散漫させずたり、資格的な混乱を最小限に抑えます。
ユーザーはボタンをタップすることでモーダル画面を閉じることができます。
ビデオ、写真やカメラなどの没入型コンテンツや、資料や写真の編集などの複雑な操作が必要な場合に適しています。


## 1. モーダル機能を適切に使用する
現在実行しているタスクとは異なるタスクを、ユーザーに意識を集中させるためにモーダル機能を使用します。
モーダル機能はユーザーの現在のタスクを無理やり離脱させて、表示する必要があるため、適切な使用用途で用いることが不可欠です。

## 2. 必須情報を提供するためのアラート機能
通常、何かが間違っているためにアラートが表示されます。
アラートはユーザーのタスクを中断するため、閉じるための手段を明確にして、モーダル表示が正当だとユーザーに感じさせることが重要です。

## 3. モーダル機能は、単純、早く、少なく
アプリは一つの目標を達成するために設計されます。
モーダル画面上に別のアプリを作成しないでください。
モーダル機能が複雑であると、前の中断しているタスクが何であったか見失う可能性があります。
ビューが階層的に複数重なりあっている場合は特に注意が必要です。
モーダル画面上にサブビューがある場合は、タスクを完了するまでの手順を明確化してください。
タスクを完了する以外の目的で「完了」ボタンを使用してはいけません。

## 4. モーダル画面には必ず「閉じる」ボタンを用意する
「完了」や「キャンセル」ボタンも同義です。
ボタンを表示することで、ユーザーの操作性が向上されたり、スワイプなどの画面を閉じる操作の代替として提供ができます。

## 5. 必要に応じて、モーダル画面を閉じる前に確認を表示する
モーダル画面上のデータの損失を回避することができます。
スワイプ操作や閉じるボタンのタップ操作に関わらず、操作によってユーザーの生成したコンテンツが失われる可能性がある場合は、状況の説明と解決方法を提示するためのシートを提示することを推奨します。
（写真編集後保存されていないまま、画面を閉じようとした場合など）

## 6. FullScreenモーダル画面の上にSheetモーダル画面を表示しない
ポップオーバー（FullScreen）画面内にカード（Sheet）画面を表示することは可能ですが、上に重ねて表示はしてはいけません。（アラートの場合を除く）
ポップオーバー画面で操作中に、カード画面の表示が必要な場合は、一度ポップオーバー画面を閉じるようにしてください。

## 7. モーダル画面の内容が分かるタイトルを表示する
モーダル画面が表示されると、前のコンテンツから切り替わるため、新しいコンテンツを明確にすることを推奨します。
タスク内容をしっかり説明するか、案内を画面内に提供するなどで対応します。

## 8. モーダル画面の外観をアプリと調整する
例えば、モーダル画面にナビゲーションバーが含まれる場合は、アプリのナビゲーションバーと同じデザインを使用する必要があります。

## 9. 表示形式を適切に選択する
アプリ全体の遷移方式を考慮し、適切な画面切り替え方式を使用します。
デフォルトの切り替え方式は、モーダル画面が下部から上下にスライドし、閉じた時に元に戻ります。
アプリ全体と一貫した遷移方式を採用するようにしましょう。


## まとめ
画面遷移はユーザーの予期しない場合に、かなりストレスに感じてしまいます。
モーダル画面上でPush遷移をさせたり、モーダル画面上に更にモーダル画面が表示されるなど、不適切な利用は避けて、UXを向上させるために適切に利用することを心がけてみてください。
「リファクタリング 第2版」Swiftでコーディング その5

# 11頁 第1章 play変数の削除 「問い合わせによる一時変数の置き換え(p.185)」

## Swift版 main.swift

データ生成、結果表示付き。

```swift
import Foundation

makeData()

func playFor(aPerformance:Performance, plays:Dictionary<String, Play>) -> Play {
    return plays[aPerformance.playID]!
}

func statement(invoice:Invoice, plays:Dictionary<String, Play>) -> String {
    var volumeCredits = 0
    var totalAmount = 0
    var result = "Statement for \(invoice.customer)\n"
    let format = NumberFormatter()
    format.numberStyle = .currency
    format.locale = Locale(identifier: "en_US")

    for perf in invoice.performances {
        let play = playFor(aPerformance: perf, plays: plays)
        let thisAcmount = amountFor(aPerformance: perf, play: play)

        volumeCredits += max(perf.audience - 30, 0)
        if "comedy" == play.type {
            volumeCredits += Int(perf.audience / 5)
        }
        result += "  \(play.name): " + format.string(from: NSNumber(value: thisAcmount / 100))! + " (\(perf.audience) seats)\n"
        totalAmount += thisAcmount
    }
    result += "Amount owed is " + format.string(from: NSNumber(value: totalAmount / 100))! + "\n"
    result += "You earned \(volumeCredits) credits\n"
    return result
}

func amountFor(aPerformance:Performance, play:Play) -> Int {
    var result = 0

    switch play.type {
    case "tragedy":
        result = 40000
        if aPerformance.audience > 30 {
            result += 1000 * (aPerformance.audience - 30)
        }
    case "comedy":
        result = 30000
        if aPerformance.audience > 20 {
            result += 10000 + 500 * (aPerformance.audience - 20)
        }
        result += 300 * aPerformance.audience
    default:
        print("error")
    }
    return result
}
 
let result = statement(invoice: invoices[0], plays: plays)
print(result)
```
「リファクタリング 第2版」Swiftでコーディング その4

# 10頁 第1章 amountFor関数

## Swift版 main.swift

データ生成、結果表示付き。

```swift
import Foundation

makeData()
 
func statement(invoice:Invoice, plays:Dictionary<String, Play>) -> String {
    var volumeCredits = 0
    var totalAmount = 0
    var result = "Statement for \(invoice.customer)\n"
    let format = NumberFormatter()
    format.numberStyle = .currency
    format.locale = Locale(identifier: "en_US")

    for perf in invoice.performances {
        let play = plays[perf.playID]!
        let thisAcmount = amountFor(aPerformance: perf, play: play)

        volumeCredits += max(perf.audience - 30, 0)
        if "comedy" == play.type {
            volumeCredits += Int(perf.audience / 5)
        }
        result += "  \(play.name): " + format.string(from: NSNumber(value: thisAcmount / 100))! + " (\(perf.audience) seats)\n"
        totalAmount += thisAcmount
    }
    result += "Amount owed is " + format.string(from: NSNumber(value: totalAmount / 100))! + "\n"
    result += "You earned \(volumeCredits) credits\n"
    return result
}

func amountFor(aPerformance:Performance, play:Play) -> Int {
    var result = 0

    switch play.type {
    case "tragedy":
        result = 40000
        if aPerformance.audience > 30 {
            result += 1000 * (aPerformance.audience - 30)
        }
    case "comedy":
        result = 30000
        if aPerformance.audience > 20 {
            result += 10000 + 500 * (aPerformance.audience - 20)
        }
        result += 300 * aPerformance.audience
    default:
        print("error")
    }
    return result
}
 
let result = statement(invoice: invoices[0], plays: plays)
print(result)
```
VSCodeのvueファイルでEmmetを簡単に使えるようにする方法

<h2>VSCodeのvueファイルでEmmetを簡単に使えるようにする方法</h2>
VSCodeのvueファイルでは\<template>タグ内にHTML、\<style>タグ内にcssを記述しますが、初期状態だとEmmetが使えないです。

これが意外と不便だったのですが、拡張機能の【Vetur】を使えばインストールするだけで、vueファイルでもEmmetが使えるようになります。

![vuter.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/b660962c-9a24-1633-9325-3334efe17e97.png)
Capistranoでの自動デプロイでエラーが起きた際の対処方法(migration error)

## この記事について
　この記事では、自身がRailsで開発しているアプリをCapistranoでデプロイをしようとした時にエラーが発生し、解決するまでに試した作業を書いています。
　同様のエラーが起きた際に自分が読み返すために書いていますが、他の方の参考にもなれば嬉しいです。

### エラーが起こった時の状況
　Capistranoでデプロイの流れを自動化しており、ある日デプロイをしようとしたところ、`deploy:migrating`実行時にエラーが発生し、デプロイができませんでした。
　ローカル環境では動作に問題がなかったため、サーバー環境に問題があると考えました。

### エラー解決までに行った作業

- AWSサービスの再起動
- unicornの再起動
- nginxの再起動
- MySQLの再起動

　こうして書いてみると、ひたすら再起動しているだけのような気がしてきました。

### 1.AWSサービスの再起動

　amazonコンソールからサインインし、EC2インスタンスの管理画面を開きます。
　該当するアプリが選択された状態で、「アクション→インスタンスの状態→停止」、「アクション→インスタンスの状態→開始」の順で行います。
　再起動を選択しても良さそうですが、学習のために開発中のアプリであることと、再起動で上手く行かなかった時に停止→開始とやり直すのが面倒だったため、今回は最初から停止→開始の作業を行いました。
　他のアプリを開発中にも直面しましたが、解決策が分からない時にインスタンスの再起動を行うとあっさり解決することがあったりします。

### 2.unicornの再起動

　以降はコンソールからサーバーにログインした上で作業を行います。`cd /var/www/アプリ名`などを実行し、アプリが保存されているフォルダに移動してから作業してください。

```ruby:unicornの停止
ps aux | grep unicorn  # 起動中のunicornプロセスを確認

# 起動中のunicorn master -c ...がある場合、停止させる
kill 0000 #上記で確認したプロセス番号を入力
```

```ruby:unicornの起動
RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
```

### 3.nginxの再起動
```ruby:nginxの再起動
# nginxの停止
sudo service nginx stop

# nginxの開始
sudo service nginx start

# nginxの状況確認
sudo service nginx status
# -> nginx (pid 0000) is running...
```

### 4.MySQLの再起動
```ruby:MySQLの再起動
sudo service mysqld restart
# nginxと同様の作業でも再起動は可能
```

### 結果
　以上の作業を行うことで、無事にデプロイが行えるようになりました。
　上の作業を全て連続して行ったため、具体的にどの部分が原因でデプロイできなかったのかまでは分かりませんでした。ですが原因を追求するつもりもありませんでしたし、問題があった時の再起動は不都合がない限り全て行って差し支えないと考えます。
bashでhealth check

# bashでhealth checkのめも

php-fpmとcrondを監視します

```bash
#!/bin/bash

while true
  do
      PHP=`sudo ps ax | grep 'php-fpm: master' | grep -v grep | wc -l`
      CROND=`sudo ps ax | grep 'crond' | grep -v grep | wc -l`
      if [ $PHP = 1  ] && [ $CROND = 1  ] ; then
          echo "HTTP/1.0 200 Ok"  | nc -l 8080
      else
          echo "HTTP/1.0 500 NG"  | nc -l 8080
      fi
      [ $? != 0 ] && break
  done

```
【python】outlookでメール送信

# はじめに
仕事でexcelでメール作成マクロ作ったけど
「excelだと起動わずらわしいし、excelありきになるからなんかやだな…」
と思い、業務外ってことでリラックスした気持ちで探したら
神がかり的にわかりやすいサイトが見つかったので作ってみた。

# 参考サイト
https://towel-memo.com/python/email_python/

```python:
#ライブラリ
import win32com.client

#Outlookのオブジェクト設定
outlook = win32com.client.Dispatch('Outlook.Application')
mymail = outlook.CreateItem(0)

#署名
sign = '''
株式会社 ホゲホゲドットコム
世界のナベヒロ
'''


#メールの設定
mymail.BodyFormat = 1
mymail.To = 'foo@hoge.co.jp; bar@hoge.co.jp'
mymail.cc = 'foo@hoge.com'
mymail.Bcc = 'bar@hoge.com'
mymail.Subject = '件名'
mymail.Body = '''各位
お疲れ様です。

以上、よろしくお願いいたします。
'''+ '\n' +sign

path = r'C:\\Users\watya\Desktop\hogehoge.txt' # 添付ファイルは絶対パスで指定
mymail.Attachments.Add (path)

#出来上がったメール確認
mymail.Display(True)
#確認せず送信する場合は、mymail.Display(True)を消して、下記コードを使用する
#mymail.Send()
```

### 実行結果
　mymail.Display(True)
で実行したので、メールは作成されたけど
送信まではされず下書き状態でストップしてくれた。やさしい。。。
これはテンプレ通りのメールを作成するのに便利ですね。

しかもfromはログイン時のOutlookアドレスを使用してくれるので
プログラム作成時に意識する必要もないのでとっても楽。
これは便利！
OpenCVで指定ディレクトリの画像を一覧表示する

```Python
import cv2
import math
import matplotlib.pyplot as plt
%matplotlib inline

# 指定パスのファイルを一括取得
import glob
import re

def show_all_img(img_path, size):
  #img_path:画像の格納されたパスを指定

  #サイズ
  plt.figure(figsize=size)

  #拡張子がpng, jpgのファイルを抽出
  img_file_names = [p for p in glob.glob('{}/**'.format(img_path), recursive=True)
                    if re.search('.*(.png|.jpg)', p)]

  img_dic = {}
  for i in img_file_names:
    img_dic[i] = cv2.cvtColor(cv2.imread(i), cv2.COLOR_BGR2RGB)

  rows = math.ceil(math.sqrt(img_file_num))
  cols = rows

  for i,k in enumerate(img_dic.keys()): 
    plt.subplot(rows,cols,i+1)
    plt.title(k)
    plt.imshow(img_dic[k])

#####
img_path = "./data"
show_all_img(img_path, (15, 10))


```
nuxtでtwitterシェアボタン設置

# やりたいこと

* nuxtでtwitterシェアボタン設置
* twitterタグをその投稿のカテゴリーごとに出し分け

# 具体的な仕様

* URLをとってきてdataに格納
* URLで下記を設定
    * ハッシュタグをそのページのカテゴリーに
    * URLを後ろにつける
* URLの生成はcomputedで行って渡す
    * script内のほうがテンプレートリテラルなど使えるので

# twitterの仕様

twitterのパラメーター
https://developer.twitter.com/en/docs/twitter-for-websites/tweet-button/overview

* ?でパラメーターを追加して複数の場合、&でつなぐ
* 値は''などで囲まなくてもok

# 参考

twitterのボタンをオプション選択すると自動生成してくれるページ
https://publish.twitter.com/?buttonType=TweetButton&widget=Button


https://qiita.com/shiroprodb/items/556b245a07c0cfb51847
dependency-checkでgrettyに含まれる脆弱性をスキップする方法

# 前提 - バージョン

```gradle:build.gradle.kts
plugins {
  id("org.owasp.dependencycheck") version "5.2.4"

  id("org.gretty") version "3.0.1"
}
```

# 説明
## dependency-checkとは
依存関係に脆弱性がないか調べてくれるツール
owaspのjeremylongさんがつくっている？
https://jeremylong.github.io/DependencyCheck/

## grettyとは
IDEの機能を使わなくても、gradleタスクでtomcatやjettyなどのアプリケーションサーバーを起動できる
gradleプラグイン
https://plugins.gradle.org/plugin/org.gretty

# なぜしようとおもったか

## grettyいれたらたくさん脆弱性があった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319886/d6b02da2-24d7-c278-7277-01a2de26cf80.png)

とても悲しい・・・
見つかった脆弱性は246個とのこと。

grettyはローカル環境だけで使っていて、
開発環境や本番環境で製品となる依存関係には含まれないので、
この脆弱性は見たくない。

# 方法

## １．grettyのconfigurationをしらべる

下記のようなタスクを用意・実行して、configurationの一覧を出力する

```gradle:build.gradle.kts
tasks.register("showConfiguration") {
    configurations.stream().forEach {
        println(it.name)
    }
}
```

https://stackoverflow.com/questions/41173616/how-can-i-get-a-list-of-all-configurations-for-a-gradle-project

出力した結果、「gretty」から始まるconfigurationがあるので、
コピーしておく


## ２．dependencyCheckのskipConfigurationsに１．を入れる

gretty version 3.0.1の場合だと以下のようになりました。
前のバージョンだと、「tomcat8」等追加になるかと思います

kotlin DSL

```gradle:build.gradle.kts
dependencyCheck {
  skipConfigurations = listOf(
      "gretty",
      "grettyNoSpringBoot",
      "grettyProductRuntime",
      "grettyProvidedCompile",
      "grettyRunnerJetty7",
      "grettyRunnerJetty8",
      "grettyRunnerJetty9",
      "grettyRunnerJetty93",
      "grettyRunnerJetty94",
      "grettyRunnerTomcat85",
      "grettyRunnerTomcat9",
      "grettySpringLoaded",
      "grettyStarter"
  )
}
```

gradle

```gradle:build.gradle
dependencyCheck {
  skipConfigurations = [
      "gretty",
      "grettyNoSpringBoot",
      "grettyProductRuntime",
      "grettyProvidedCompile",
      "grettyRunnerJetty7",
      "grettyRunnerJetty8",
      "grettyRunnerJetty9",
      "grettyRunnerJetty93",
      "grettyRunnerJetty94",
      "grettyRunnerTomcat85",
      "grettyRunnerTomcat9",
      "grettySpringLoaded",
      "grettyStarter"
  ]
}
```

https://jeremylong.github.io/DependencyCheck/dependency-check-gradle/configuration.html


# 結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319886/db920a88-7119-207c-daf5-b337e9a377fe.png)

見つかった脆弱性は0になりました:relaxed:


# まとめ
※gretty version 3.0.1の場合。
  前のバージョンだと、「tomcat8」等追加になるかと思います

```gradle:build.gradle.kts
dependencyCheck {
  skipConfigurations = listOf(
      "gretty",
      "grettyNoSpringBoot",
      "grettyProductRuntime",
      "grettyProvidedCompile",
      "grettyRunnerJetty7",
      "grettyRunnerJetty8",
      "grettyRunnerJetty9",
      "grettyRunnerJetty93",
      "grettyRunnerJetty94",
      "grettyRunnerTomcat85",
      "grettyRunnerTomcat9",
      "grettySpringLoaded",
      "grettyStarter"
  )
}
```
git のauthor と committer を 変更

## ブログの動機
　うっかりして、会社のPCでプライベートのGitにコミットしてしまうと、`author`や`commiter`が会社のものになってしまいます！:frowning2::frowning2:
その度に`author`や`commiter`を修正するのですが、肝心のコマンドが直ぐに思い付かずググっていました。。。もう二度とググりたくないと誓い、自分用のメモとしてまとめます。


## gitコミットログを確認
```bash
$ git log --pretty=full
commit 186543f9bece44383ab973dc0253946bf09b159f
Author: 会社の <会社の@example.com>
Commit: 会社の <会社の@example.com>

    commit message2

commit 25ddf087cfe17f7f71c1fd273eed931b39c71a4b
Author: 自分の <自分の@example.com>
Commit: 自分の <自分の@example.com>

    commit message1
```

## authorのみ変更
`git rebase -i <修正したいコミットの一個前のコミットハッシュ>`
例えば、`commit message2`の`author`を変更するなら

```bash
１． git rebase -i 25ddf087cfe17f7f71c1fd273eed931b39c71a4b

で修正したい対象のpick -> edit

２． git commit --amend --author="自分の<自分の@example.com>"

３． git rebase --continue
```

## authorとcommitter両方変更する

### git configを修正
configを正しい状態に設定する。
local configを確認する方法：
`git config --local --list`

```bash
$ git config --local user.name 自分の
$ git config --local user.email 自分の@example.com
```

### ログを修正

```bash
1.git rebase -i <commit hash>

2.git commit --amend --reset-author これを実行することで、一発でcommiterとauthorが修正できる

3.git rebase --continue

4.git log --pretty=full で正しく修正されたのを確認
```

これで正しく修正できた:v:

##　補足

一番最初のコミットを修正する際は、
`git rebase -i --root <commit hash>`
でやります。
OpenStack-Novaでマイグレーション並列実行数の設定変更

# はじめに

デフォルト状態のNovaでは、マイグレーションは1台ずつしか実行されない。
例えば、host-evacutionで特定コンピュートノードから全てのインスタンスをマイグレーションさせようとしても、一台ずつ実行なので非常に長い時間がかかってしまう。それこそ、NWやStorageの能力的にまだまだ余力があるのだとしたら、これはとても非効率。
というわけで、Novaの設定変更で何とかする。

# 環境

QueensベースのRedHat OpenStack Platform v13で動作確認。

# 設定変更

`/etc/nova/nova.conf`の`max_concurrent_live_migrations`を変更する。デフォルトは`1`に設定されている。そのせいでマイグレーションは1台ずつ実行される。

```/etc/nova/nova.conf
- max_concurrent_live_migrations=1
+ max_concurrent_live_migrations=3
```

そしてnovaのプロセスを再起動させればOK
この場合、3並列でマイグレーションがされることになる。ハードウェアの能力にもよるだろうが、50台のインスタンスを10分程度でマイグレーションできたりするので、非常に高速化される。

RHOSP v13の場合はコンピュートノードの`/var/lib/config-data/puppet-generated/nova_libvirt/etc/nova/nova.conf`を変更してnova_computeコンテナを再起動させればOK
当然、オーバークラウドの再デプロイやアップデートをかけると設定が元に戻ってしまうので、環境ファイル側でもオーバーライドするように構成する必要がある。

# 使用帯域幅の調整

マイグレーション中にNICのトラフィックを見て頂ければよく分かるが、マイグレーションはかなりNW帯域を消費する。これもインスタンスの稼働状態などにもよるので、一概には言えないが、3並列で実行して4~8Gbps程度はコンスタントに使っている。下手すると、10Gbpsに張り付いたりする。

当然ながら、マイグレーションのトラフィックでNWが使い潰されてしまっては、他のトラフィックに影響が出てしまう可能性がある。そんな場合には、nova.confには、`live_migration_bandwidth`という設定もあって、この値を調整すると良い。

デフォルトは、`0`に設定されており、この場合は自動調整されるらしい。が、10GbpsのNW構成だから他トラフィックに影響でないように8Gbps抑えて欲しいな♪なんて人間の希望をエスパーしてくれるような機能ではない。個人的には、この値も調整した方が良いと考えている。

live_migration_bandwidthは`MiB(メビバイト)`で記述する必要がある。メガビットでもメガバイトでもない。"メビバイト 変換"とググるとGoogle大先生の計算ツールが表示されるので、それを使うのが便利。

```/etc/nova/nova.conf
- live_migration_bandwidth=0
+ live_migration_bandwidth=1073
```

10Gbps構成ならば、他トラフィック用に1Gbpsぐらい空けておけば良いのではないだろうか。もちろんこれはそれぞれの環境に合わせて調整して欲しい。

# あとがき

今までずっとデフォルト状態で運用していて、マイグレーションの待ち時間が長くて苦労していた。今回、記事にした2点を調整しただけで劇的に高速化されたので、非常に満足している。

# 参考

* [https://docs.openstack.org/queens/config-reference/compute/config-options.html](https://docs.openstack.org/ocata/config-reference/compute/config-options.html)
* [https://docs.openstack.org/nova/pike/admin/configuring-migrations.html](https://docs.openstack.org/nova/pike/admin/configuring-migrations.html)
多引数で多返値な関数が利用できるLua言語のお話

# 1. はじめに
某所で、「関数定義で複数の引数が使えるのに返値は1個に限定される言語が多いのはなんで？（意訳）」という議論が起きていたようですね。たしかにC言語など関数の返値が1つな言語は多いようです。

でも例外はありますよね。私の知る限り、Go、Lisp、Ruby、Luaあたりは一度に複数の返値を返す関数が定義できます。

今回はその中でも、（私が大好きな）Lua言語に注目して多値の利用について雑談をしていきましょう。

「エクスキューズ」
Lua言語は、ソフトウェア内の組み込み用途で作られた軽量高速な言語であり、シンプルであることを信条としている言語ですのでご承知ください。変数の型？引数の個数？　あーあー聞こえない。

# 2. 多重代入って素敵
## 2.1 多引数・多返値な関数
Lua言語では以下のように多引数・多返値な関数が定義できます。

```lua
function swap(a,b)
  return b,a
end

print(swap(1,10))

-----
結果
10 1
```

print()関数は複数引数を受けとる関数ですのでswap()関数が出した2つの返値をそのまま画面表示してくれます。

しかし、二つの返値をいったん別の変数に保持したいこともあるわけで、その場合は次のような「多重代入」が使えます。便利ですね。

```lua
local x, y = swap(1,10)
print("1st: ", x)
print("2nd: ", y)
-----
結果
1st: 10
2nd: 1
```

## 2.2 Luaはうまくやってくれます
なお以下のように、Lua言語では返値の個数と受け取り手の変数の個数が違っていても、なんとなくうまくやりくりしてくれる仕様になっています。

```lua
-- 変数1個 ← 返値2個
local v0 = swap(1,10)
print("v0: ", v0)

-- 変数3個 ← 返値2個
local v1, v2, v3 = swap(1,10)
print("v1: ", v1)
print("v2: ", v2)
print("v3: ", v3)
-----
結果
v0: 10
v1: 10
v2: 1
v3: nil
```

つまり、多重代入で受け取り変数1個で返値2個の場合、変数には一番目の返値のみを代入し、二番目以降は無視します。逆に、受け取り側の変数の方が多ければ、先頭の変数から返値を詰めていき、余った変数は触らずそのままnilとなります。

とはいえ、返値を無視する（握り潰す）ときは、それを明示的にアピールするために次のような表記（"_"、アンダーバー）をするのが一般的です。

```lua
local v0, _ = swap(1,10)
print("v0: ", v0)
```

# 3. 関数の入れ子もできる
## 3.1 関数から関数へ直接代入
また、以下のように関数が返す複数の返値をそのまま他の関数の引数として叩き込むことも可能です。

```lua
function swap(a,b)
  return b, a
end

print(swap(swap(1,10)))
-----
1 10
```
swap()は2引数2返値な関数です。一番内側のswap()で処理された返値"10 1"をさらに外側のswap()で処理することで、もとの並び順に戻ったことになります。

複数のバラバラな変数をバラバラなまま処理できるのって便利ですよね。2引数2返値な異なる関数を順番に適用していくことで、Luaでも関数型のプログラミングが可能になります。

え？　「他言語なら構造体使う？」「LuaならTableを使え？」　あーあー、聞こえない。

## 3.2 Luaならうまくやって・・・くれます？
Luaは変数と返値の数があっていなくてもうまくやってくれることは前述しましたが、それでは受け取り側関数の引数と送り側関数の返値の数があっていないときはどういう挙動になるのでしょうか。
以下のような例を考えてみます。

```lua
function plusichi(x)
  return x+1
end

-- 引数1個の関数　←　返値2個の関数
print(plusichi(swap(1,10)))
-----
結果
11
```
これ、型厳密な言語を普段から扱っている人にとってはとても気持ち悪い処理だと思います。

具体的な処理の流れは以下のとおりです。
1. swap()で "10 1" の2つの返値。
2. plusishi()は1引数なので2つの返値のうち先頭"10"のみを受け取って処理。
3. plusichi()により"11"を返す。
4. 画面に"11"を表示する。

ええ、Luaってこういう仕様なんです。仕様だから仕方ない。

なお、次のようなプログラムも何の問題もなく動きます。

```lua
function swap(a,b)
  return b,a
end

print(1+swap(1,10))
-----
結果
11
```

うん、さすがにこれはドン引きです。

でもLuaって次のようなプログラムでも問題なく動くのですから、そういうものだと思いましょう。

```lua
function multi(a,b,c)
  print(a)
  print(b)
  print(c)
end
multi(1)
-----
結果
1
nil
nil
```

# 4. おわりに
Lua言語の関数定義では、C言語とは異なり、複数の返値を持つことができます。

C言語における関数定義時に、「ただ2つの値を返したいだけなのになんで構造体使わないといけないの！めんどくさい！」という不満を持っていた人にとってはうれしい機能ですね。

ただし紹介した通り、Luaは変数・引数の個数が異なっていてもなんとか処理してしまいますので、複雑なプログラムを組む時は、はまらないよう気をつけましょう。特に、2つ程度ならともかく、それ以上大量の変数を一気に扱うならば、LuaのTable（ハッシュテーブル）の方が楽だと思います。

# 追記
Go言語も多返値をもつ関数が定義できますが、Goの関数は定義時に返値の型や個数を記述しなくてはなりません。そのため、Luaのように「うまく」やってくれないので気をつけましょう。
多重代入時には、変数の数（型）と返値の数が同じでなくてはコンパイルエラーです。

このあたり、Lua言語との比較をしながら、まとめてくれる識者はいらっしゃいませんか？
【自作機】ESXi機にローカルストレージを追加する

#2.5インチSSDを勢いで追加する記録
ESXi機は電源通電したままのオンライン作業とする。
接続するSSD: Crucial MX300 750GBモデル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91280/83f009d7-5133-213a-64d9-5f190ede714d.png)

1. SSDを本体に接続する。（電源、SATAポート）

2. vSphere clientからストレージを確認する。
認識はした。データストアはまだ無い状態。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91280/8350ee9c-3233-45bb-30ee-09054a40b639.png)

3. 念のためパーティションテーブルをクリアする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91280/3b4dfbe7-92ed-6b9a-4819-967d1658b512.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91280/376e54f6-8a34-1a0f-3976-59e06e51b0d4.png)

4. 「新しいデータストア」からデータストアを作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91280/911e09ff-a9a6-b6f9-5e84-bd15e438b783.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91280/56d2ce5b-f624-697c-12fe-8e67ebf20011.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91280/ede2f7f3-6d3b-447d-80bb-3afe786c5cb1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91280/a67c7ee2-7683-66c7-c79f-fd2c76fe656b.png)

5. 再度ストレージを確認する。
データストアが作成された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91280/7b63774f-d755-c5aa-af6e-5fe16f9a7e5d.png)

簡単に増設できた。
以上
Coral Dev Boardでどうしようもなくなった場合のリカバリー(Mac使用)


mendel でログインできなくなったり、fastboot でデバイスが認識できなくなったりしたときの対処について。

# 方針

* 概要： SDカードに入れたrecovery.imgでブートしてみます
* 参考というかそのまま引用：
https://coral.ai/docs/dev-board/reflash/#flash-from-u-boot-on-an-sd-card

## 今迄と他に必要なもの
1. micro SDカード
1. micro SDカードを読み書きできるMacもしくは、その付属品
1. イメージ書き込みソフト(balenaEtcherなど)
## DIP SWITCHの設定
DIP SWITCHにて、Boot Moodeを、SD Cardに変更します。1/2/3/4をON/OFF/ON/ONにします。

<img src="https://user-images.githubusercontent.com/315029/71572179-3fa64d80-2b21-11ea-99a9-f9b6b81c78db.png" width="400"/>

## 一応OSなどイメージのダウンロード
```
$ wget https://dl.google.com/coral/mendel/enterprise/mendel-enterprise-day-13.zip
$ unzip mendel-enterprise-day-13.zip
```
こちらのmendel-enterprise-day-13フォルダのツール群を使います。

## recoveryイメージの書きこみ
[balenaEtcher](https://www.balena.io/etcher/)からツールをダウンロードする。
先程のフォルダのrecovery.imgを選択、あとは画面の通りに進むと書き込めます。
![Snip20191230_2](https://user-images.githubusercontent.com/315029/71571816-90b54200-2b1f-11ea-94e3-de28dbba4aea.png)
- MacにSDカードさしても認識しない事があります。ゆっくりでなく勢い良くさすと認識率が上がります。嘘のような本当の話です。
- このままだとブートできないけどいいのか?と言われますが、そのまま進んで良いです。

## SDカードからのブート
順番が重要です

1. USB-Bのシリアルを繋ぎます
1. もはやお馴染となった、screen /dev/cu.SLAB_USBtoUART 115200を実行します。
1. micro SDカードをボードにさします。
1. 続いてUSB-C(パワー)をさします。

そうすると、文字が出てきて u-boot> プロンプトで止まるか、hit any key to stopなどと出て、数秒以内に何か押すと先にすすまずに、u-boot>プロンプトで止められます。

### fastbootの実行
```
$ fastboot 0
```
そして次に、USB-C(Data(OTG))をさしてください。
画面は固まったままですが、それで良いのでそのままほっておいて下さい。

## OSの書き込み
### fastbootの確認
screenを実行したのとは、違うターミナルを開いて以下を実行

```
$ fastboot devices
12345689a012    fastboot
```

みたいな感じで数値が返ってくればOK

### 書き込み実行
```
$ cd mendel-enterpriseday-13
$ bash flash.sh
...
```
しばらく時間がかかって書き込みが終わり、リブートがかかりますが、DIPスイッチがSD Card Boot modeままなので、ちゃんと動くわけではありません。ケーブル群を抜いて、DIPスイッチを元に戻したら終了です。

<img src="https://user-images.githubusercontent.com/315029/71552089-fb3f8280-2a38-11ea-92aa-55f00f180a22.png" width="320"/>

(by 団員H）
【junos】wildcard rangeでコマンドを一気に投入してみる

# はじめに
<バージョン>
Model: vmx
Junos: 18.4R1.8

コードを使わなくてもwildcard rangeを用いてコマンドを一気に投入できます。

# コマンド例
[]内で範囲指定などをするだけなので、コーディング等の知識は不要です。（参考資料[1]）

| 用途| 方法 | 設定例|
|:-----------|:------------|:------------|
| 範囲指定 | -でつなぐ |wildcard range set interfaces lt-0/0/0 unit [1-10] family inet address 192.168.0.1/30 |
| 範囲指定 + 除外 | !で除外範囲を指定 | wildcard range set interfaces lt-0/0/0 unit [1-10,!3-7] family inet address 192.168.0.1/30 |
| 特定の値を指定  | ,でつなぐ | wildcard range set interfaces lt-0/0/0 unit [1,3,5] family inet address 192.168.0.1/30 |
| 等間隔で指定  | /で間隔を指定 | wildcard range set interfaces lt-0/0/0 unit [1-10/2] family inet address 192.168.0.1/30 |

# 注意点
以下のように変数箇所が2か所あると、変数の全パターンが入ります。

```text
test@ip-<address># wildcard range set interfaces lt-0/0/0 unit [1-2] family inet address 192.168.0.[1-2]/32
-
[edit]
test@ip-<address># show | compare
[edit]
+  interfaces {
+      lt-0/0/0 {
+          unit 1 {
+              family inet {
+                  address 192.168.0.1/32;
+                  address 192.168.0.2/32;
+              }
+          }
+          unit 2 {
+              family inet {
+                  address 192.168.0.1/32;
+                  address 192.168.0.2/32;
+              }
+          }
+      }
+  }
```

# 参考資料
[[1]Example: Using the Wildcard Command with the Range Option]
(https://www.juniper.net/documentation/en_US/junos/topics/example/junos-cli-wildcard-range-configuring.html)
PythonのためにVimにALEを導入するときにハマった点

## 追記(2021/05/23)
最近はALEよりCOCのほうが良いらしいです。
COCをご存じでない方は、ぜひ調べられるとよいと思います。
（私は最近まで知りませんでした）

## 環境
Windows 10
Vim
Windows Terminal
dein

## ハマったこと
`vim` + `dein` + `ale`を導入しようとした。
そこで、`ALELint`や`ALEFifx`を実行してみたがソースコードには何の変化もなかった。
`pip install`していて、`black`などはインストールされていた。

3時間ほどかけて見つけた原因は、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183842/f84ef14e-da39-dc70-082f-e9475eb69b1a.png)
でした。
以下のように変更する必要がありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183842/d978775b-cef8-6fe6-e4d3-0e41e4cef5ff.png)

`g:python3_host_prog`が(windowsの)pathのイメージだったので、ディレクトリ指定だと思い込んでいました...
`python.exe`のpathを指定しないといけないというお話でした。

## 参考文献
[ALE(on NeoVim)でPythonコードを楽に整形する](https://qiita.com/lighttiger2505/items/9a36c5b4035dd469134c)
[NeovimでモダンなPython環境を構築する](https://qiita.com/lighttiger2505/items/e0ada17634516c081ee7#ale)
AWS Lambdaのログをtailする

# はじめに

AWSマネジメントコンソールでAWS Lambdaのログを確認するのは面倒だ。
そう思ってググったんだが、当時、それっぽいことをやってる事例を見つけられなかった。

さて、AWS LambdaのログはCloudWatchログに記録され、次のような構造をしてる。

    CloudWatchログでは、個々の記録をイベントと呼んでるようだ。
    一連のイベントをひとまとまりにしたものを、ログストリームと呼んでるようだ。
    ログストリームは関数ごとにまとめられており、それをロググループと呼んでるようだ。

これを踏まえると、tailは次のような流れになる。

    tailしたいロググループを特定する
    while True:
        tailしたいロググループから最も新しいログストリームを見つける
        if 見つけたログストリームの最初の取得だったら:
            ログストリーム内のイベントを最初から取得する
        else:
            ログストリーム内の続きのイベントを取得する
        少し待つ


# Pythonで書いたので

とりあえずboto3のインポートは必要となる。

```Python
#!/usr/bin/python3

import boto3
```

# CloudWatch Logsのクライアントを作成する

```Python
# 最も単純な場合
aws_cwl_client = boto3.client('logs')
# プロファイル指定が必要ある場合
aws_cwl_client = boto3.session.Session(
    profile_name='プロファイル名').client('logs')
# プロファイルに加えてリージョン指定が必要ある場合
aws_cwl_client = boto3.session.Session(
    profile_name='プロファイル名',
    region_name='リージョン名').client('logs')
```

# ロググループ名の一覧は次のように取得できる

```Python
log_group_list = []
response = aws_cwl_client.describe_log_groups()
while True:
    for value in response['logGroups']:
        log_group_list.append(value['logGroupName'])
    if 'nextToken' not in response:
        break
    response = aws_cwl_client.describe_log_groups(nextToken=response['nextToken'])
print(log_group_list)
# ロググループ名の一覧が表示される
```

# tail本体は次のようになる

```Python
log_group_name = 'tailしたいロググループの名前'
stream = ''
next_token = ''
while True:
    response = cwl.describe_log_streams(
        logGroupName=log_group_name,
        orderBy='LastEventTime',
        descending=True,
        limit=1)
    if stream != response['logStreams'][0]['logStreamName']:
        stream = response['logStreams'][0]['logStreamName']
        print('---- %s ----' % stream)
        next_token = ''
    if next_token == '':
        response = cwl.get_log_events(
            logGroupName=group, logStreamName=stream)
    else:
        response = cwl.get_log_events(
            logGroupName=group, logStreamName=stream, nextToken=next_token)
    if len(response['events']) > 0:
        for value in response['events']:
            msg = value['message']
            if msg.startswith('START RequestId: '):
                temp = time.strftime(
                    '%Y-%m-%dT%H:%M:%S',
                    time.localtime(value['timestamp'] / 1000))
                print('---- %s.%0d ----' % (temp, value['timestamp'] % 1000))
            print(msg.replace('\r', '\n').replace('\n\n', '\n').rstrip())
        next_token = response['nextForwardToken']
    time.sleep(3)
```

# 補足

いまググったら、[awslogs](https://github.com/jorgebastida/awslogs)が見つかった。
UbuntuでMeCabのユーザ辞書に単語を追加してPythonで使えるようにする

#はじめに
最近、研究でpythonとMeCabを使用した解析し始めたものの、単語をユーザ辞書に追加する際に苦労したので自分用にまとめてみました。

#環境
- Ubuntu 16.04
- Python 3.6 (anacondaの仮想環境)
- MeCab 0.996 (pip install mecab-python3で導入)

#1. 辞書を用意する
辞書はcsvファイルで作成しておきます。辞書のフォーマットは
表層形,左文脈ID,右文脈ID,コスト,品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原型,読み,発音
の順で並べます。

```
vim add_term.csv
アナと雪の女王,,,1,名詞,一般,*,*,*,*,アナと雪の女王,アナトユキノジョオウ,アナトユキノジョオー
```

左文脈IDと右文脈IDは空欄にしておくと自動で入力してくれます。また、コストはその単語がどれだけ出現しやすいかを示しており、小さいほど出現しやすいという意味になります。コストの推定法もあるようですが、今回は1にしました。不要なものは「*」でオーケーです。
※文字コードは必ず「UTF-8」で作成すること！「Shift-jis」や「EUC-jp」にすると上手くいきませんでした。

#2. ユーザ辞書を作成する
作成したcsvファイルからユーザ辞書を作成します。辞書の作成にはMeCabをインストールした際に付属のmecab-dict-indexを使います。

```
#ユーザ辞書保存先ディレクトリの作成
mkdir /usr/local/lib/mecab/dic/userdic

#辞書作成
sudo /usr/lib/mecab/mecab-dict-index \
-d /usr/local/mecab/dic/ipadic \
-u /usr/local/lib/mecab/dic/userdic/add.dic \
-f utf-8 \
-t utf-8 \
add_term.csv
```

オプションは以下の通りです。
-d システム辞書が入っているディレクトリ
-u ユーザ辞書の保存先
-f csvファイルの文字コード
-t ユーザ辞書の文字コード
csvファイル

mecab-dict-indexはフルパスで実行します。この時も文字コードはUTF-8を指定します。

```
reading add_term.csv ... 1
emitting double-array: 100% |###########################################|

done!
```

と表示されると成功です。

#3. MeCabの設定ファイルに作成したユーザ辞書を追加する
設定ファイルに以下の文を追記します。

```
sudo vim /etc/mecabrc
userdic = /usr/local/lib/mecab/dic/userdic/add.dic
```

公式サイトでは
/usr/local/lib/mecab/dic/ipadic/dicrc
/usr/local/etc/mecabrc
のどちらかに追記するように書いてありますが、筆者の環境では上手くいかず、上記場所にmecabrcがあったのでそちらに追記することで正しく動作しました。複数辞書を登録したい場合は，

```
userdic = AAA.dic,BBB.dic
```

とすれば登録できました。

#動作確認

- コマンドラインから確認する

```
#追加前
mecab
アナと雪の女王
アナ	名詞,一般,*,*,*,*,アナ,アナ,アナ
と	助詞,並立助詞,*,*,*,*,と,ト,ト
雪	名詞,一般,*,*,*,*,雪,ユキ,ユキ
の	助詞,連体化,*,*,*,*,の,ノ,ノ
女王	名詞,一般,*,*,*,*,女王,ジョオウ,ジョオー
EOS

#追加後
アナと雪の女王
アナと雪の女王	名詞,一般,*,*,*,*,アナと雪の女王,アナトユキノジョオウ,アナトユキノジョオー
EOS
```

- pythonのMeCabで使用する

```python:python3
>>> import MeCab
>>> m_t = MeCab.Tagger('-Ochasen \
                        -u /usr/local/lib/mecab/dic/userdic/add.dic')
>>> txt = 'アナと雪の女王を観に行こう。'
>>> print(m_t.parse(txt))
アナと雪の女王 を 観 に 行こ う 。
```

インストール済みのmecab-ipadic-neologdと一緒に使いたい場合は

```python:python3
>>> import MeCab
>>> m_t = MeCab.Tagger('-Ochasen \
                        -d /usr/lib/mecab/dic/mecab-ipadic-neologd \
                        -u /usr/local/lib/mecab/dic/userdic/add.dic')
```

と変更すれば同時に読み込んでくれます。

#結論
試行錯誤しましたが、python上で上手く動作するところまで確認できました。もし間違っている点などありましたらご指摘をいただけますと幸いです。

#参考サイト
[単語の追加方法](https://taku910.github.io/mecab/dic.html)
[MeCab ユーザ辞書への単語追加](https://blog.apar.jp/linux/2748/)
python DSのデバッグ

◆pdb
デフォルトのデバッグ機能

◆helpコマンド
help(なんかオブジェクト)でだいたいの説明が出てきます

◆対話的なデバッグも
https://recruit-tech.co.jp/blog/2018/10/16/jupyter_notebook_tips/#b31

◆言語ごとのDumpの違い
https://hydrocul.github.io/wiki/programming_languages_diff/io/dump.html
pprintがpythonでは紹介されてます。


◆VS codeによるデバッグ
やはり機能は最強ですね！
https://karaage.hatenadiary.jp/entry/2019/02/20/073000
【小ネタ】Window関数で移動平均を算出する【SQL】

# はじめに
SQLのWindow関数について、移動平均を算出する方法をメモします。

# メモ
## 利用するデータ構造
以下のように、日付・地名ごとに記録されている気温データがあるものとします。
各地名・日付ごとに、気温の平均値や最大値などを集計したいものとします。

```SQL:テーブル定義
CREATE TABLE temperature (record_date date, place_name text, celsius_degree float);
```

| record_date      | place_name        | celsius_degree     |
|------------------|-------------------|--------------------|
| 2019-12-01       | 東京              | 10.1               |
| 2019-12-02       | 東京              | 11.2               |
| 2019-12-03       | 東京              | 8.2                |
| 2019-12-01       | 福岡              | 13.5               |
| 2019-12-02       | 福岡              | 12.4               |
| 2019-12-03       | 福岡              | 11.7               |
| :                | :                 | :                  |
| :                | :                 | :                  |

## SQLのサンプル
### 1.当日を含む過去5日と過去15日の単純移動平均を計算する
WINDOW句で、2つのframeを定義する場合のサンプルとなります。
なおこのクエリが意図したとおりに動くためには、各日のレコードが常に1件ずつ存在する必要があります。
これはWINDOW句のROWS句にて、現在処理中の行（？）を含めた5件/15件を集約関数の処理対象とするように指定しているからです。
日付を指定する場合は、RANGE句を用いる必要があります。

```SQL
SELECT
	record_date AS 日付
	, city_name
	, AVG(celsius_degree) OVER w_latest5days AS 移動平均5日間
	, AVG(celsius_degree) OVER w_latest15days AS 移動平均15日間
FROM temperature
WINDOW
	w_latest5days AS (
		PARTITION BY city_name
		ORDER BY record_date ASC
		ROWS BETWEEN 4 PRECEDING AND CURRENT ROW
	)
	, w_latest15days AS (
		PARTITION BY city_name
		ORDER BY record_date ASC
		ROWS BETWEEN 14 PRECEDING AND CURRENT ROW
	)
;
```

### 2.移動平均の対象日の日付を付与する
上記の抽出結果に対し、平均を算出したレコードの日付情報を付加します。

```SQL
SELECT
	record_date AS 日付
	, city_name
	, AVG(celsius_degree) OVER w_latest5days AS 移動平均5日間
	, min(record_date) OVER w_latest5days AS 移動平均5日間初日
	, max(record_date) OVER w_latest5days AS 移動平均5日間末日
	, AVG(celsius_degree) OVER w_latest15days AS 移動平均15日間
	, min(record_date) OVER w_latest15days AS 移動平均15日間初日
	, max(record_date) OVER w_latest15days AS 移動平均15日間末日
FROM temperature
WINDOW
	w_latest5days AS (
		PARTITION BY city_name
		ORDER BY record_date ASC
		ROWS BETWEEN 4 PRECEDING AND CURRENT ROW
	)
	, w_latest15days AS (
		PARTITION BY city_name
		ORDER BY record_date ASC
		ROWS BETWEEN 14 PRECEDING AND CURRENT ROW
	)
;
```


# 参考資料

達人に学ぶSQL徹底指南書 第2版 初級者で終わりたくないあなたへ
https://www.amazon.co.jp/dp/4798157821