OmniAICreator/Qiita-1.07M huggingface dataset:
自分用メモ html

htmlは(Hyper text markup language)の略でwebサイトを作成するための言語。
htmlタグで始まり、htmlタグで終わる。
head,bodyタグで構成され、headにはページに関する情報、タイトルや文字コード等の記入。
bodyにはページのなように関して記述を行う。
タグは</○○>を忘れないよう、注意。
見出し(h1-h6) 数値が大きくなるにつれ、見出しが小さくなる。
段落(p)　段落の指定。
改行(br)htmlは自動的に改行をしてくれないので(br)で改行を行う。brタグは終了タグなし。
箇条書き(ul)を使い、内の項目には(li)で囲む。
箇条書きの項目の先頭を数字にしたい場合は(ol)を使う。(li)で囲むのは変わらず
画像の表示(img src="ファイルへのpath" alt="画像が表示されなかったときの代用文字")
(img)タグは終了タグなし。
コメントは<!--で行える
リンク表示(a href="URL")をh1,liタグに囲まれた中に記述することで記述されたテキストに
クリックすると記述したリンクへ移動することが出来る、
# Rubyでハッシュの引数にデフォルト値を渡せるという基本をまるで知らなかった。もうキーワード引数のエラーに怯えない。

# Ruby keyword arguments raises "unknown keyword (ArgumentError) " so use hash keyword with default value

# Hash argument

```rb
class Alice
  def initialize(options = { nickname: :liddel })
    @options = options
  end

  def nickname
    @options[:nickname]
  end
end

p Alice.new.nickname
# :liddel

# unknown hash value ignored, not raise error
p Alice.new(nickname: :wonder, sex: :woman).nickname
# :wonder
```

# Keyword argument

```rb
class Bob
  def initialize(nickname: :phantom)
    @nickname = nickname
  end

  def nickname
    @nickname
  end
end

p Bob.new.nickname
# :phantom

p Bob.new(nickname: :animal, sex: :man).nickname
# `initialize': unknown keyword: sex (ArgumentError)

```

# Original by Github issue

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








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
dockerfile で git cloneしようとしたらうまくいかなかった件

コンテナ内部で

```shell
git clone git@github.com:motto1123/mot.git
```

をした際はうまくいったのに、

```dockerfile
RUN git clone git@github.com:motto1123/mot.git
```
とすると以下のようなエラーが

```shell-session
Cloning into 'motto'...
Host key verification failed.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
ERROR: Service 'shell' failed to build: The command '/bin/sh -c git clone git@github.com:motto1123/motto.git' returned a non-zero code: 128
```

ちょっと時間がかかったのですが、結局以下のようにするとOK

```dockerfile
RUN git clone https://github.com/motto1123/mot
```

 git@から始まるのでやるとうまくいかないので、httpsで始まる命令にする必要があります。
DockerでMariaDB 10.4(Mroongaプラグイン有効化)を起動時にログファイルの場所も変更してみる

## 環境

Windows 10 Pro Version 1903 (OS build 18362)
Docker Desktop
　Engine: 19.03.4
　Compose: 1.24.1

docker-composeインストール・・・PowerShellを管理者権限で実行

```
PS C:\WINDOWS\system32> [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
PS C:\WINDOWS\system32> Invoke-WebRequest "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-Windows-x86_64.exe" -UseBasicParsing -OutFile $Env:ProgramFiles\docker\docker-compose.exe
```

MariaDB 10.4.5 + Mroongaプラグイン有効化のDockerイメージ
[kazaoki/mariadb-mroonga](https://hub.docker.com/r/kazaoki/mariadb-mroonga)

## ファイル

```docker-compose.yml
version: "3.7"
services:
  mariadb:
    container_name: mariadb
    image: kazaoki/mariadb-mroonga:10.4
    environment:
      MYSQL_ROOT_PASSWORD: test
    ports:
      - 3306:3306
    volumes:
      - ./sql/mroonga-log.sql:/docker-entrypoint-initdb.d/mroonga-log.sql
```

```./sql/mroonga-log.sql
SET GLOBAL mroonga_log_file = "/var/log/mysql/mroonga.log";
SET GLOBAL mroonga_query_log_file = "/var/log/mysql/mroonga-query.log";
```

## 動作確認

```
$ docker-compose up -d
$ docker exec -it mariadb bash
$ cat /var/log/mysql/mroonga.log

2019-11-16 13:16:12.976751|n|042d8700|log file is changed: <groonga.log> -> </var/log/mysql/mroonga.log>
2019-11-16 13:16:12.976928|n|042d8700|query log is enabled: </var/log/mysql/mroonga-query.log>
2019-11-16 13:16:14.352656|n|0d48b540|mroonga 7.07 deinit
2019-11-16 13:16:14.353231|n|0d48b540|grn_fin (0)

$ cat /var/log/mysql/mroonga-query.log

2019-11-16 13:16:12.976964|0x7fafb17f5f40| query log will be closed: </var/log/mysql/mroonga-query.log>
2019-11-16 13:16:12.977011|0x7fafb17f5f40| query log is opened: </var/log/mysql/mroonga-query.log>
2019-11-16 13:16:14.353102|0x7fafb17a2040| query log will be closed: </var/log/mysql/mroonga-query.log>
```
AtCoder 第二回全国統一プログラミング王決定戦予選 参戦記

# AtCoder 第二回全国統一プログラミング王決定戦予選 参戦記

## [A - Sum of Two Integers](https://atcoder.jp/contests/nikkei2019-2-qual/tasks/nikkei2019_2_qual_a)

2分で突破. 書くだけ. ARC の A 問題ってこんなに簡単だっけかと混乱した.

```python
N = int(input())

print((N - 1) // 2)
```

## [B - Counting of Trees](https://atcoder.jp/contests/nikkei2019-2-qual/tasks/nikkei2019_2_qual_b)

68分半で突破. WA 6個. WA2個が中々消えずに WA を重ねてしまった. その2個は0が複数あるやつだった…….

```python
from sys import exit

N = int(input())
D = list(map(int, input().split()))

if D[0] != 0:
    print(0)
    exit()

c = {}
for i in D:
    if i in c:
        c[i] += 1
    else:
        c[i] = 1

if c[0] != 1:
    print(0)
    exit()

result = 1
for i in range(1, max(D) + 1):
    if i not in c:
        print(0)
        exit()
    result = result * (c[i - 1] ** c[i]) % 998244353
print(result)
```

Python は `result = result * (c[i - 1] ** c[i]) % 998244353` とサラッと書けるけど、多倍長整数じゃない言語だと大変だよなと思って、Go で書き直してみたのが以下. やっぱり大変だなー. 冪乗は *O*(log<i>N</i>) じゃないといけないかと思って苦労して書いたら、みんな *O*(*N*) で計算していた(笑).

```go
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func pow(base int, exponent int) int {
	result := 1
	for exponent > 0 {
		if exponent%2 == 1 {
			result *= base
			result %= 998244353
		}
		exponent >>= 1
		base *= base
		base %= 998244353
	}
	return result
}

func main() {
	N := readInt()
	D := readInts(N)

	if D[0] != 0 {
		fmt.Println(0)
		return
	}

	c := map[int]int{}
	maxD := 0
	for _, i := range D {
		c[i]++
		if i > maxD {
			maxD = i
		}
	}

	if c[0] != 1 {
		fmt.Println(0)
		return
	}

	result := 1
	for i := 1; i <= maxD; i++ {
		if _, ok := c[i]; !ok {
			fmt.Println(0)
			return
		}
		result *= pow(c[i-1], c[i])
		result %= 998244353
	}
	fmt.Println(result)
}

const (
	ioBufferSize = 1 * 1024 * 1024 // 1 MB
)

var stdinScanner = func() *bufio.Scanner {
	result := bufio.NewScanner(os.Stdin)
	result.Buffer(make([]byte, ioBufferSize), ioBufferSize)
	result.Split(bufio.ScanWords)
	return result
}()

func readString() string {
	stdinScanner.Scan()
	return stdinScanner.Text()
}

func readInt() int {
	result, err := strconv.Atoi(readString())
	if err != nil {
		panic(err)
	}
	return result
}

func readInts(n int) []int {
	result := make([]int, n)
	for i := 0; i < n; i++ {
		result[i] = readInt()
	}
	return result
}
```

## [C - Swaps](https://atcoder.jp/contests/nikkei2019-2-qual/tasks/nikkei2019_2_qual_c)

突破できず. 実現可能であれば、N-1回操作できれば必ず実現できることは分かったが、N-1回が必要かどうかを求める方法がさっぱり分からなかった. 終了後、解説に巡回置換とかサイクルとか知らない単語を見て、これは無理だったと悟る. 巡回置換でググると大学の数学っぽく、そりゃ無理だ(まて).
Python3で日付の月(数字）を英語名に変換する方法

# Pythonでは 月の数字(int型の数値1〜12)から直接、月の英語名へ変換する関数が見当たらなかったの、一手間挟んで出力してみました。

```python3:ソースコード

# coding: utf-8
import datetime

def MonthNumberToMonthName(month):
    date = datetime.date(2000, month, 1)  #年と日は自由に設定する
    return date.strftime("%B")

# １月から１２月まで表示
for month_number in range(12):
    month_name = MonthNumberToMonthName(month_number)
    print(month_name)
```


```qiita:実行結果
January
February
March
April
May
June
July
August
September
October
November
December
```

以上です。

この処理を単体で使う機会はほとんどないと思いますが、
調べても意外と出てこなかったので、記事として残してみました。
参考になれば、Likeしてもらえると励みになります。

他にもっとシンプルな記述方法を知っている方がいれば教えてくださるとありがたいです。
Flask入門その1：まずはローカルで動かしてみる＆配布用に実行ファイルを作ってみる

# 環境
PC : Mac
開発環境 : Visual Studio Code

# まずはローカルでhello worldを動かす
flaskをインストール

```
pip install flask
```

実行

```python
from flask import Flask
app = Flask(__name__)
 
@app.route('/')
def hello_world():
    return '''
        <html>
            <body>
                <h1>hello world</h1>
            </body>
        </html>
        '''

if __name__ == '__main__':
    app.run()
```

ブラウザで確認
[http://127.0.0.1:5000/](http://127.0.0.1:5000/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/1824d811-6f23-3b8a-7881-866fb19192ec.png)


# 非エンジニアに渡して使ってもらえるように、実行ファイル化してみる
実行ファイル化用パッケージをインストール

```bash
pip install pyinstaller
```

実行ファイル化

```bash
pyinstaller flask_test.py --onefile
```

問題なくMac用の実行ファイルを作れた
ちなみに、クロスコンパイラではないのでMacでWindows用の実行ファイルを作ることは出来ないらしい


# 大いに参考にさせてもらったサイトたち
* [flask入門](https://www.python.ambitious-engineer.com/archives/1630)
* [実行ファイル化](https://techacademy.jp/magazine/18963)
awsのec2にApacheを入れてwebサーバーとして使う

# 0-1. 環境
aws - ec2 - ubuntu
インスタンスタイプ：t2.micro

# 0-2. 前提（今回作業前の状態）
awsアカウントは持ってた
一つインスタンスを作っていて、実行中のがあった
sshの設定なども済ませていて、すぐにログインできる状態

# 0-3. 大いに参考にさせて頂いたページたち
* [今更聞けない！Webサーバーの仕組みと構築方法
](https://eng-entrance.com/web-server-mechanism)
* [AWS EC2を使って無料枠でWebサーバを立ててみた（2015年12月版）](https://sil.hatenablog.com/entry/aws-ec2-free-webserver)
* [Ubuntu16.04にApache2をインストール・設定する](https://chee-s.net/ubuntu16-04%E3%81%ABapache2%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%83%BB%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B)
* [Apache:インストール(httpd)、初期設定、その他](https://qiita.com/YasuyukiKawai/items/b32bd94cde7f928c0753)
* [【HTML入門】イラスト付き解説とサンプルの練習で基本を身につける](https://webliker.info/84713-2/)

# 1. セキュリティーグループの設定

参考サイトの説明（下図）に従い、セキュリティーグループの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/72a42900-554b-df8a-7f6b-eaeee3dec4ee.png)

# 2. Apache2のインストール

```bash
パッケージの更新
sudo apt-get update
 
Apache2のインストール
sudo apt-get install apache2

バージョン確認
apache2 -v
```
IPv4 パブリック IPを確認し、自分のPCブラウザからアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/c7fc57f9-c490-bd6b-c7ec-07b6539254c3.png)
ok

# トップページの箱（index.html）を作る
まず、ルートディレクトリを確認

```bash
vim /etc/apache2/sites-available/000-default.conf 
```
「DocumentRoot /var/www/html」っぽい

index.htmlを修正する

```
sudo vim /var/www/html/index.html 
```

以下のように記載

```html
<!DOCTYPE html>
<html>
    <meta charset="utf-8">
    <head>
        <title>我が青春のホームページ</title>
    </head>
    <body>
        これがスマホとか他のパソコンから見れればOK
    </body>
</html>
```
インストール後に確認したのと同様に、IPv4 パブリック IPを確認し、自分のPCブラウザからアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/1750feff-4bc7-5b3b-8504-a386a543f153.png)
**これで準備OK!**
後日、中身を作ります（flaskと何かのAPIを使う想定）
　おわり
[Nestjs] Webアプリの基本　コントローラーを実装する

# 概要

NestjsでHTTPリクエストを捌くコントローラーを作成する
以下の項目を考慮する

- HTTPメソッドのルーティング
- 正常処理時のレスポンス
- 異常処理時のレスポンス

## ルーティングと正常処理

Nestjsのコントローラーはデコレーターパターン(@で始まる)で機能を追加していく
以下ではGet /practiceを処理するためのコントローラーを作成している

[リクエスト]
クラスに@Contoller(path_name)をデコレートする事でパス /path_naneを拾うコントローラーが作成できる
そのクラスのメソッドに@Getをデコレートすることでhttpメソッド Getを拾って処理するハンドラが作成できる
メソッドの引数に@Query()を追加することでクエリストリングを拾う
他にも@BodyでBodyを扱うこともできる
以下のソースコードではtypeというクエリストリングを拾い,変数typeに割り当てている

[レスポンス]
メソッド内でnumberやstringなどのプリミティブ型をreturnするとそのままボディに入れてレスポンスを返す
また、javascriptオブジェクトをreturnすると, 自動的にJSONに変換してレスポンスボディに詰めて返す

以下のコントローラーのソースコードをnestjsモジュールに登録して実行すれば、以下のリンクにアクセスして動作を確認できる
http://localhost:3000/practice?type=number
http://localhost:3000/practice?type=string
http://localhost:3000/practice?type=object

``` typescript
import { Controller, Get, Query } from '@nestjs/common';

@Controller('practice')
export class AppController {

  @Get()
  getHello(@Query('type') type: string) {
    if (type === 'number') {
      return 123456789;
    }
    if (type === 'string') {
      return 'hoge moge poge';
    }
    if (type === 'object') {
      return {
        hoge: 'hoge',
        moge: 'moge',
        poge: 'poge',
      };
    }
  }

}

```

## 異常処理

以下では、例外処理の方法を実装する
正常時はreturnでレスポンスを返していたが、例外はthrowすることでレスポンスを返す
Nestjsでは例外用のクラスも用意されていて@nestjs/commonからimportし、400を返したいときはBadRequestException, 404を返したいときはNotFoundException, 自分で例外を作りたいときはHttpExceptionを使って作ることができる

以下のコントローラーのソースコードをnestjsモジュールに登録して実行すれば、以下のリンクにアクセスして動作を確認できる
http://localhost:3000/practice?code=400
http://localhost:3000/practice?code=404
http://localhost:3000/practice?code=500

```typescript
import { Controller, Get, Query, HttpException, NotFoundException, BadRequestException, HttpStatus } from '@nestjs/common';

@Controller('practice')
export class AppController {
  @Get()
  getHello(@Query('code') code: string) {
    if (code === '400') {
      throw new BadRequestException();
    }
    if (code === '404') {
      throw new NotFoundException()
    }
    if (code === '500') {
      throw new HttpException('Internal Server Error', HttpStatus.INTERNAL_SERVER_ERROR)
    }
  }

}
```
【WPF】スタイルの共通化方法

# はじめに
はじめまして、現在仕事でWPFを使用した開発を行っているdaitenと申します。
本記事は、仕事にて学んだことを備忘録的な感じで書いていきますので、何か誤りがありましたらご指摘頂けますと幸いです。
また今後も新たに学んだ部分は記事を修正、追加などしていく予定です。

# スタイルの共通化とは
Xamlによって記述されたコントロールはそのプロパティの値を変更することによってデザインや挙動などを変更することができる。
そのプロパティの値を複数のコントロールで共有するために値のリソースを別の場所に定義し、そこの値を参照することで共通化を行うことができる。

# StaticResourceを使用した共通化
静的(Static)なリソースでアプリの実行時のリソースは常に固定される
例えば以下のようにWindowのリソース内にButtonを対象とするButton_RedというKey名のリソースを配置し、ButtonからはStyleプロパティにStaticResourceで参照させています。
このようにすることで複数のButtonで、共通の背景色を設定することができます。
![スクリーンショット 2019-11-16 22.33.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396155/eb92adb2-08aa-de2e-d313-ee0686df2caf.png)

# 共通化項目の設定方法
共通化したいプロパティの設定方法はSetterとValueを使用して設定を行います。
まずSetterで共通化したいプロパティを指定し、Valueで値を設定します。
![スクリーンショット 2019-11-16 23.21.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396155/e4c183d0-6a13-8af7-f7ca-4c49cf31a71b.png)


# ネストしたスタイルの共通化方法
Styleの内部でStyle.Resourceを定義することで、共通化を行うことができます。
以下の例はStackPanelに配置したButtonの背景色を赤にするよう共通化を行ったものです。
手順としてはまずWindow.Resource内にStackPanelのスタイルのリソースを定義し、その内部でStyle.Resourceを定義することでStackPanel内に指定したコントロールを配置した場合(今回の場合はButton)にスタイルが適用されます。
![スクリーンショット 2019-11-16 23.43.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396155/e941396a-d9ca-8d27-d1aa-0522bf6a5788.png)

# 参考
https://kosiro.tech/front-end/wpf-style-common.html
Javascript で diff (内部仕様についての補足５)


  10/14 に投稿した[Javascript で diff (通信なし、ローカルで完結)](https://qiita.com/stonee/items/e2d88f07d08171b2816f)の内部仕様についての補足、その５です。
 [Javascript で diff (内部仕様についての補足)](https://qiita.com/stonee/items/8964e801f27cd9433e01)
 [Javascript で diff (内部仕様についての補足２)](https://qiita.com/stonee/items/62aebae3a4ee07c76601)
 [Javascript で diff (内部仕様についての補足３)](https://qiita.com/stonee/items/df1019d2f4877c342217)
 [Javascript で diff (内部仕様についての補足４)](https://qiita.com/stonee/items/dea3fdbdbceb0c799362)

※10/14 投稿のソースは Microsoft Edge で文字コードをUTF-8として認識していなかったので、文字コードの指定を追加しました。
Edge が Chrome 準拠になったら、また微修正するかもしれません。

# 文字列の類似度をはかる (検討しようとして撃沈された)

補足その１ [Javascript で diff (内部仕様についての補足)](https://qiita.com/stonee/items/8964e801f27cd9433e01) で、レーベンシュタイン距離の用語を出したまま説明を端折っていたので、今回はレーベンシュタイン距離の話題です。

行単位の差分をとるにあたって、似ている行は差分を表示、似ていない行は削除＋追加として表示するため、文字列の類似度を測ることにします。
文字列の類似度を測る指標はいろいろありますが、まずはどの指標でどのような数値が算出されるのか試してみようとして、下記の方法でスコアを算出してみることにしました。

- レーベンシュタイン距離(Levenshtein distance)
- ダメラウ・レーベンシュタイン距離(Damerau-Levenshtein distance)
- ジャロ・ウィンクラー距離 (Jaro-Winkler distance)
- N-Gram 

「abcdef」「defabc」の距離をはかると、レーベンシュタイン距離は類似度0.5となりましたが、残り３つはすべて類似度0となり、検討する前に終了してしまいました………… orz
なので、diff_orz では、レーベンシュタイン距離を類似度の指標として採用しています。


# レーベンシュタイン距離

Wikipediaの該当ページ － [レーベンシュタイン距離](https://ja.wikipedia.org/wiki/%E3%83%AC%E3%83%BC%E3%83%99%E3%83%B3%E3%82%B7%E3%83%A5%E3%82%BF%E3%82%A4%E3%83%B3%E8%B7%9D%E9%9B%A2)

レーベンシュタイン距離の解説そのものは、Wikipedia のものをはじめネット上の各所にあるので、詳細な説明はここでは省略します。
簡単に言うと、ある文字列を別の文字列に変形するのに必要な操作回数を調べれば、「削除・追加・置換の操作回数が多い」＝「似ていない文字列」といえます。
削除・追加・置換の回数を調べた段階では、操作回数の絶対値が算出されるだけですので、何%くらい似ているかを調べるには、

　　1 - (操作回数 / 文字列の長さ)

と換算する必要があります。
上述の換算には、

- 置換を操作コスト1としてカウントするか、操作コスト2としてカウントするか
- 二つの文字列のうち、長いほうの長さを基準にするか、両方の長さを考慮するか

など、バリエーションがあります。diff_orz では、

- 削除・追加・置換の操作のコストはすべて1
- 二つの文字列のうち、長いほうの長さを基準にする

としています。

最初に試作したときは、動的計画法で実装していたのですが、効率がO(MN)で**大変**遅かった (2019/11/16 時点の Wikipedia では何故か「効率がよい」となっている) ため、あれこれ試行錯誤した後、Wu のアルゴリズムによる O(NP) の実装に落ち着きました。

[An O(NP) sequence comparison algorithm](https://dl.acm.org/citation.cfm?id=96223)

文字列どうしが似ていると判定する閾値は threshold で指定しています。
既定値の0.5のままでも大抵うまくいくと思いますが、判定をゆるくしたい場合は0に近い数値、判定をきつくしたい場合は1.0に近い数値を指定してください。
下記実装では、閾値を超えた場合に計算を打ち切って「似ていない」と判定しています。


```js
var DiffEngine = {
	//中略
	threshold: 0.5,	//0(loose) < threshold < 1(strict) 文字列どうしが似ていると判定する閾値

	//中略

	//レーベンシュタイン距離のスコアを計算
	CalcScore(s1, s2, len1, len2) {
		const pmax = len1 + 1 - this.threshold * len2, _max = Math.max;
		if (pmax < 1) { return 0; }		//optimize
		let y, p = 0, fp = (new Int32Array(len1 + len2 + 3)).fill(-1);
		for (; (p < pmax) && (fp[len2 + 1] != len2); p++) {
			for (let k = len1 - p; k < len2; k++) {
				for (y = _max(fp[k] + 1, fp[k + 2]);
					(y < k) && (s1.charCodeAt(y - k + len1) == s2.charCodeAt(y));
					y++) {}
				fp[k + 1] = y;
			}
			for (let k = len2 + p; k >= len2; k--) {
				for (y = _max(fp[k] + 1, fp[k + 2]);
					(y < len2) && (s1.charCodeAt(y - k + len1) == s2.charCodeAt(y));
					y++) {}
				fp[k + 1] = y;
			}
		}
		return (1 - (len2 - len1 + p - 1) / len2);	//distance score
	},
	//後略
}
```
年末まで毎日webサイトを作り続ける大学生 〜49日目 サイトを10*10に区切って、マウスを動かすと背景も変わる〜

##はじめに
こんにちは！@70days_jsです。

サイトを10*10に区切って、マウスが動くと背景も変わるようにしました。
ほぼ全部JavaScriptを使っています。

今日は49日目。(2019/12/6)
よろしくお願いします。

##サイトURL
https://sin2cos21.github.io/day49.html

##やったこと
伝えづらいんですが、映像を見れば一発だと思います。
こんな感じです。↓
![test3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/fdd610b3-c7f6-7d93-1639-eb369fe2e132.gif)


htmlはdivを一つ用意するだけです。↓

``` html
  <body>
    <div id="mouseMove"></div>
  </body>
```

JavaScript全文↓

```javascript
let mouseMove = document.getElementById("mouseMove");
let innerWidth;
let innerHeigt;

innerHeigt = window.innerHeigt;
innerWidth = window.innerWidth;
height10 = innerHeight / 10;
width10 = innerWidth / 10;

for (var i = 0; i < 10; i++) {
  for (var j = 0; j < 10; j++) {
    let div = document.createElement("div");
    div.setAttribute("class", "color");
    div.style.top = height10 * i + "px";
    div.style.left = width10 * j + "px";
    randomColor(div);
    mouseMove.appendChild(div);
  }
}

mouseMove.addEventListener("mousemove", function(e) {
  let getClass = document.getElementsByClassName("color");
  for (var i = 0; getClass.length > i; i++) {
    randomColor(getClass[i]);
  }
});

function randomRGB() {
  let r = Math.floor(Math.random() * 256);
  let g = Math.floor(Math.random() * 256);
  let b = Math.floor(Math.random() * 256);
  let rgb = [r, g, b];
  return rgb;
}

function randomColor(element) {
  let rgb = randomRGB();
  let r = rgb[0];
  let g = rgb[1];
  let b = rgb[2];
  element.style.backgroundColor = "rgba(" + r + ", " + g + "," + b + ", .3)";
}
```

サイズを取って/10をして10分割を実現しています。↓

> innerHeigt = window.innerHeigt;
innerWidth = window.innerWidth;


10*10のdivを作っています。↓

> 
for (var i = 0; i < 10; i++) {
  for (var j = 0; j < 10; j++) {
    let div = document.createElement("div");
    div.setAttribute("class", "color");
    div.style.top = height10 * i + "px";
    div.style.left = width10 * j + "px";
    randomColor(div);
    mouseMove.appendChild(div);
  }
}


マウスが動くごとに　背景を変えています。↓

> mouseMove.addEventListener("mousemove", function(e) {
  let getClass = document.getElementsByClassName("color");
  for (var i = 0; getClass.length > i; i++) {
    randomColor(getClass[i]);
  }
});


最後にcss全文↓

```css
body {
  margin: 0;
  overflow: hidden;
}

#mouseMove {
  height: 100vh;
  width: 100vw;
}

.color {
  background-color: red;
  position: absolute;
  width: 10%;
  height: 10%;
}
```

ポイントは

>  position: absolute;
  width: 10%;
  height: 10%;
}

この3行だけです。

##感想
マウスを動かす系にはまってしまいました。
そろそろpromiseとか、技術的な方向を掘っていきたいと思います。

最後まで読んでいただきありがとうございます。明日も投稿しますのでよろしくお願いします。
シャッフルランチを効率化したい

この記事は[Pathee Advent Calendar 2019](https://qiita.com/advent-calendar/2019/pathee)の7日目の記事です。

## はじめに
Patheeでは毎週木曜日に社員全員を対象にシャッフルランチを開催していて、そのメンバーシャッフルの担当をしています。

チーム間交流になるようにチームをバラけさせたり、できるだけメンバーがかぶらないように前回のメンバー表と見比べたりと、手作業による調整を行ってきましたが、最近では直前の欠席の連絡による出席メンバーの確認や、その調整をする時間が取れないなど課題がありました。

そこで、スプレッドシート上での作業をSlackのコマンドを活用して効率化していきます。
今回は出席者の登録とメンバーのシャッフルを自動化します。

## 開発したもの
Slackのスラッシュコマンド `/lunch`
* 出欠確認
* メンバーを指定して欠席を登録
* 出席するメンバーの確認
* シャッフルした結果を表示

![スクリーンショット 2019-12-06 22.31.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66520/4f4dcf32-addf-342c-8772-ce5193aec60b.png)

## 使うもの
* Slack
  - シャッフルランチ用のチャンネルで欠席の連絡やメンバーの発表を行う
* スプレッドシート
  - メンバーの管理・チーム分けの記録をする
* Google Apps Script
  - slackのコマンドを受けてスプレッドシートを書き換えたり結果を返す 

## メンバーリストの作成
スプレッドシートにシャッフルランチの参加メンバーのリストを作成します
リストの項目は「名前」「SlackのUserID」「出欠」にしました

* 「名前」はメンバー一覧やシャッフル結果の表示に使用します
* 「SlackのUserID」は、Slackでメンバーの出欠登録をするときに使用します。
Slack画面の左上のチーム名をクリック、「その他管理項目」の「メンバー管理」ページから入手できます
* 「出欠」には出席／欠席が入力されて、出席になっているメンバーのみシャッフル対象にします。

## コマンド
SlackのAppで`/lunch`というスラッシュコマンドを追加します。
`parameter.text`で/lunchの後に入力された文字列を取得できるので、その文字列によって処理を分岐させます

### 初期化
スプレッドシートには前回の内容が入力された状態になっているので、内容をリセットします。
基本的に全員参加するので、「出席」に書き換えます。

スプレッドシートの操作のコードをまとめておきます。

```js
    // スプレッドシートの取得
    var spreadsheet = SpreadsheetApp.openById('スプレッドシートID')
    // シートをシート名から取得
    var sheet = spreadsheet.getSheetByName('シート名');
    // sheet.getLastRow()を使えばデータの入っている最後の行が取得できる
    var range = "取得範囲";
    // 指定範囲のデータを取得
    sheet.getRange(range).getValues();
    // 指定範囲のデータをセット
    sheet.getRange(range).setValue("設定する値")
    // シートの削除
    spreadsheet.deleteSheet(sheet);
    // シートのコピー
    sheet.copyTo(spreadsheet);
    // シート名の設定
    sheet.setName("members")
```

### 出欠の登録
出欠の登録方法には２種類あり、１つはメンバーが自身の出欠をボタンで入力するもので、もう１つは欠席するメンバーを選択するものです。

メンバー自身が出欠を入力するものは、「出席」と「欠席」の２つのボタンのどちらかを入力するものになっています。

```js
    var actions = [
        {
            name: "feedback",
            text: "出席",
            style: "primary",
            type: "button",
            value: "出席"
        },
        {
            name: "feedback",
            text: "欠席",
            style: "danger",
            type: "button",
            value: "欠席"
        }
    ]
    var attachments = [{
        callback_id: "confirm",
        actions: actions
    }]
    return {
        text: "今日のシャッフルランチに参加しますか？",
        attachments: attachments
    }
```

欠席するメンバーを入力するほうは、`data_source: "users"`でユーザのリストが選択肢となったセレクトボックスから欠席するメンバーを選べます。

```js
    var actions = [
        {
            name: "user",
            text: "Select user",
            type: "select",
            data_source: "users"
        }
    ]
    var attachments = [{
        callback_id: "member",
        actions: actions
    }]
    return {
        text: "欠席するメンバーを選択してください",
        attachments: attachments
    }
```

### メンバーシャッフル

スプレッドシートから「出席」になっているメンバーだけを抽出し、完全にランダムでシャッフルします。
１チームが最大４人でメンバーの数が偏りすぎないように調整します。


## おわりに
出欠の登録やメンバーのシャッフルを、スプレッドシートを開かずにSlackだけでできるようになりました。
まだメンバーを完全にシャッフルしているだけなので、メンバー管理用シートにメンバーのチームや過去のチームを登録できるようにして、よりいろんなメンバーと交流できるように改良していきたいです。
Swiftのprotocolとprotocol extensionまとめる。

## 初めに
今日はswiftの基本的なところであるprotocolとprotocol extensionについて自分なりにまとめていきます。
## protocolとは
定義は下のような感じで書きます。

```swift:protocol定義
protocol hoge {
  func hugahuga() -> Int
}
```
関数の処理などは書きません。定義だけします。

クラスなどにprotocolを準拠させる場合は  


```swift:protocolをクラスに準拠させる。(エラー)
protocol hoge {
  func hugahuga() -> Int
}
class viewController: hoge {

}
```

みたいな感じになりマス。
ただしprotocolを準拠したクラスは必ずprotocolで定義されている関数などを継承させなければならないので上のclassは実際にはエラーになります。
正しくは

```swift:protocolをクラスに準拠させる。
protocol hoge {
  func hugahuga() -> Int
}

class viewController: hoge {
  func hugahuga() -> Int {
    return 5
  }
}
```
となります。
クラス継承と違ってprotocolは一つのクラスに複数継承できます。
classと一緒にprotocolを継承する場合は下のように書きます。

```swift:protocolと親クラスを子クラスに準拠させる。

class viewController: スーパークラス名,protocolA名,protocolB名 {

}
```
protocolはclass,extension,sturct,enum,クロージャの他にも変数の型としても使えます。
例えば

```swift:変数の型にprotocolを使う
protocol UserProtocol {
  var name: String { get }
}
func hoge(x: Protocol名){
   print(x.name)
}
```
みたいな感じに使えます。
他にもDI(DependencyInjection)に使えたりするのでめちゃくちゃ便利ですね。
まだまだありますがprotocolの説明はこんくらいにしときます。
## protocol extension
protocol extensionはprotcolの機能を拡張するものです。

```swift:protocolextension
protocol Hoge{
  var x: Int { get }
}
extension protocol hoge{
  var y: Int { return 5 }
}

class Huga1: Hoge {
  var x: Int
}
class Huga2: Hoge {
  var x: Int { return 1 }
  var y: Int { return 2 }
}

Huga1().x  //1
Huga1().y  //5 huga1でyを定義していないのでextensionのデフォルト値が呼ばれる。
Huga2().x  //1
Huga2().y  //2
```
extension protocolで定義したものは準拠したクラスや構造体で必ず継承しなければならないということはありません。
なので上の例ではHuga.xはHugaでは定義されていませんがextensionで定義してある5が返されています。
このようにextensionにdefaut値を設定することをデフォルト実装と言います。

protocol extensionは型制約を追加することができて条件を満たす時だけプロトコルエクステンションを有効化できます。

```swift:ProtocolExtension型制約
extension protocol名 Where 型制約 {
  制約を満たした時だけ有効になる処理。
}
```

## 最後に
これだけでは全部網羅したとは言えませんが自分なりにざっくりまとめてみました。
protocolまじで便利。ということで寝ますおやすみなさい。
最近知った言葉まとめてみた

## はじめに
Qiita最近毎日頑張ってコツコツ書いてます。
よかったら、読んでくれると嬉しいです:relaxed:
間違えたりしているところあったら、すいません:droplet:


## ドキュメンテーションコメント
ドキュメンテーションコメントはAPIの仕様である。主にAPIを使用する人のために記述するもの。ドキュメンテーションコメントを見ただけで、そのAPIを正しく使えるようになっている必要がある。一般公開する目的っで作られたライブラリや、アプリケーション作成などの際も、開発効率を上げるなどといった目的があるので、ドキュメンテーションコメントを記述する必要があります。

## RDoc
Rubyで書かれたソースコードから、ドキュメントを自動生成するライブラリ。クラスやモジュールの定義を抜き出し、includeやrequireに関して解釈をして、直前のコメントと合併し、HTMLを出力します。
コメント内で、見出しレベルを変えたりできる。また、クラスの関連図を画像出力など、便利なオプションもある。
     
## ガード節
プログラミングの手法で、特定な条件を最初に処理することで、コードをわかりやすくする手法。
例えば、if文でネストが深くなってしまう場合、否定の条件で処理するとネストが浅くなり、ソースコードが見やすくなる場合があります。ネストが浅くなると読みやすくなります！合致する条件が多い場合で、条件が合致するかどうかのif文をたくさん作るより、合致しない条件(否定)でif文を作ったほうが、早いと思います(たぶん)

## 論理削除
データベース自体からデータ削除自体は行わず、削除されたとみなされるフラッグと呼ばれるカラムを設定することで、ユーザーには削除しているかのようにふるまうことができること。言い換えると削除されているように見えているけど、見えないだけであってデータ自体は残っているということ！

## 物理削除
実際にSQLでDeleteされることを指す。データベースから削除されるので、データの復元、削除されたデータの参照は不可。

## 隠しフィールド
プログラムには値を渡したいが、ブラウザ上には表示させたくないという場合に使用。
`input` タグの中で`type="hidden"`を設定すると隠しフィールドの定義ができる。

## さいごに

これからもっとたくさんコード書いて、自分にしか読めないコードではなく、「誰が読んでも理解できるコード」が書けるようになるよう努力していきたいと思います。
[UE4] StationaryなDirectional Lightは半透明用のShadow Mapをひっそりと持っている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363464/b8b8bf48-e544-3793-1af9-a2c2221bd114.png)
この煙がどのようにライティングされているかイメージできてますでしょうか？？

半透明オブジェクトは、StationaryなDirectional Lightの影響を**影付きで**受けることができます。（このシーンのDirectional LightはなのでStationaryです）その様なライティングができるように。。ShadowMapのデータがあるということなので、メモリ量であったりそのクオリティだったりに注意する必要があります。

実はあまり知られてないのですが、オフィシャルドキュメントにも実はちゃんと記載されています。

こことか -> [Lit の透過処理](https://docs.unrealengine.com/ja/Engine/Rendering/LightingAndShadows/LitTranslucency/index.html)
> 透過アイテムは、ライティング ビルド時に生成された特別な静的シャドウ深度マップによってStationary Light (固定ライト) から静的シャドウイングを取得できます。

ここにも-> [Stationary lights(固定ライト)](https://docs.unrealengine.com/ja/Engine/Rendering/LightingAndShadows/LightMobility/StationaryLights/index.html)
> 透過も Stationary light (固定ライト) で負荷をかけずにシャドウイングを受け取ります。Lightmass は、ランタイム時に透過に適用される静的ジオメトリからシャドウ深度マップを事前計算します。このシャドウイングの形式は非常に粗く、シャドウイングのキャプチャはメートル単位でのみ行います。


半透明ライティングの詳細は割愛しますが、一つの手法にTranslucencyLightingVolumeを毎フレームアップデートし続ける手法があります。このボリュームデータの計算のさい、たしかにこのShadow Mapが参照されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363464/7f27d6a5-66ee-eb96-6958-b7bf93c2d600.png)

しかし、そのテクスチャを見ると非常に粗いです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363464/8ee590e1-030b-4b41-2c72-0ed7b466b712.png)

これはオフィシャルにも記載されているのですが、初期設定ではこの半透明用ShadowMapはデフォルト1メールと1ピクセルという非常に粗いものです。もしもこの影のクオリティを上げたい場合、解像度を高くする必要がありますが、その手法は三種類ほど用意されています。

**1. LightのComponentのShadow Resolution Scaleを上げる**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363464/9c696773-eec3-4c6e-1736-494711bc5af8.png)
しかしこの手法だと他のShadowMapの解像度も上げる可能性があります


**2. World SettingsのStatic Lighting Scaleを小さくする**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363464/e897e55b-7557-d98a-0a06-078f4cfb4362.png)
しかしこの手法だと、他の間接光用Volume Dataの密度も上げてしまう可能性があります。


**3. Lightmass.iniのStaticShadowDepthMapTransitionSampleDistanceX/Yを小さくする**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363464/57c10f02-539f-09e1-34b2-65597742e199.png)
この設定で、半透明用のShadowMapの解像度だけを個別に制御することができます


ということで、3番目の手法によりStaticShadowDepthMapTransitionSampleDistanceX/Yともに10にしてみました。下の様に解像度があがっているのがわかるかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363464/4862d34d-1260-9afc-bca1-59b3306f5c32.png)


実際のライティングにより具体的に反映させるには、半透明ライティングボリュームの解像度も上げる必要があったりしますが、半透明ライティングのイメージがつかめると幸いです。
スプレッドシートの値をGASを使ってhtmlに持ってきて、3択クイズwebアプリを作った話

# はじめに
色んなデータをCloud上でやり取りできるGoogleサービス！
そんなGoogleサービスたちを繋げてくれるGoogle Apps Script(GAS)に最近ハマっています。

今回は、Googleフォームで入力した3択クイズをランダムに表示してくれるwebアプリケーションを作りました。そのときにスプレッドシートからhtmlに値だけを渡すのに苦労したので、同じ苦労をしている人のためにまとめておきます。
※この3択クイズを使った商品を今後公開する(売り出す)予定なので、今はスプレッドシートからhtmlに値を渡すところだけの公開になります。（今後編集するかもしれません）

前提としてデータを取得したいスプレッドシートがあり、公開用のhtmlファイルがあることとします。

# 概要
1. GASを使ってスプレッドシートから値を取得する
1. 値を取得したGASをウェブアプリケーションとして公開
1. インラインフレーム要素を使って公開したページを自分のウェブアプリケーションに埋め込む

# GASを使ってスプレッドシートから値を取得する
今回サンプルとして使用するスプレッドシートにはこのように書かれています。
![スプレッドシート.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398251/afff6cb3-7cdd-e770-4515-9898e5a88b00.png)


次に[Google Apps Script](https://developers.google.com/apps-script/)の「新しいプロジェクト」を選択し、「コード.gs」に次のコードを書いていきます。
## コード.gs

```js
function doGet() {
  return HtmlService.createTemplateFromFile("index").evaluate();
}

function doPost(e) {
  var sheet = getSheet('シート1');//スプレッドシートのシート名
  var lastRow = sheet.getLastRow();
  sheet.appendRow([lastRow, e.parameter.value, new Date(), e.parameter.name]);
  return HtmlService.createTemplateFromFile("index").evaluate();//htmlの名前
}

function getSheet(name){
  var ssId = 'スプレッドシートのURLで"d/"と"/edit"に挟まれているID';
  var ss = SpreadsheetApp.openById(ssId);
  var sheet = ss.getSheetByName(name);
  return sheet;
}

function getData() {
  var values = getSheet('シート1').getDataRange().getValues();//スプレッドシートのシート名
  return values;
}
```
## index.html

次に、「HTMLファイル」を選択し名前を「index」としてhtmlファイルを作成します。

![HTMLファイル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398251/2f0b334f-b245-9955-5e0e-59275a8b90df.png)

作成したファイルに次のコードを書いていきます。

```html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <p>
      <?
      var data = getData();
      output.append(data[0][0] + ' ' + data[1][0])
      var pi = data[1][1];
      ?>
    </p>
    <p>円周率は<?output.append(pi)?>です</p>
  </body>
</html>
```

# 値を取得したGASをウェブアプリケーションとして公開
作成したGASをウェブアプリケーションとして公開します。
![ウェブアプリケーションとして導入.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398251/c78e3356-d0ac-c875-f1d5-e38b816da497.png)
※プログラムを編集したあとは「Project version」の名前を変更しないと更新されません。

公開したwebページを見てみると
![webページ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398251/425faab0-0943-b869-dc65-140ef8f2a210.png)
このように値を取得できました！

# 公開したページを自分のウェブアプリケーションに埋め込む
今回はhtmlの要素の１つであるインラインフレーム要素を使って自分のウェブアプリケーションに埋め込みました。

まずは前準備として「コード.gs」を編集していきます。
doGet()を次のように編集します。

```js
function doGet() {
  return HtmlService.createTemplateFromFile("index").evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME).setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
```

最後に自分のウェブアプリケーションのスプレッドシートの値を挿入したい部分に次の要素を挿入します。

```html
<iframe src="https://script.google.com/macros/s/公開したGASアプリケーションのID/exec" class="example1" allowtransparency='true' frameborder="0">読み取れませんでした</iframe>
```
完成！

# 最後に
今回はスプレッドシートの値を取得して自分のウェブアプリケーションに挿入する方法を説明してきました。
3択クイズでは、この方法でスプレッドシートのデータからランダムに問題文を選んで表示し、3つのボタン上に選択肢を表示することができました。また、選択したボタンによって正解か不正解かを判定することもできました。

効率的な方法ではないかもしれないのでもっといい方法があれば教えていただきたいです。
最後まで読んでいただきありがとうございます。
Kicad で Plot した Gerber File を elecrow 向けにリネームする python (適当)

偉い人が Kicad のプラグインとして使える python スクリプト書いてるみたいだけど、
すでに出力されてるやつをリネームすることも何故か結構あるので、主に自分用に置いときます。


```python:elecrow.py
import glob
import re
import os
import sys

args = sys.argv
if len(args) < 2:
    print("Usage: python rename.py foldername_of_gerberfiles")
else:
    path = args[1]
    for x in glob.glob( path + "/*"):
        if re.search(r"-NPTH\.", x) is None:
            y = re.sub(r"([^-]+)\-\w+\.(\w+)",r"\1.\2",x)
            z = re.sub(r"drl$", "txt",y)
            os.rename(x,z)
            print(z)
        else:
            y = re.sub(r"drl$",r"txt",x)
            os.rename(x,y)
            print(y)
```
FigmaのPrototypeで横スクロールをさせる方法

Startup WeekendでサービスのMVPを作ったときにFigmaのPrototype機能を使った横スクロールがなかなかできなかったので忘れないように書いておきます。

ポイントは
① component　② Frame　③ Horizon Scrolling
この3つだけです

①　最初に横にスクロールしたい要素の１つを作成し、Componentを作成します。
　　この時上のバーにある真ん中の◆が4つ並んだアイコンをクリック(またはCtrl + Alt + K)します。
![FireShot Capture 453 - Untitled – Figma - www.figma.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448051/a6d926ed-b49f-9399-93be-0e8fd0aa74db.png)

②　①で作ったcomponentをコピーし、他のインスタンスを作成します。（今回は色を変えました）
　　今回はコピーしましたが、Assetsから持ってきても大丈夫です。
![FireShot Capture 455 - Untitled – Figma - www.figma.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448051/09616250-d210-1d57-4bd3-d6f708d041b7.png)

③　Frameとなっていることを確認します!
![FireShot Capture 457 - Untitled – Figma - www.figma.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448051/c8463649-f09c-9889-b0ad-5d98141fadb9.png)

④　PrototypeのOverview BehaviorをHorizon Scrollingにします。
![FireShot Capture 458 - Untitled – Figma - www.figma.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448051/c266a4c8-0a97-bf83-2e88-34aa47332986.png)

⑤　下のように外側のFrameの枠をずらしたら完成です！！
![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448051/61b28018-391a-fbc8-dd55-df8c597f28f2.gif)

⑥　こんな感じになります
![test2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448051/be3fc5a9-51b7-ac9d-40f5-ea69cf7b625e.gif)


参考になればうれしいです！
シェルスクリプト eval コマンド

正直なところ、あまり使う機会はないかもしれない。
eval コマンドは渡されたパラメータに対して、再度解釈を行う。
以下の例では、today は month2 である。までが単純な echo。
更に、month2 は何だっけ？まで解釈し、February と解釈するのが eval コマンド。

```bash:eval-command.sh
month1=January
month2=February
month3=March
today=month2
echo ${today} # month2
eval echo \$${today} # February
```
【線形代数】一般の行列のグラム行列とランクについて

# 諸定義
一般の行列というのは$A \in \mathbb{K}^{a_r \times a_c}$についてとします．$a_r,a_c$はそれぞれ行列$A$の行（row）と列(col)です．$\mathbb{K} \in \\{ \mathbb{C},\mathbb{R} \\}$で，断りがない限りどちらでも良いということにします．
$\cdot^T$は転置のオペレーター，$\overline{\cdot}$は共役オペレーター，$\cdot^H$は共役転置のオペレーターとします．
例：$a_r = 2, a_c = 3$の場合は以下です．　
$$A=
\left(\begin{matrix}
a_{1,1} & a_{1,2} & a_{1,3} \\\
a_{2,1} & a_{2,2} & a_{2,3}
\end{matrix} \right)$$
それでは始めましょう．
# ランク
$rank(\cdot)$をランクのオペレーターとしておきます．ランクの同値な定義は複数存在しますが，今回は以下を採用します．
>行列$A$のランクとは$A$の非ゼロ特異値の個数

このままでも使いやすいですが，このように読み替えると証明に使いやすくなります．
>行列$A$のランクとは以下の条件を満たす線型独立なベクトル$\boldsymbol{v}$の本数である
$A\boldsymbol{v} \neq \boldsymbol{0}$


# グラム行列らしきもの
$a_r=a_c$の場合，つまり正方行列である$A$に対して$A^H A$はグラム行列と言います．本章では正方行列に限らずグラム行列らしきもののランクについて記述しておきます．ちなみに$A^H A \in \mathbb{K}^{a_c \times a_c}$の正方行列であるのは明らかですね．
結論を最初に書いておくと，$A^H A$のランクについては以下となります．
$$
rank(A^H A)=rank(A)
$$

証明
まず行列$A$を特異値分解します．ユニタリ行列$U \in \mathbb{K}^{a_r,a_r}$,対角行列$\Sigma \in \mathbb{K}^{a_r,a_c}$,ユニタリ行列$V \in \mathbb{K}^{a_c,a_c}$で以下に分解できます．（ユニタリ行列は$U^H=U^{-1}$です．）
$$A = U \Sigma V^H \tag{1}$$
この時$A^H A$は次式となります．
$$A^H A = \left( U \Sigma V^H \right)^H U \Sigma V^H=V \Sigma^H U^H U \Sigma V^H\\\
=V \Sigma_{square} V^H \tag{2}$$
$\Sigma_{square}=\Sigma^H \Sigma$の要素は全て非負の実数ですね．式(1),(2)を見比べると非ゼロ特異値の数が一致することは明らかなので特異値の定義からランクが同じなのは明らかですね．　□

一度証明してしまえば簡単ですね．同時に$A^H A$の特異値（場合によっては固有値）は非負であるということも証明しています．
$rank(A^H A)=rank(A)$という定理から，$A^H A$が正則( $rank(A^H A)=a_c$ )かどうかを簡単に判定することができます．結論は以下です．
>$A^H A$は$a_r<a_c$なる横長行列の時必ず非正則．
$a_r \geq a_c$ならばランク最大状態である$rank(A)=a_c$の場合正則である．

この章のまとめとして次の命題を証明して終わります．
>$A^H A + \lambda I\ (\lambda > 0)$は常に正則．

証明
最初に先ほどと同じ議論から，$A^H A = V \Sigma_{square} V^H$が導けます．
次に読み替えた方のランクの定義を利用します．
$A^H A$に対して$(A^H A)\boldsymbol{v} \neq \boldsymbol{0}$なる$\boldsymbol{v} \in \mathbb{K}^{a_c}$が$r_g=rank(A^H A) \leq a_c$本存在します．
ここで特異値$\sigma_i^{square}(\geq 0)$に対応する$V$の縦ベクトル（列ベクトル）$\boldsymbol{v_i}\\ (i=1,..,a_c)$を考えると，
$$(A^H A)\boldsymbol{v_i}=\sigma_i^{square}\boldsymbol{v_i}$$
となります．つまり非ゼロ特異値に対応するベクトルが$r_g$本あり，ゼロ特異値に対応するベクトルが$a_c-r_g$本存在します．
これらの$\boldsymbol{v_i}$に対して$A^H A +\lambda I$はどう振る舞うか見てみましょう．

$$(A^H A + \lambda I)\boldsymbol{v_i}=(\sigma_i^{square}+\lambda)\boldsymbol{v_i}\neq\boldsymbol{0}$$
となります．$\sigma_i^{square},\lambda$は非負と正なので非ゼロベクトルとなります．$A^H A$とは違い，$A^HA+\lambda I$は全てのベクトルに対して非ゼロとなるため読み替えた方のランクの定義からフルランクとなります．□

時間があれば可視化のグラフを追加で載せておこうかと思います．
WORD2007以降で 2003のテンプレートを開いてうざくない図形作成をしよう

以下のテンプレートを開けば、うざくない図形が作成できる。
C:\Program Files (x86)\Microsoft Office\Office14\Templates\1041\Office Word 2003 Look.dotx
上記はoffice2010のものだが、office2019もフォルダの場所は若干違うが、ファイルは存在する（会社のPCで確認済み）
32it版  C:\Program Files (x86)\ ...
64bit版 C:\Program Files\ ...


図形メニューもチョット違う
個人的にはこっちのメニューの方が何倍も直観的で分かりやすい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/9dbc0957-626c-d414-61f5-2fac6f639f63.png)

通常のメニュー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/3eb96949-6c13-e22f-4f29-c7113a44b7ca.png)

WORDアートもチョット違う
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/482a637a-52ab-6556-bcb4-0d34f62b01d1.png)

通常のメニュー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/44c36b46-f365-6155-bad3-9fa146eeca06.png)
ゲームディレクターを目指す新卒１年目がエンジニアからスタートして学んで良かった事

[グレンジ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/grenge) ８日目担当の kanyuhei です。
2019年4月入社、新卒１年目のグレンジでクライアントエンジニアをやっています。

# ■はじめに
今回、私が書く記事は題名の通り **「新卒１年目で学んで良かった事」** のまとめを書こうと思います。
自分用のメモに近い形ですが、次の新卒１年目の為になると思って自分のありのままの経験を元に書こうと思います。

# ■学んで良かった事
###  **①新卒の特権を出来るだけ使う** 
基本は右も左も分からないのが新卒だと思うので、
 **・失敗して覚える（同じ失敗をしない）
・分からない事はすぐに聞く
・学んだ事はとりあえずどこかにメモる** 
基本は最初１ヶ月ぐらいはこれさえ守ればなんとかやっていけました。

入ったすぐの時はまず開発の流れが全く分からず
フィーチャー確認、デベロップ確認...何それ？って感じで最初は始まったのを覚えています（汗
誰に何を確認して、自分の今やっている物はどこに繋がるのかなど、とにかく全てが分からなかった。

ただ、新卒は注目度も高く、どんな人にも聞きやすく、出来なくて当たり前なので
臆せず色々とチャレンジしてみる事を意識してやってきました。
その分、色々とやらかしましたが（笑）

###  **②自分のタスク量にどれくらい時間がかかるかの見積もり力を鍛える事** 
どんなタスクにも期限はあり、それに着手する際、どのくらい時間がかかるか、現在どのくらいの進捗かなどを把握する必要があります。
そこで自分がやっていたのは、まず **1日に出来る仕事の正確さ** を鍛える事です。
「定時以外は絶対に業務の仕事を行わない」という強い意思のもと開発をしていました。
業務時間内で終わらない仕事は
・そもそもそのタスク量が多いか
・本人の仕事スピードが遅いか
・緊急対応が入った
のどれかなので、ひとまず1日毎に目標を置いてタスクは絶対に達成するようにしていました。
それでもやはり、終わらない仕事はあるものなので、
それは次同じような失敗を踏まないために自分用の学んだ事、失敗した事のメモ帳に書いて
次回の1日目標設定の際に活かすよう対応していました。

###  **③情報共有の大切さ、共通認識を持つ事の重要さ** 
会社では色んな人が働いています。今まで生きてきた背景、価値観など様々なものが違います。
そんな中で一緒に働く仲間、チームとして一つのゴールに向かって開発を進めていきます。
つまり、そのゴールまでにいく道のりが違うと歯車が一気に噛み合わなくなり、ゴールにたどり着けなくなります。

自分が会社に入って最初に驚いた事ですが
隣にいる人にさえSlackでメンションをつけ、伝えたい内容を送信して開発を進めている事です。
これは最初、新卒入りたての自分にとっては分からない現象で、
なぜその短い一文を口頭ではなくチャットで話すのかが理解出来ませんでした。

そして、その理由は日々色んな業務をこなしていくと判明しました。
「あの時相談したあの内容なんだけど..」「昨日、言ってたあれどうなった？」なのどタイミングで
どこかのドキュメントなどの記録に意識的に残さなくても自然と残っている事になっていたのです。
何気ない小さな会話も **チャットベースでコミュニュケーションをとる事でお互いの認識のズレや、
そのほかの開発メンバーの情報共有にもなっていた** 事に気付きました。

なので、何か口頭で相談したい場合があってもまずチャットベースで相談したい内容を書き、その後口頭でも必要ならする。
このような流れが一番お互いの認識のズレが少なく結果的に時間のかからない効率の良い仕事に繋がる事を学びました。

###  **④自分の型を作ること** 
これは人それぞれあると思いますが、自分なりの個人としてのやり方をとりあえず紹介します。
・タスク管理
　　slackの個人チャットをメモ帳変わりに使いタスクを書き出す（終わった文章に取り消し線を入れる）
　　プロジェクト管理用サービスwrikeを使う（スケジュール感をみる時などに使う）
・頭を切り替える方法
　　コンビニに行く
　　タイマーをかけ時間になったら別の事をやる
・リフレッシュ方法
　　沢山寝る
　　定時に帰宅
　　自分がやりたい事をやってみる（趣味）
・モチベーションコントロール
　　この会社に入った理由、この道に進もうと決めた瞬間を思い出す

###  **⑤仕事のしかた、進め方** 
・朝に1日の作業予定を組み立てる
・帰る前に今日の進捗を確認し、朝立てた予定とどこがずれていたかを確認し、そして翌日以降の予定に改善を入れる
・報連相をしっかりおこなう
・作業進捗に合わせて予定を都度調整する事
・２割当て
・どんなタスクにも優先順位をつける事
・アラートを上げる事
・よくわからないまま仕事せず、納得して自分事として働く事
・同じ所で悩む時間が15分でもかかったらすぐ聞く事

# ■まとめ
この約一年間、新しい事ばかりを学び続ける日々で、頭の整理が追いつかない日々を送っていました。
学んだ事はメモはしていても真の意味で理解が出来ていなかったり、頭には入っていなかったりと色々と大変で、
コードを書くだけがエンジニアの仕事ではない事を特に思い知らされた約一年間でした。
ただ、色んな失敗もありましたが、徐々に自分の知識が増え、仕事にも慣れ、出来る事の幅が広がっていく感覚を最近はおぼえます。
入社した当初の時より自分が成長出来ている感覚があるのはとても大切な点だと思うのでこれからも引き続き頑張りたいと思います。
Django pythonのwebフレームワーク

今回はpythonのwebフレームワークについて説明します。

# Django
Pythonで実装されたWebアプリケーションフレームワーク
複雑なデータベース主体のWebサイトの構築を簡単にするのを第一の目的としています。

# 採用例
かなりの大御所のサイトで使用されています。

* Youtube
* DropBox
* Google
* Instagram

などwebサービスの中でも上位のものが使われています。

# 3大フレームワーク
フレームワークの中でも3大の一つとして数えられ
昨今注目を浴びているPythonを使用していることから
学ぶのをおすすめします。

| WEBフレームワーク | 使用言語 |
|:-:|:-:|
|  Django | Python  |
|  Rails |  Ruby |
|Laravel|PHP|
Fastlane pemでpush通知の証明書の更新

### Fastlaneでpush通知の証明書(Apple Push Notification Service)作成

iosアプリを作成している人であればおなじみの、push通知のための証明書、通称「pemファイル」。

こいつの期限が1年なので毎年更新しなくちゃいけないんですよね。

でも前にやったのは結構前だから、やり方調べるところから、、、と、やっていて気づいたら半日終わってた。

なんてことにならないようにfastlaneを使ってコマンド一つでベシっと作成できるようにしましょう。

### fastlaneのインストール
すでにインストール済みの人は飛ばしてください。

```bash
// xcodeコマンドのインストール
$ xcode-select --install

// gemでのインストールだけど、fastlane pemを使う上でrubyの知識は不要
$ sudo gem install fastlane --verbose

// 証明書を作るだけなら不必要 →飛ばしてOK
$ cd <プロジェクトのディレクトリ>
$ fastlane init
```

### 一発で作りたい
対話的に作成したい人は、作成したい場所で下記コマンドでできますが、私は対話形式は面倒なので一撃で作成します。

```bash
// 対話形式でやる場合
$ fastlane pem
[23:12:13]: Your Apple ID Username: <ログインID(メールアドレス)>
...
<色々効かれるので答えていく>

```

```bash
// 一撃で作る場合
$ fastlane pem -u "ログインID(メールアドレス)" -a <Bundle ID> -e <ファイルの出力先ディレクトリ> -f -o <出力ファイル名> 
> password:<パスワード>

// ヘルプの表示
$ fastlane pem -h
```

これで証明書の作成ができました！！

※ちなみに初めてやる時に2ファクタ認証が走ります。この時に1台目の端末がない場合には、6桁のコードの代わりに「sms」と入力して、登録している別の電話番号を選択して、再度6桁のコードを別端末に送ってもらいましょう。

### 注意点
ただ、このFastlaneを使ってできることは、新規で証明書を作成するということだけで、Apple Developper側にある既存の証明書を削除するということはできないよう。
しかも、Apple Developper側では最大2つまでしかpush通知用の証明書を作成することができないので、完全に自動的に更新をするのは今のところ難しそう、、、

App Store Connect APIのページを確認しても削除をするといったAPIは今の所(2019/12/06)見つけられていませんが、もしかしたら今後削除本当の意味での更新ができるようになるかもしれませんね。

App Store Connect API：https://developer.apple.com/documentation/appstoreconnectapi

### 最後に
Fastlaneについての情報がネットにあんまり転がっていなくて、試行錯誤しながら頑張って調べていますが、まだまだ理解が足りない部分が多々あるので、間違っている箇所等があれば指摘いただけると助かります。

次はビルドの提出の自動化を頑張るぞー！
【Docker / php-fpm】docker-php-entrypointの動作

[php公式イメージ](https://hub.docker.com/_/php)のDockefileの内容を確認していたら

```Dockerfile:Dockerfile
ENTRYPOINT：["docker-php-entrypoint"]
（中略）
CMD：["php-fpm"]
```

という記述を見つけてなんぞこれ？となったのでその解説。
php公式イメージで**php起動にオプション付与**したり、
**phpと別プロセスも走らせたりする**ときの一助にはなるかと。
# ENTRYPOINTとCMDが両方ある場合
ENTRYPOINTとCMDがどちらもセットしてある場合、
**CMDの設定値はENTRYPOINTへの引数として渡されます。**
# 今回のケース
今回の場合、CMDに設定されている**php-fpm**は**それ単体でプロセス起動**されるのに、わざわざENTRYPOINTの**docker-php-entrypoint**に**引数として渡される**ことになります。

僕の場合、**CMDにシェルを指定してphpとcronを同一コンテナで動かそう**としていました。
**docker-php-entrypoint**が何をしているか理解しないと想定外の動きをしそうでちょっと怖いですね。
# 先に結論
**似た様なことを考えている人、問題ないのでそのままGOしてください。**

docker-php-entrypoint、以下の単純な処理のためのものです。
CMDにオプションだけがセット　→　**CMDの設定値をオプションとしてphp-fpmを起動**
その他　→　**CMDをそのまま実行**
# 解説
下記が問題のファイルです。単純なシェルですね。

```sh:docker-php-entrypoint
#!/bin/sh
set -e

# first arg is `-f` or `--some-option`
if [ "${1#-}" != "$1" ]; then
    set -- php-fpm "$@"
fi

exec "$@"
```
ざっと解説すると

- 実行時に渡された1番目の引数がオプションかどうかチェック （if文）
- オプションだったら1番目の引数に"php-fpm"、実行時の引数をそれ以降の引数としてセット （set -- php-fpm "$@"）
- 全引数を並べて実行 （exec "$@"）

って流れです。

オプションかどうかは1番目の引数の"-"以降を抜き出したものと、
1番目の引数全体が合致（-で始まるオプションか否か）で判定しています。

**execをechoに変えたシェル**を作って試してみるとわかりやすいと思います。
以下、その場合の例です。
### オプションだけを渡して実行（適当）

```
$ docker-php-entrypoint-echo -f -d
php-fpm -f -d
// php-fpmにシェル実行時の引数が続く
// execの場合、オプション付きのphp-fpmが実行される
```
### その他
```
$ docker-php-entrypoint-echo test.sh
test.sh
// 渡した引数だけが表示される
// execの場合、引数に指定した処理が実行される
```

これで安心して魔改造できますね！
PHPカンファレンス2019 無線LAN(人権)舞台裏

本記事は、[サムザップ Advent Calendar 2019 #1](https://qiita.com/advent-calendar/2019/sumzap1) の12/08の記事です。

### ■はじめに　
　情報シス的なところで社員の皆が働きやすいような環境を整えるお仕事をしています。
仕事以外でも似たようなことをして人のために生きてるのでその活動を紹介します。

### ■PHPカンファレンスとは?

　詳細は[こちら](https://phpcon.php.gr.jp/2019/)を読んでおいてください！
　年数回日本各地で行われているユーザーコミュニティによるイベントです

### ■人権？

　エンジニアイベントに来たのに、スマホのギガを消費する。ありえないですよね？
　登壇される方の発表をツイートしたり記事にして配信したり、ちょこちょこゲームやったり、ネットに繋がっているのは基本的人権とも言うべきエンジニアの権利です。その権利を保障しましょう！！というのがNOC (NetworkOperationCenter)の役割となります。

### ■本題

　じゃあその人権って具体的にどうやって確保しているのさ？っていうのが本記事の内容となります。皆様少々お付き合いください。

## ■人権を確保するための準備

　まず必要なのはメンバーの募集！次に会場仕様書。その次に敷設するための設計図。そして必要な部材調達を行い、部材に設定を入れていき、接続テストという流れになります。

　会場設計図自体は、舞台になる[大田区産業プラザPiO](https://www.pio-ota.net/)からゲットしてきます。
　みんなでわちゃわちゃと、あーする？こーする？これがいい？みたいな話を集まってしつつ、オンラインでバンバン設計図を書いていきます。大体これが2ヶ月くらい前に始まります。
　結果完成するのがこういった図面。
　今回特に気をつけたのは、人の導線でLANケーブルを踏ませないこと。それにより配線が大分大回りしているのがわかると思います。
<img width="600" alt="1Fホール" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154680/b612f9a3-0670-b62b-32b9-df4d4aac832e.jpeg">
<img width="600" alt="4Fホール" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154680/1a936759-a6fe-fa8b-debc-0ad308ae511b.jpeg">

　このあたりが大体固まって来たら、PoEスイッチは何台要るよね、APは何台で、ケーブルはxxメートルがyy本！というのが出てきます。
　大体ザッと、APは30台以上、スイッチは10台以上で、ケーブル総延長は1kmを超えてきます。
　そこまで出てきたら、あとはHotStageと呼ばれる事前設定大会を行います。4日くらいかけて分担し、それぞれの機器を設定したり、各APを管理するCiscoWLCをセットアップ・設定し、各フロア拠点から接続するVPN設定を行ったりしていきます。
　最後に各機器を接続してみんなのスマホで接続確認を行って完了！
　大体インフラ作業は事前準備で8割方終わっているのが常ですが、例に漏れずここでもそのような形となります。

## ■前日・当日準備
　さあ！あとは肉体労働のお時間です。
　事前に設定した機器を搬入し、実際に敷設していきます。予算の都合上前日に借りているのは1F大展示ホールのみなので、前日は全機器を纏めてフロア拠点毎に置いておき、1Fの敷設のみ実施します。

　当日になると朝7時半くらいに集合。ミーティングの後フロアがオープンする8時から開場の10時までスピード勝負。実際敷設してから
**あれ？繋がらないぞ！**
**この壁コンセント電源来てない！**
などのトラブルを乗り越えつつ、開場までひたすら労働労働労働。そして無事開場を迎えます。

## ■本番！
　10時になると続々と参加者の皆さんが入場してきます。監視ツールをにらめっこしつつ、ヤバそうなところがもしあれば予備機を増設、緊急対応、などを行いますが今回は無事大きなトラブルもありませんでした。同時接続ピークも700を越えて安定。無事人権問題を捌ききり、フィナーレへ向かいます。

## ■撤収！
　借りた物は返さなくてはいけません。PiOへ原状復帰状態でお返しするためにも敷設した物をひたすら回収していきます。最後は綺麗に箱詰めして配送業者にお渡ししなければいけないので、最長60mのLANケーブルも綺麗に八の字巻きしながら片付けていきます。
　最後に配送業者を見送り、集合写真を撮って、現地打ち上げに参加して終了です。

## ■延長戦！
愉快な肉体労働メンバーの会合はまだまだ続きます・・・
<img width="600" alt="4Fホール" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154680/292f03f0-e117-7f0f-eed9-a4d99b700a12.jpeg">

こんな世界に興味のある方は、是非来年PHPカンファレンス2020！にスタッフとして参加してみてください！

※NOCコアスタッフとして[CONBU](https://conbu.net/)の多大なる協力をいただいています

明日は我らがCTO @shirai_suguru さんの記事です
【C++/OpenSiv3D】波の背景

## 説明

このような波の形の `Polygon` を作成し描画するサンプルを紹介します。

![20191206-230301-636.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30255/92ed27c6-8316-6b9e-a838-d709358f0788.png)

## サンプル

```C++
# include <Siv3D.hpp> // OpenSiv3D v0.4.2

class WaveBackground
{
private:

	Polygon m_polygon;

public:

	WaveBackground() = default;

	explicit WaveBackground(const Rect& rect, double distance = 4.0)
	{
		const Vec2 br(rect.x + rect.w, rect.y + rect.h);
		const Vec2 bl(rect.x, rect.y + rect.h);
		const int32 samples = static_cast<int32>(rect.w / distance);

		Array<Vec2> points;

		for (int32 i : Range(0, samples))
		{
			const double x = Math::Lerp(rect.x, rect.x + rect.w, static_cast<double>(i) / samples);
			const double y = rect.y + rect.h * 0.75 - Math::Sin(x * 0.5_deg) * (rect.h * 0.1);
			points.emplace_back(x,  y);
		}

		points << br << bl;

		m_polygon = Polygon(points);
	}

	void draw(const ColorF& color) const
	{
		m_polygon.draw(color);
	}

	void drawWireframe(const ColorF& color) const
	{
		m_polygon.drawWireframe(1.0, color);
	}
};

void Main()
{
	Scene::SetBackground(Palette::White);

	double distance = 5.0;
	bool showWireframe = false;
	WaveBackground waveBackground(Scene::Rect(), distance);

	while (System::Update())
	{
		waveBackground.draw(Palette::Skyblue);

		if (showWireframe)
		{
			waveBackground.drawWireframe(Palette::Blue);
		}

		if (SimpleGUI::Slider(U"Distance: {:.0f}"_fmt(distance), distance, 1.0, 80.0, Vec2(20, 20), 140, 140))
		{
			waveBackground = WaveBackground(Scene::Rect(), distance);
		}

		SimpleGUI::CheckBox(showWireframe, U"Show wireframe", Vec2(20, 60));
	}
}
```

## 実行結果

![20191206-230311-940.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30255/5e4e247a-f909-c16b-7433-f32edb15f2d0.png)
react + marked + highlight の設定や拡張

# はじめに

[いなたつアドカレ](https://qiita.com/advent-calendar/2019/allinatatsu)の六日目の記事です。

今回は前回に続いてMarkdownをReactで表示するために、htmlに変換する部分です。
あとは、シンタックスハイライトをする方法ですね。


## じっそー


まずはインポートとインスタンスの生成

```js
import marked from 'marked';
import hljs from 'highlightjs'
import 'highlightjs/styles/monokai.css'　// monokaiの場合
const r = new marked.Renderer()
```

そして、markedの拡張(変更)



```js
// h1,h2,h3 ....
r.heading = (text, level) => {
    let escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
    return (
        `
            <h${level}>
                ${text}
            </h${level}>
        `
    )
}
```
h1などのタグの拡張です。
rは先ほどインスタンス化したものですね。
headingがh1,h2などのタグにあたります。

これを使うことで、指定したclass名を付与し、cssによる管理が可能になります。

このほかにも様々な記法をHTMLタグに変換する過程で拡張できます。

以下が拡張できるものです(公式リファレンス参考)

ブロック要素

- code(string code, string infostring, boolean escaped)
- blockquote(string quote)
- html(string html)
- heading(string text, number level, string raw, Slugger slugger)
- hr()
- list(string body, boolean ordered, number start)
- listitem(string text, boolean task, boolean checked)
- checkbox(boolean checked)
- paragraph(string text)
- table(string header, string body)
- tablerow(string content)
- tablecell(string content, object flags)

インライン要素

- strong(string text)
- em(string text)
- codespan(string code)
- br()
- del(string text)
- link(string href, string title, string text)
- image(string href, string title, string text)
- text(string text)


次にインポートしたmarked本体の設定で、。これでhighlight.jsを有効にできます

```js
marked.setOptions({
    highlight: function (code, lang) {
        return hljs.highlightAuto(code, [lang]).value;
    }
});
```

そして、以下のようにすることで、markdownをhtmlに変換します

```js
marked(md, { renderer: r })
```
mdに入ってる値をmarkedを使って変換しています。ここをstateなどを指定することで、reactっぽくなりますね。

最後に前回と組み合わせて、stateのbodyに格納されたmarkdownをhtmlに変換しコンポーネント内部に展開して表示する部分を記しておきます。

```js
<span dangerouslySetInnerHTML={{ __html: marked(state.body, { renderer: r }) }} />
```

以上がreact + markedown + highlight の使い方になります。