OmniAICreator/Qiita-1.07M huggingface dataset:
(同一アカウントでも) aws cliの実行時に2 factor/MFAの入力を強制する 

自分用IAMユーザのAccess key / secret keyが何かの間違いで流出 & 悪用されたら嫌ですよね！
ということで、aws-cliを利用する時にMFAの認証を通したいときのやり方、何個か記事はあるんですが、微妙に色んな情報が混じっていてわかりずらかったので、最短のパスをここにまとめてみました。

# 全体の流れ
- 必要な権限を持ったassumeするためのIAM Roleを作成
- ↑で作ったRoleをassumeして使えるIAM Userを作成。
- ↑で作ったUserにMFAデバイスの紐付けを行う。
- ~/.aws/credentials, ~/.aws/config の設定
- `aws` コマンドを実行してみる！


# IAM Role作成
trusted entityには"Another AWS account" を選択。ここが地味に混乱しやすいポイントですが、同一のアカウントで使う場合も、これを選択して、そのアカウントのIDを入力すればOKです。プラスで、`Require MFA` にチェックを入れてroleの作成をしていきます。
Roleの権限は、aws-cli を実行するユーザに持たせたい権限(EC2操作、S3操作、Admin etc...)にしてください。
![スクリーンショット 2018-08-23 13.06.34.png](https://qiita-image-store.s3.amazonaws.com/0/91324/fcf74a44-07b9-756b-f967-644f28929f0d.png)


# IAM User作成
Programmatic accessを有効にした、何の権限も持たないIAM Userを作成し、以下のpolicyを直接attachする(CREATED_ROLEの部分は先の工程で作ったrole名を入力)。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::123456789012:role/CREATED_ROLE"
        }
    ]
}
```


# IAMユーザにMFA deviceの紐付けを行う
作成したIAMユーザの詳細画面を開き、"Security Credentials"タブ -> Assigned MFA device を選んで設定する。


# ~/.aws/credentials, ~/.aws/config の設定
Key pair, Role, MFAの設定は先に作成したモノに置換してください。

```yaml:~/.aws/credentials
[test_iam_user]
aws_access_key_id=ACCESS_KEY_OF_CREATED_USER
aws_secret_access_key=SECRET_KEY_OF_CREATED_USER
region=ap-northeast-1
```

```yaml:~/.aws/config
[profile test]
role_arn = arn:aws:iam::123456789012:role/CREATED_ROLE
source_profile = test_iam_user
mfa_serial = arn:aws:iam::123456789012:mfa/CREATED_MFA
region=ap-northeast-1
```

# aws コマンドを実行してみる！
MFA codeの入力が求められればOK!

```bash
$ aws --profile test s3 ls
Enter MFA code:
```

<br/>

IAM Userとしては`AssumeRole`の権限しか持っておらず、新しいセッションでこのRoleをassumeしてAPIを実行しようとする場合、MFA codeの入力が求められるので、万一、IAM Userのkey pairが流出しても悪さされません！！


# 参考
AWS CLI 経由で AWS リソースへのアクセスを認証するには、どのように MFA トークンを使用したらよいですか?
https://aws.amazon.com/jp/premiumsupport/knowledge-center/authenticate-mfa-cli/

AWS CLIがAssumeRoleによる自動クレデンシャル取得とMFAに対応しました！
https://dev.classmethod.jp/cloud/aws/aws-cli-supports-assume-role-credentials-provider-and-mfa/

(タイトルなしの英語記事)
https://dogsec.io/2017/06/03/awscli-mfa.html

初めてのAssumeRole
https://dev.classmethod.jp/etc/sugano-005-s3/
(直接は関係ないですが、`AssumeRole` とは何ぞや？ってのがキレイにまとまっていました)
痒いところに手が届くmongoidの検索条件集

## はじめに
本記事は、mongoidでこういう検索条件で検索をしたいのだけど、どうやったらいいのか？という痒いところに手が届くように、その他のmongoidの記事では触れていない部分に触れていきます。
サンプルが最初は少ないですが、順次更新していく予定です。
RubyでMongoDBを使おうとする人のお役に立てれば幸いです。

## 目次

- その1：件数を指定して取得したい場合
- その2：特定の条件を含めない結果が欲しい場合
- その3：特定のモデルとアソシエーションを組んでいるモデルがデータとして存在するかを判定したい場合

## 軽く前提事項を確認
`mongoid` はRailsにおける ActiveRecordのような感覚で、MongoDBを扱えるようにしたgemです。

## 実行環境
- MongoDBのバージョン ： 3.2.11
- mongoidのバージョン : 4.0

#### 事前にbrewの以下のコマンドでMongoDBを入れておくこと
- 特に何も指定せずに `brew install mongodb` でインストールすると最新版になるため、今回の記事のバージョンを指定する場合は、 `brew install mongodb@3.2` という形でインストールすること  
- 今回の場合は、特に指定しないでインストールしても問題ない( `version 3.4.9` 時点では動作検証済み)

```ruby
$ brew install mongodb
```

# 検索条件アレコレ

## その１：件数を指定して取得したい場合
- 例えば、ヒットする条件のうち20件だけを取得してみる

#### `limit(整数)` を使う
```ruby
# Rails consoleにて実施

# Userの作成日の降順で20件を取得
# ちなみに末尾の.to_aはmongoidのクエリを発行するためのメソッド
# .to_aと同様に.firstや.lastでもクエリが発行される
> users = User.order_by(:created_at => "desc").limit(20).to_a
=> [#<User _id: ユーザーID,　created_at: 日付, updated_at: 日付]
# 20件が取得出来ている事を確認
> users.count
=> 20

```

- ActiveRecordのように `User.last(20)` のように最後の20件を取得みたいなことは出来ないので注意

```ruby
# エラーになる
> User.last(20)
ArgumentError: wrong number of arguments (given 1, expected 0)
```

## その2：特定の条件を含めない結果が欲しい場合
- 例えば、hogeという名前じゃないユーザーを複数件取得したい

#### `モデル名.nin(検索条件)`　を使う

```ruby
# Rails consoleにて実施

# nin は not inの意味
> users = User.nin(name: "hoge").limit(20).to_a
=> [#<User _id: ユーザーID,　created_at: 日付, updated_at: 日付]
```

## その3：特定のモデルとアソシエーションを組んでいるモデルがデータとして存在するかを判定したい場合

#### `has_モデル名?`　を使う

* 例1）userモデルがhas_manyでblogモデルを持っている場合(`has_複数形?`)

```ruby
user.has_blogs?
=> true
```

* 例2）hogeモデルがhas_oneでfugaモデルを持っている場合(`has_単数形?`)

```ruby
hoge.has_fuga?
=> true
```

## まとめ
mongoidに関する検索条件などに関する記事が少ないように感じたので投稿させて頂きました。
これを機に使ったことがない方は試しにmongoidを使ってみてはいかがでしょうか。
また、不備などありましたら、ご指摘頂ければ幸いです。
spring-bootでデータソースをプロパティでなくコードで定義

通常、spring-bootでデータソースを定義するには以下のようにプロパティ等で設定するが、従来のように```@Bean```で定義も出来る。

```
spring.datasource.url=jdbc:postgresql://192.168.10.23:5432/testdb
spring.datasource.username=postgres
spring.datasource.password=xxxx
```

# ソースコード

```xml:pom.xml
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.3.RELEASE</version>
	</parent>

	<properties>
		<java.version>10.0</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
```

以下のように、```DataSource```を返す```@Bean```定義を作っておけばそれを使ってくれる。ここではとりあえずの動作確認にPostgreSQLの```PGSimpleDataSource```を使用している。

```java
import javax.sql.DataSource;

import org.postgresql.ds.PGSimpleDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;

@SpringBootApplication
public class App implements CommandLineRunner {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args).close();
    }

    @Autowired
    JdbcTemplate t;

    @Bean
    public DataSource dataSource() {
        PGSimpleDataSource p = new PGSimpleDataSource();
        p.setUrl("jdbc:postgresql://192.168.10.23:5432/testdb");
        p.setUser("postgres");
        p.setPassword("xxxx");
        return p;
    }

    @Override
    public void run(String... args) throws Exception {
        t.query("select * from users", (e) -> {
            System.out.println(e.getInt("user_id"));
        });
    }
}
```

バリエーションとして```@ConfigurationProperties```でプロパティをファイル等から読み込む方法もある。

```
my.datasource.postgres.url=jdbc:postgresql://192.168.10.23:5432/testdb
my.datasource.postgres.user=postgres
my.datasource.postgres.password=xxxx
```

```java
    @ConfigurationProperties(prefix = "my.datasource.postgres")
    @Bean
    public DataSource ds() {
        return new PGSimpleDataSource();
    }
```

# 参考URL
* https://stackoverflow.com/questions/28821521/configure-datasource-programmatically-in-spring-boot
【java】アルファベット1種禁止縛りでHello, world!【縛り】

#概要
Javaでアルファベット1種禁止（a~zのうち1種類を使わずに書く）でどのアルファベットが抜いても書けるかを検証した。ただの遊び。
#ルール
1.java10,Windows10
2.コンパイルはjavac, 実行はjavaでオプションなし（というかEclipseで書いて実行）
3. 標準出力にHello, world!と出力する
4. 余計な標準出力、エラー出力は禁止（改行はOK）
5.アルファベットを1種類だけ使用禁止
6.大文字小文字は区別なし
7.外部ファイル禁止（Java標準ライブラリのみ可能）
8.ユニコードエスケープ禁止（2018-08-26追記）※詳細は後述
#結論
可能：bfhjklpquwxyz
不可能：acdegimnorstv
#詳細
大体アルファベット順に縛ったコード書いてる。
##fjkqxz
普通に書いたHelloWorldに出てこない。ちなみに変数名、クラス名はアルファベット使わないように日本語にしてる。クラス名にアルファベット以外がつかえることを利用してる人っているのかな……。（教育用のソースコードに使われてたのを1回見た。）

```java:ハローワールド.java
class ハローワールド {
	public static void main(String[] 引数) {
		System.out.print("Hello, World!");
	}
}
```
##b
interface内のメソッドはpublicが暗黙的に加わるのでmain文でも書く必要がなくなる。java7か8からの機能だった気がする。ただ結構ほかのところで使われてる文字が多いのでbしか対処できない。

```java:ハローワールド.java
interface ハローワールド {
	static void main(String[] 引数) {
		System.out.print("Hello, World!");
	}
}
```
#hlpw
文字コードをフォーマット形式で入力してHello, worldにしか含まれてる文字列を使わないようにする。printfではなくformatにすることでpを使うことを回避し、interfaceにすることでpublicでplを使うことを回避してる。

```java:ハローワールド.java
interface ハローワールド {
	static void main(String[] 引数) {
		System.out.format("%c%c%c%c%c, %c%c%c%c%c!",72,101,108,108,111,87,111,114,108,100);
	}
}
```
#uy
s[y]stem.o[u]tにはいっているのでどうにかしてこれを使わずに標準出力をする。
ScriptEngineというスクリプト言語を実行できるクラスがあって、スクリプトで出力を行うと標準出力される。
ただScriptEngineを取得するときにgetB[y]Nameメソッドを使うので、これをgetClass, getMethod,invokeを使い文字列から実行し、文字列ではyを数字から取得して解決する。

```java:ハローワールド.java
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

interface ハローワールド {
	static void main(String[] 引数) throws Exception {
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = (ScriptEngine)manager.getClass()
				.getMethod("getEngineB"+(char)121+"Name", String.class).invoke(manager, "javascript");
		String script = "print('Hello, World!')";
		engine.eval(script);
	}
}
```
#縛れない文字と理由
##acdgimnorstv
static void main(String[] 引数)が絶対必要なため、これに含まれているアルファベットは抜くことが出来ない。これがないとそもそも実行できない。これ対処する方法あるんだろうか。
（2018-08-26追記）JavaFXのApplicationを継承すればmain文を書かなくていいという情報を得た。

```java:ハローワールド.java
public class ハローワールド extends javafx.application.Application{
	public void start(javafx.stage.Stage ステージ){
		System.out.print("Hello, World!");
	}
}
```
ただこれでもほとんどの文字が使われていてどの縛りも解決しなかった。mはSyste[m].out使わなければいけるんだけど、ScriptEngine[M]anagerは使えないし、[m]ethodとna[m]eが使えないのでリフレクションでごまかせない。

##e
uyと同じくSyst[e]m.outに入っているのでこれを使わずに出力できればいいのだが、Script[E]ngin[e]に入ってしまっているし、文字列から取得しようにもそもそもg[e]tClassに入ってる。というかg[e]tにはいっているので何かしらを取得するメソッドが使えない。そうでなくてもかなり使われやすいアルファベットなので引っかかりやすい。
#終わりに
以上より
可能：bfhjklpquwxyz
不可能：acdegimnorstv
となる。main文が邪魔すぎる。eはどうにかして解決する方法がありそうなんだけど……。
やりかたがあったら教えてください。
fizzbuzzあたりをやっても面白いかもしれない。

#（2018-08-26追記）ユニコードエスケープ禁止
[コメント](https://qiita.com/ki_ki33/items/319e2cda34df77c945f2#comment-4814f0c0cbcb10cba6af)で情報を頂いた。Javaではユニコードエスケープ（\uxxxx）形式でソースコードを書ける。これを使えば理論上16進数のa~fとuを合わせたabcdefuしか出てこず、a~fはユニコードエスケープに変換してもそれぞれアルファベットを含まないので、各アルファベットのみをユニコードエスケープに変換すれば解決する。u以外はコードに関係なく縛ることが可能になる。それだとあんまり縛る意味が無い気がするので自分の縛りでは禁止とする。
こういう変なことしてると普通のプログラムでは使わないような情報が入ってきて面白い。
Markdownファイルをリアルタイムプレビュー出来るvmdを入れてみた

# Markdownファイルのリアルタイムプレビュー

一通り使ってみたが、冷静に考えると、様々なリアルタイムプレビューツールがあるので、別にこの**vmd**にこだわる必要は一切ないと思った。


一応リンク先。
[https://github.com/yoshuawuyts/vmd](https://github.com/yoshuawuyts/vmd)


# インストール方法

yarn信者なので、yarnで入れた。

`yarn global add vmd`


npmならこう

`npm install -g vmd`


# 使い方

`vmd README.md`


とてもシンプルに使える。Electronで作ったであろう画面がでろーんと出てきて、markdownの中身を表示するので、後は、markdownファイルを修正して行けば良い。
ファイルを保存したら、自動的に画面が更新される。


# 既に出ている結論

日本語圏には、[previm](https://github.com/previm/previm)という素晴らしいツールが既に存在しているので、このツールを使うメリットはほぼないと思った。
だが、Vimがメインエディタではない人にとっては、有用なのかもしれない。
後続関数のpipeについて

後続関数pipe()の処理についてのメモ
pipe()の機能は2つあり

 - 引数を変更して渡すことができる
 - Defferredオブジェクトの遷移状態の起点をpipe()で示した位置にし、チェーンさせることができる。例は以下の通り。



```js:js
//非同期処理
 const foo = () => {
  var d = new Deferred();
  setTimeout(() => {
    alert('foo');
    d.resolved();
  }, 500);
 };

//非同期処理
const bar = () => {
  var d = new Deferred();
  setTimeout(() => {
    alert('foo');
    d.resolved();
  }, 1000);
};

//同期処理
const baz = () => {
    alert('foo');
};

foo().done(bar).done(baz);　　//発生順は、foo baz bar
foo().pipe(bar).done(baz);　　//発生順は、foo bar baz
```
<br>
チェーンで書かれているので、期待する発生順は、foo => bar => baz

しかし、１つめではfoo => baz => barになる
done()で設定する後続関数は、fooで作成されたDefferredオブジェクトの状態に依存するため、fooが発生したとき、barとbazの処理が可能になる。そのため、同期処理であるbazの方が早く処理が終わるため、発生順は、foo baz bar。
<br>

2爪の処理では、pipe(bar)としている。その結果、barで作成されたDefferredオブジェクトに状態が依存するようになるため、barの発生をまち、bazが発生する。
AWS Lightsail でwordpress は.htaccessを使えないようだ

開発中と言うこともあって、とりあえずIPでフィルターをかけたかったのだが、表題の通り、.htaccessが無効らしい。その変わりに次の場所に以下のファイルがあるので同様に記載してapacheを再起動すればOK

/opt/bitnami/apps/wordpress/conf/htaccess.conf

htaccess.confの一番下に、IPフィルターをいつもの要領で記載
![スクリーンショット 2018-08-23 21.25.11.png](https://qiita-image-store.s3.amazonaws.com/0/105531/0aaedefb-f3d2-4153-f3f0-819cc176fce1.png)

apache再起動のコマンドは

![スクリーンショット 2018-08-23 21.26.38.png](https://qiita-image-store.s3.amazonaws.com/0/105531/563442ac-282c-fc90-f071-283c61e50128.png)

無事にフィルターがかかったかどうかを確認。
AWS Lightsail を使って5分でwordpressを構築する

###お手軽にWordpressを構築したいのであればLightsail


AWSコンソールからログイン→Lightsail
![スクリーンショット 2018-08-23 20.51.20.png](https://qiita-image-store.s3.amazonaws.com/0/105531/3a9f1cfe-1da2-0099-c27f-ab16374f6d55.png)

プラットフォームはそのまま

![スクリーンショット 2018-08-23 20.52.05.png](https://qiita-image-store.s3.amazonaws.com/0/105531/e2e3729e-d373-2fc6-0bb0-301d407f65ab.png)

画面をスクロールしてインスタンスの作成ボタンを押せばほら・・・
![スクリーンショット 2018-08-23 20.52.53.png](https://qiita-image-store.s3.amazonaws.com/0/105531/7b1b5b15-715b-765c-10d0-efb114992375.png)

数秒でインスタンスが起ち上がる！

![スクリーンショット 2018-08-23 20.53.40.png](https://qiita-image-store.s3.amazonaws.com/0/105531/22b2a6f4-e12f-6de0-5fe5-df4c26638601.png)

早速SSH接続を試みるのだが、「アカウントページ」からLightsailDefaultPrivateKey-ap-northeast-1.pemをダウンロードして、.sshフォルダに格納、マックのコンソールからコマンドを叩けば

![スクリーンショット 2018-08-23 20.58.37.png](https://qiita-image-store.s3.amazonaws.com/0/105531/5cd44262-032a-c795-5491-40402bd7ffef.png)

あっと言う間にSSH接続が確立。

##続けてWordpressの初期設定へ
SSH接続したカレントディレクトリにて以下のコマンドを入力

cat bitnami_application_password

するとwordpressのパスワードが表示されるのでメモし、 
http://ipアドレス/wp-admin
をブラウザで開くと、管理者ログインページ。

User →　user
Pass →　上でメモったパスワード

これでwordpressにログインが完了する。
後は煮るなり焼くなり。
さくらVPSでPHPプログラムからメールを送信できるようにする

メール送信は、postfixを使います。

# Postfixをインストール

```
yum -y install postfix
```

# Postfixの設定を更新

```
vi /etc/postfix/main.cf
```

### ドメイン関連

```
#myhostname = host.domain.tld
#myhostname = virtual.domain.tld
myhostname = {ドメイン}
```

```
#mydomain = domain.tld
mydomain = {ドメイン}
```

### インタフェース関連
 
```
inet_interfaces = all ← 行頭 # 削除
#inet_interfaces = localhost ← 行頭 # 追記
```

### IPv6に未対応対策

```
# Enable IPv4, and IPv6 if supported
#inet_protocols = all
inet_protocols = ipv4
```

### スプール

```
# "Maildir/" for qmail-style delivery (the / is required).
#
#home_mailbox = Mailbox
home_mailbox = Maildir/ ← 行頭 # 削除
```

### SMTP認証の設定
メール送信用サーバーとして利用可能にするため、以下を最後に追記。

```
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_recipient_restrictions = permit_sasl_authenticated, reject_unauth_destination
```

# Postfixを起動

```
service postfix start
chkconfig postfix on
```

# Submissionポート設定

Postfixの設定を開く。

```
vi /etc/postfix/master.cf
```

下記内容に更新。

```
# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: "man 5 master").
#
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# 　　　　　　(yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp　　　inet n　　　-　　　n　　　-　　　-　　　smtpd
submission inet n　　　-　　　n　　　-　　　-　　　smtpd ← 行頭 # 削除
# -o smtpd_enforce_tls=yes
　-o smtpd_sasl_auth_enable=yes ← 行頭 # 削除
　-o smtpd_client_restrictions=permit_sasl_authenticated,reject ← 行頭 # 削除
```

# Postfixを再起動

```
service postfix reload
```
Eclipseのdefファイル

Eclipse(MinGW)で、ビルド時に作成されるdefファイルについてご教示願います。
C++で、DLLを2つ(A.dll、B.dll)作成し、defファイルも作成してます。

A.dllは、アプリ.exeで動的リンクします。
B.dllは、A.dllに暗黙的リンクします。

B.dllのdefファイルの中身を見ると、EXPORTSに
externとextern "C"で定義した関数、変数が序数付きで書かれていました。

質問ですが、Eclipseでdefファイルを作成する場合、
・extern/extern "C"で定義した関数、変数は全部defファイルに書かれる仕様でしょうか？
・エクスポートしたい関数、変数は任意に設定できないのでしょうか？
・序数を付けないようにすることは可能でしょうか？


Visual Studioだとdefファイルは、自分で作成する必要があり、エスクポートしたい関数、変数は任意で設定でき、序数も省略できるのでEclipseでも同様のことが出来ないか？が知りたいです。

補足として、
Eclipseは、defファイルの作成する設定項目があり、ビルドした時にdefファイルが作成されるという認識です。

よろしくお願いいたします。
LINEに本日開催のインフラ勉強会を通知する

## 対象者
 - インフラ勉強会に参加している人
 - インフラ勉強会に興味がある人
 - とりあえずGASでなにか作ってみたい人

## 背景
最近<a href="https://wp.infra-workshop.tech/">インフラ勉強会</a>（Discordを使用して行われるオンラインの勉強会）に参加することが増えてきたので、その日開催される勉強会のタイトルと時間を毎日LINEに通知するようにGoogleAppsScriptとLineNotifyを使って組んでみました。

## 準備
#### Googleアカウントの発行
Googleアカウントの発行(GmailもっていればOK)をしましょう。
#### アクセストークン取得
まずLineNotifyのアクセストークンを<a href="https://notify-bot.line.me/ja/">こちら</a>から発行してください。

## 実装
Googleスプレッドシートで新規シートを開いてツールからスクリプトエディタを選択します。Google Apps Scriptのエディタが開きますので、下記コードを実装します。

```gas:infra.gs
var LINE_NOTIFY_TOKEN = [取得したアクセストークン];
var LINE_NOTIFY_API = "https://notify-api.line.me/api/notify";
var INFRA_CALENDAR = "https://wp.infra-workshop.tech/events/";

function sendInfraSchedule() {
  var today = new Date();
  var targetYMD = today.getYear() + "-" + ("0" + (today.getMonth()+1)).slice(-2) + "-" + ("0" + today.getDate()).slice(-2); //YYYY-MM-DD形式
  var bodyItem = ["-本日のインフラ勉強会-"];
  var targetURL = INFRA_CALENDAR + targetYMD;
  
  var searchTagTitle = "<h3 class=\"tribe-events-list-event-title summary\">";
  var searchTagTitleStart = " rel=\"bookmark\">";
  var searchTagA = "\t</a>";
  var searchTagDateStart = "<span class=\"tribe-event-date-start\">";
  var searchTagDateEnd = "\t</div>";
  
  var response = UrlFetchApp.fetch(targetURL);
  var html = response.getContentText("UTF-8");
  
  //タイトルの個数取得
  var num = html.split(searchTagTitle).length - 1;
  
  var index = 0;
  
  for (var i = 0; i < num; i++) {
    //タイトルの取得
    index = html.indexOf(searchTagTitle);
    if (index !== -1) {
      html = html.substring(index + searchTagTitle.length);
      index = html.indexOf(searchTagTitleStart);
      if (index !== -1) {
        html = html.substring(index + searchTagTitleStart.length);
        index = html.indexOf(searchTagA);
        var title = "";
        if (index !== -1) {
          title = html.substring(0, index).trim();
        }
      }
    }
    
    //開始時刻の取得
    index = html.indexOf(searchTagDateStart);
    if (index !== -1) {
      html = html.substring(index + searchTagDateStart.length);
      index = html.indexOf(searchTagDateEnd);
      var date = "";
      if (index !== -1) {
        //タグを削除した状態の時刻を抽出
        date = html.substring(0, index).trim().replace(/<("[^"]*"|'[^']*'|[^'">])*>/g,"");
      }
    }
    bodyItem.push(date + " > " + title);
  }
  if (bodyItem.length == 1) {
    bodyItem.push("今日の予定はありません。");
  }
  _sendMessage(bodyItem.join("\n"));
}

function _sendMessage(msg) {
  // 認証情報のセット
  var headers = {
    "Authorization": "Bearer " + LINE_NOTIFY_TOKEN
  };
  // メッセージをセット
  var payload = {
    "message": msg
  };
  // 送信情報をまとめる
  var options = {
    'method' : 'post',
    'contentType' : 'application/x-www-form-urlencoded',
    'headers': headers,
    'payload' : payload
  };
  Logger.log(options);
  // 実際に送信する
  var response = UrlFetchApp.fetch(LINE_NOTIFY_API, options);
  Logger.log(response);
}
```
なんかスマートじゃないコードですが、とりあえず動きます^^;
ご指摘いただければリファクタリングしたいと思います。

## トリガーの設定
 - Google Apps Script の「編集」 - 「現在のプロジェクトのトリガー」を選択
 - 新しいトリガーを追加
 - 実行欄にsendInfraSchedule
 - イベントに　「時間主導型」「日タイマー」「午前8時～9時」に設定　※時間はお好みで

以上で完了です！

それでは良いインフラ勉強会ライフを！
reduceで配列の1つめの要素に処理が当たらない問題

reduceで処理をしていて、１つ目の要素に処理があたらない問題が発生した。
例えば、以下の配列に、「フルーツ：」の文字列を付け足して、一つの文字列として生成したい場合。

期待するのは、"フルーツ:りんごフルーツ:ばなな,フルーツ:なし,フルーツ:ぶどう,"だが

```js:js
const arr = ['りんご', 'ばなな', 'なし', 'ぶどう'];
const result = arr.reduce((previousValue, currentValue) => {
  const name = 'フルーツ:' + currentValue;
  return previousValue + name;
});
console.log(result);
//"りんごフルーツ:ばなな,フルーツ:なし,フルーツ:ぶどう,"
```

1回目の処理で’りんご’は'previousValue'に入り、'currentValue'にばななが入るため、'りんご'に処理は当たらない。
<br>

実はreduceは第二引数を取れることがわかった。

```js:js
const arr = ['りんご', 'ばなな', 'なし', 'ぶどう'];
const result = arr.reduce((previousValue, currentValue) => {
  const name = 'フルーツ:' + currentValue + ',';
  return previousValue + name;
}, '');
console.log(result);
//"フルーツ：りんご,フルーツ:ばなな,フルーツ:なし,フルーツ:ぶどう,"
```
reduceの第2引数に空文字をいれることで、'previousValue'は空文字になり、'currentValue'に’りんご’が入ることができる。
`git log --pretty=format` で tagを表示する方法


「`git log --pretty=format` で tagを表示する」とはつまり、

```
[2018-07-27 23:13:04 +0900] ec017df : Merge branch 'b3.3_4.6'
[2018-07-10 23:09:09 +0900] cc0b4f3 : Fix IncursionMods
```

↑を↓にしたいってことです。

```
[2018-07-27 23:13:04 +0900] ec017df : Merge branch 'b3.3_4.6' tag: v3.3_4.6
[2018-07-10 23:09:09 +0900] cc0b4f3 : Fix IncursionMods
```

## tl;dr

```sh
# 色なし
git log --pretty=format:'[%ad] %h : %s %D' --date=iso --decorate-refs=tags

# 色付き
git log --pretty=format:'%C(yellow)[%ad] %C(green)%h %Creset: %s %C(red)%D%Creset' --date=iso --decorate-refs=tags
```

## 解説

`%D`を使うと`ref name`とやらが表示されます。

```sh
$ git log --pretty=format:'[%ad] %h : %s %D' --date=iso
[2018-07-27 23:13:04 +0900] ec017df : Merge branch 'b3.3_4.6' HEAD -> master, tag: v3.3_4.6, origin/master
```

こんな感じ(`HEAD -> master, tag: v3.3_4.6, origin/master`の部分)。

ちなみに`%d`もあってちょっとフォーマットがちょっと違います。

```sh
$ git log --pretty=format:'[%ad] %h : %s %d' --date=iso
[2018-07-27 23:13:04 +0900] ec017df : Merge branch 'b3.3_4.6'  (HEAD -> master, tag: v3.3_4.6, origin/master)
```

で、これが`HEAD`とかリモートとかが混ざっていて邪魔。タグだけでいいのに。

そんなとき`--decorate-refs=` オプションを使うことで`%D`, `%d`で表示するものを制御できます。
`--decorate-refs=tags`だとタグだけになるわけですね。

このオプションの引数は`tags`以外には`heads`と`remotes`があるみたいです。

お試しあれ。

## 参考資料

- https://git-scm.com/docs/git-log
WindowsにTensorflowを入れてみる(総集編)

#始めに
以前記録した、WindowsにTensorflowを入れてみるの総まとめです。

#参照
「TensorFlowのオリジナルのインストールページ」
https://www.tensorflow.org/install/install_windows

#Visual C 2015再配布のライブラリインストール
CUDA9.0で必要なのだが、9.2の情報しか無い…
一応9.2では、2010、2012、2013、2015,
2017のいずれかがあれば行ける模様。ただし、64bit環境において32bitのCrossしてる場合は、2010、2012、2013の持とう。
駄目な理由が無ければ、Microsoft Visual C++ Redistributable一通り入れておいた方が良いんじゃ無いでしょうか？
私は、32bitと64bit共に、2005、2008、2010、2012、2013、2015、2017を入れてあります。

#CUDAインストール

「CUDA Toolkit 9.2 Download」
https://developer.nvidia.com/cuda-downloads
から
「Windows」
まで選んだ上で…ページ中段くらいの
「Legacy Releases」
を叩く。

「CUDA Toolkit 9.0」に飛びます。
5つ落として順に入れる。
Windows10だとセキュリティの警告が出るが構わずインストール。
また、特に1つめのファイルが1.5GBとか大きい為に時間が掛かるのと、ダウンロードに失敗している事もある。
\# なお、前の掲載より、パッチが1つ増えたのと、ぼちぼち10.0が出る模様…

```
cuda_9.0.176_win10.exe
cuda_9.0.176.1_windows.exe
cuda_9.0.176.2_windows.exe
cuda_9.0.176.3_windows.exe
cuda_9.0.176.4_windows.exe
```
%PATH%を確認します。
CUDA\v9.0\binとCUDA\v9.0\libnvvpに通っていれば良さそう。

#cuDNNインストール

cuDNN7.0を入れる。
https://developer.nvidia.com/rdp/form/cudnn-download-survey
ログインして、「Software License Agreement」にチェックすると選択肢が現れるが、その中でも枠外に出てくる「Archived cuDNN Releases」を選択。
「Download cuDNN v7.0.5 [Dec5, 2017], for CUDA 9.0」
から
「cuDNN v7.0.5 Library for Windows10」選んで下記を落としてくる。

```
cudnn-9.0-windows10-x64-7.zip
```

展開すると「cuda」フォルダ下に、「bin」「include」「lib/x64」フォルダが現れるので、中のファイル(dll)を
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\
の該当するフォルダにコピーする。

#Python3.6.6インストール
\#素朴な疑問として、3.7.0でも動くんだろうか？
https://www.python.org/downloads/release/python-366/
から
「Windows x86-64 executable installer」
クリックして下記を落とします。

```
python-3.6.6-amd64.exe

```
インストールする時は、初期画面で全てのチェックボックスをチェックしないとはまります。
「Customize installation」選んで、「Optional Features」はそのままNext、「Advanced Options」で「Install for all users」にチェックしてインストールした方が良さそう。あと、一応全部チェックした。そして「Install」。
PATHに下記を追加する。

```
C:\program files\python36\Scripts
```

#Tensorflowご本尊。

先にpipのアップグレードでしょうな。

```
> python -m pip install --upgrade pip
```

では。管理者モードでコマンドプロンプト起動後。

```
> pip install --upgrade tensorflow-gpu
```


では、Validate your installation


```
> python
>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
>>> print(sess.run(hello))

```
確認もOK。
dokkuで定期実行アプリケーションをデプロイするときにはDOKKU_SCALEファイルを置く

[dokku](http://dokku.viewdocs.io/dokku/)にアプリケーションをデプロイすると、デフォルトのプロセスタイプが `web` になります(出典:http://dokku.viewdocs.io/dokku~v0.12.10/deployment/process-management/#process-and-container-management)

プロセスタイプが `web` の場合、 アプリケーションのコンテナにnginxを介したプロキシと外部ポートへのバインディングが行われます。

プロキシする必要がない場合、以下のどちらかの操作を行います(例えば単なるワーカーを動かしたいとき)。

- リポジトリのルートディレクトリに `DOKKU_SCALE` ファイルを置く
- `ps:scale <app> web=0 worker=1` を実行し、webプロセスを無効化する

ここではDOKKU_SCALEファイルを置く場合について説明します。

# DOKKU_SCALEファイルを置く場合
Procfileが以下のようになっていると仮定します。

```Procfile
worker: python main.py
```

同じくリポジトリのルートディレクトリに以下のような `DOKKU_SCALE` を置きます。

```DOKKU_SCALE
web=0
worker=1
tick=1
```

# 具体的なユースケース
僕は以下のような場合に、 `web` プロセスタイプを使っていません。

- Slackなどの定期的な通知
- 情報収集するためのクローラー

# おわり
ウェブアプリケーションをリリースするために便利な [dokku](http://dokku.viewdocs.io/dokku/) ですが単なる定期実行するようなワーカーをリリースするときにもとても便利です。
JSでの何分前、何日前の表示は moment.js におまかせ [BitScheduler開発日誌]

近頃のタイムスタンプ表示は「20時間前」とか「11日前」なんて表示するのをよく見かけますよね。
JavaScriptでこれを実現するには moment.js というライブラリを使うと簡単です。

ブラウザ、Node.js 双方用意されており、タイムゾーンに対応したモジュールも別途用意されています。
ここではタイムゾーン対応版を使います。

# インストール

```:Node.js
npm install moment-timezone --save
```

``` JavaScript:Node.js
var moment = require('moment-timezone');

let date = moment('Sun, 24 Jun 2018 01:20:26 GMT');
date.locale('ja');
date.tz('Asia/Tokyo');
date.fromNow();    // システム日付に対する経過時間によって "20時間前" とか "11日前"
```

## 利用例

チームの出欠管理サービス「BitScheduler」では Firebase の CloudFunctions で利用しており、メンバーの投稿タイムスタンプの表示に使っています。

![moment-capture.png](https://qiita-image-store.s3.amazonaws.com/0/25427/a01b10d4-632d-3e4a-e9d1-31804dc30cae.png)


## 参照

[Moment.js](https://momentjs.com/)
[Moment Timezone](https://momentjs.com/timezone/)

## BitSchedulerとは

チーム、グループの専用ページが用意される出欠管理サービスです。Googleカレンダーと連携することで簡単にチームの出欠を管理、運用できることを目指しています。
現在β版をリリースしています。ぜひ使ってみてください！

[BitScheduler](https://bitscheduler.com/)
Docker（nginx+php-fpm）で既存ソースをローカルで実行してsession_startエラー

```
Warning: session_start(): Cannot send session cache limiter - headers already sent (output started at /usr/share/nginx/html/index.php:1) in /usr/share/nginx/html/conf.php on line 2
```

`session_start()` の前に改行とかあるのではないの？
という指摘が多い中、本番ではエラー出てないし、改行などないんだけどなぁと悩んでいたところ[こちらの記事](https://warumono.at.webry.info/201104/article_5.html)を発見。

# 解決方法

`ｐｈｐ．ini`をDockerコンテナに設置して、`output_buffering = 4096` を設定。
コンテナ再起動したら、エラーは解消された。

```ini:php.ini
output_buffering = 4096
```

これを `config/php.ini`として設置。

# おまけ

```yml:docker-compose.yml
version: '3'
services:
    web:
        restart: 'yes'
        image: nginx:alpine
        ports:
            - "8080:80"
        restart: always
        volumes:
            - ./config/default.conf:/etc/nginx/conf.d/default.conf
            - ./dist:/usr/share/nginx/html
        depends_on:
            - app
    app:
        image: php:5-fpm-alpine
        volumes:
            - ./config/php.ini:/usr/local/etc/php/conf.d/php.ini
            - ./dist:/usr/share/nginx/html
        ports:
            - "9000:9000"
        working_dir: /usr/share/nginx/html
```

こちらは `config/default.conf` に置いたnginxの設定

```conf:default.conf
server {
    listen 80;
    server_name localhost;

    root  /usr/share/nginx/html;
    index index.php;

    access_log /var/log/nginx/access.log;
    error_log  /var/log/nginx/error.log;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(\.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}
```

#参考
[PHPで"session_start()"のエラーが出たときの対応](https://warumono.at.webry.info/201104/article_5.html)
Macbook Airでやらかす話（水没）

#水没とは
この場合、パソコンに（普通の）水をはじめとする電気伝導度の高い液体がかかる、または、そのような液体が侵入することを指す。

筆者の場合は、液体はレッドブル（355ml）を指し、パソコンはMacBookAir 2017を指す。

##筆者の場合の水没範囲
主に右側。電源キーからかなキーあたりまで。
缶の中の容量のうち、少なく見積もって$\frac{1}{5}$くらいは「だばぁ」したんじゃないでしょうか。

## 筆者の場合の水没直後の様子
普通に電源が落ち、再起動を試みようとするパソコン。
締め切り前で焦る、徹夜明けの筆者。

#免責（筆者は一切の責任を負わない）
本稿の目的は、あくまで、実施可能性のある手法について論じ、笑い話を提供することにとどまる。
この方法を筆者が実行したとは言わないし、何らかの検証が加えられた手法とも言わない。
途中、検証・考察と受け取れる文章が出現する可能性は、これを否定しないが、そのような箇所は、検証・考察ではなく、詐欺師のいう「これを買いなさい」程度の意味であり、戯言の一種と受け取るべきである。

よって、この記事に記載のあるいずれかの手法を用いたことによる、復旧をする・しないはもとより、それに伴って発生するあらゆるリスク・あらゆる不利益は、筆者にとって全く予見不能であることを宣言する。
また、本記事に対して払われた注意は、ただ、誤字脱字に対するもののみであり、それについても、万全を期するものの、万全でない可能性を否定するものではない。まして、注意を払われていないあらゆる事柄について、万全など期待できようはずもないことを読者は理解しているものとする。

万が一、この記事に記載の手法の内、どれか１つでも、実行に移す場合は、全く各実行者の責任に於いて実行されるものであり、例え、機器の破損、あらゆる動植物の傷害・死亡などのいかなる不利益が発生したとしても、当然、筆者はいかなる責任をも負わない。

それから　ここまでの　ぶんの　いみが　わからないひとは　つづきを　よんでは　いけません。

# 通常の復旧手法（既存手法）
調べるとよく出てくる手法が、自然乾燥を狙ったと思われる手法である。

重田, Mac Book Airの水濡れ（水没）故障、、絶望から奇跡の生還〜役立つ10の教訓〜, 重田のECサイト完全攻略ブログ, http://www.cl-link.com/blog-shigeta/2017/02/04/macbookair/
小林, 【MacBook Airが水没から復活】コーヒーをこぼしてから8時間で復旧するまでの全手順, ミラクリ, http://enrique5581.net/mac-suibotu-fukkyuu/
namaco_, Macさん水没から復活したよ, https://note.mu/namaco_/n/nedab1fcb74d6

ドライヤーで乾燥させてみたり、ストーブの前においてみたり、キーボードを下にして放置してみたり。
それから、業者に依頼するなど。
そのうち、キーボードを下にして放置する手法はよく取られるようではある。

なお、今回話題にしているパソコンでは、キーボードに水が残留していた、という報告が少ないため、おそらく水分は、キーボードのキーを外して見える範囲を「ほぼ素通り」するようである。

# 今回の復旧手法（提案手法）
遠心力を使って水を飛ばそう

## 提案手法の優れる点
既存手法では、即座の復旧は見込めないことがある。最大（なのかは不明だが）日単位の乾燥期間が必要になることもあると思われる。
提案手法では、物理のパワー（適当）で水分を減らすため、30分以下での電源再投入すら可能である。

そのため、締め切り間際に、よりにもよってエナジードリンクをかけてしまったような場合でも、素早く作業を再開することができる。

既存手法では、重力にしたがって排出される液体の他は、単なる乾燥に任せることになるため、特定の方向に溜まった液体は残留するものと思われる。
提案手法では、重力よりも強い力を、即座に切り替え可能な任意の方向にかけることが可能である。

そのため、内部に残留する液体の量を減らすことができるものと考えられる。

## 提案手法の劣る点
パソコン全体（より正確には、ケーシングと接触のある部分）に強い力がかかること。それゆえに、HDD搭載機ではHDDの破損が想定される。また、そうでない機器にしても、基板などに負荷がかかるは必定であり、パソコンにとって悪い影響がありこそすれ、（水没の解消以外の）いい影響があろうとは思われない。

思い出してください……「大いなる力には大いなる責任が伴う」のです（適当再び）。

## 提案手法の実施手順
1. 電源強制断
2. 側面を下にする
3. 目につく液体を拭き取る
4. 汚れても良い場所に移動
5. パソコンを閉じた状態でキーボードのescがある上側を奥にして、しっかりと両手で持つ
6. 周囲の状況を確認し、手をどのような方向に振り回しても物に当たらないことを確認する
7. 任意の向きに体ごと回転する
8. 液体が排出されるので、拭く
9. 向きを変更して、5からを繰り返す
10. さらに、5で指定された方向以外で液体が排出されそうな向きを奥にしてしっかりと両手で持つ
11. 6から9の5を10として繰り返す
12. 液体がそれ以上排出されないことをあらゆる方向について確認する
13. 電源再投入

## いずれの手法でも発生する問題
一定の時間経過後、機器内部に糖分が析出する可能性が高い。そのため、ファンなどの摺動部を持つような部品に液体が残留した場合に、問題となる可能性がある。しかしながら、固体として析出している糖類に高い電気伝導度はないだろうから、その点で問題となる可能性は低いものと考えられる。

# 時間と手間を惜しまない場合に上記以外に考えられる手法の案
電源断、純水中に完全に水没させ、放置、自然乾燥、である。
私は怖いのと純水を潤沢に準備できないのでやりたくないが、純水であれば、ショートはない、はず、なので、この方法が使えるはずである。純水は、できれば超純水をだばだば流しかけ、常に入れ替わるような処置を施すと、なおいい気もする。
この手法であれば、無用な荷重もかからず、また、固体の析出、液体による基板の侵食（？）も最小限に抑えられる、と思われる。
乾燥時にはデシケーターを減圧・加熱しないように使うと早いものと予想される。

# まとめ
パソコンは家電ではない（復唱）
パソコンは精密機器である（復唱）
パソコンをおいた机に液体を置いてはならない（復唱）
パソコンに顔を向けているときに唾液以外の液体を口に含んではならない（復唱）

どうしても液体を置きたいなら、ペットボトルなど蓋のできるものか、せめてストローのある（紙パックとか）飲料にすべきである。
[kotlin]Retrofit2のリクエストボディにキャメルケースのkeyを入れたい(2018/9/2追記)

~~Retrofit2でpostしようとした時にリクエストボディにクラスを入れたらキャメルケースの変数がスネークケースのkeyとして変換されてしまう。~~

```kotlin:RetrofitInterface.kt
interface RetrofitInterface {

    @POST("/api/sample")
    fun postSample(@Body body: RequestModel): Call<ResponseModel>
}
```

```kotlin:model.kt

class RequestModel(loginId: String,
            password: String) {

    val loginId = loginId
    val password = password
}
```

~~結果~~

```
{
    "login_id":"aaa",
    "password":"bbb"
}
```

~~サーバー側がキャメルケースで設計してしまってる場合、これはまずい。~~

# BodyにMapを挿入する

~~クラスではなくてMapでbodyを指定すると無事キャメルケースになる。~~

```kotlin:RetrofitInterface.kt
interface RetrofitInterface {

    @POST("/api/sample")
    fun postSample(@Body body: Map<String, String>): Call<ResponseModel>
}
```

```kotlin
val body = mapOf("loginId" to "aaa", "password" to "bbb")
```

~~結果~~

```
{
    "loginId":"aaa",
    "password":"bbb"
}
```

# gsonのFieldNamingPolicyを設定する
(2018/09/02追記)FieldNamingPolicyに依存されるということを存じ上げなかった。

参考: https://qiita.com/yysk/items/e549ba40bc2accfdff35

今回は叩くAPIのレスポンスがキャメルケースとスネークケースと混在していたので、`IDENTITY`を設定して解決

```kotlin

val gson: Gson = GsonBuilder()
                .setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)
                .create()


val restAdapter = Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(okHttpClient)
                .baseUrl("https://xxxx.jp")
                .build()
```
モバイルブラウザでのアクセシビリティチェック

[WAIC](https://waic.jp/) さん主催の「これから取り組むWebアクセシビリティ 2018 夏」に行ってきました。
そこの質疑応答がすごい参考になりました。。
モバイルブラウザでのアクセシビリティ確認方法について
新しい知識が得られたので、まとめます。


## アクセシビリティの確認について

この記事で行う「確認」とは、WCAG2.0 の

> **2.1.2 キーボードトラップなし**: キーボードインタフェースを用いてキーボードフォーカスをそのウェブページのあるコンポーネントに移動できる場合、キーボードインタフェースだけを用いてそのコンポーネントからフォーカスを外すことが可能である。さらに、修飾キーを伴わない矢印キー、 Tab キー、又はフォーカスを外すその他の標準的な方法でフォーカスを外せない場合は、フォーカスを外す方法が利用者に通知される。 (レベル A)
[キーボードトラップなし:達成基準 2.1.2 を理解する](https://waic.jp/docs/UNDERSTANDING-WCAG20/keyboard-operation-trapping.html)

が達成できているかの検証です。
キーボード操作、もしくはフォーカスを移動する一般的な方法で
問題なくコンテンツの行き来ができるか確認します。


## iOS safari での確認

### キーボード操作

外部キーボードは接続できるが、Tab でフォーカスの移動ができない。

### キーボード以外の標準的な操作

VoiceOver を有効にすると、ジェスチャー操作でのフォーカス移動が可能になる。

#### VoiceOver の設定

iOS の「一般」の「アクセシビリティ」から VoiceOver がオンにすることができます。
このとき、読み上げ速度も変えられるのですが、
「読み上げ速度」の項目領域内で上か下へスワイプすると変更可能です。
（この領域はすごい狭いです）
![IMG_0403.png](https://qiita-image-store.s3.amazonaws.com/0/131281/777da5f7-ad6d-03f6-6b6b-b31cc0c68f3b.png)


#### ジェスチャーでのフォーカス移動

| safari での制御 | 操作 |
|:----|:----|
| 要素（リンク・テキスト）の選択 | タップ | 
| 遷移 | リンクにフォーカスが乗った状態で画面内をダブルタップ | 
| 前の要素にフォーカス | 画面上で左方向にスワイプ | 
| 次の要素にフォーカス | 画面上で右方向にスワイプ | 
| ページをスクロール | 指３本で上下どちらかにドラッグ | 

## Android での確認

### キーボード操作

外部キーボードの Tab キーでフォーカスの移動が可能。

### キーボード以外の標準的な操作

Android はプリインストールされている「TalkBack」もしくは
「Android Accessibility Suite」を使うことで、
iOS 同様、音声による読み上げとジェスチャー操作が可能になります。


#### 「TalkBack」の設定
Android の「設定」から「ユーザー補助」に進み、
「TalkBack」を有効にすることで設定できます。
（「TalkBack」が「ユーザー補助」のさらに下の階層に隠れている端末もありました）

#### 「TalkBack」のジェスチャー

| ブラウザ での制御 | 操作 |
|:----|:----|
| 要素（リンク・テキスト）の選択 | タップ | 
| 遷移 | リンクにフォーカスが乗った状態で画面内（もしくはその要素）をダブルタップ | 
| 前の要素にフォーカス | 画面上で左方向にスワイプ | 
| 次の要素にフォーカス | 画面上で右方向にスワイプ | 

その他のジェスチャーは [TalkBack ジェスチャーを利用する] (https://support.google.com/accessibility/android/answer/6151827) にまとめられています。

#### 補足

Andoird OS によっては「ユーザー補助」内に「選択して読み上げ」という項目があるのですが、
こちらはコンテンツを読み上げるだけで、ジェスチャーでの操作はできません。
iOS の「画面の読み上げ」と同じ機能だと思います。


## まとめ

モバイル環境での ガイドライン 2.1.2 への対応検証は、
iOS なら VoiceOver、Android だったら外部キーボードや TalkBack で確認できました。

しかし、現在タッチデバイスでのアクセシビリティに
対応した WCAG2.1 が~~提案中~~（訂正：20180824）勧告済みらしいので、
今後モバイルデバイスでの検証項目はもっと増えるかもしれません。。

記事のツッコミや補足などありましたら、大歓迎です。
よろしくお願いいたします:bow:
ブラウザの拡張機能を自作してみた

# はじめに
最近はコーディングする機会がなかなかないので、気分転換兼ねてブラウザの拡張機能を開発してみました。
理解に重きを置くのではなく、まずは作ってみたという感じです。

# 対象
* ブラウザの拡張が作りたい人
* とりあえず動かしたい人

# 参考サイト

[ゼロからはじめる Microsoft Edge 用の拡張の作り方](https://blogs.msdn.microsoft.com/osamum/2016/07/05/how-to-make-extension-for-msedge/)
[拡張機能の開発](https://developer.mozilla.org/ja/docs/Mozilla/Add-ons)

# 開発
今回はブラウザーのコンテキストメニュー(右クリックメニュー) に項目を追加しました。

Qiitaなどでリンクを貼るときにURLとタイトルをコピーするのが面倒だったので、
文字を選択範囲してメニューを選ぶとMarkDownのリンク形式でクリップボードにコピーするという機能です。


## 必要なもの

最低限必要なファイルは以下の2つのみ。

* manifest.json
* background.js


## manifest.jsonを作成
拡張機能に関する情報を記載したファイル

```json:manifest.json
{
    "name": "MarkDown-URL",
    "author": "(Your name write down here.)",
    "version": "0.1",
    "manifest_version": 2,
    "description": "URLをMarkDownのリンク形式で返します。",
    "background": {
        "scripts": ["background.js"],
        "persistent": true
    },
    "permissions": [
        "contextMenus"
    ]
}
```

## background.jsを作成
メニュークリック時の動作

```javascript:background.js

//Edge の名前空間(browser) がなけれぱ chrome の名前空間を使用する
var browser = browser||chrome;

//コンテキストメニューに拡張のメニューを追加
browser.contextMenus.create({

  id: 'MarkDownLink',

  title: 'MarkDownのリンク形式で取得',

  contexts: ['selection'], //選択しているときのみメニューに表示される


    onclick: (info, tab)=>{ //クリックされた際のアクション

        var url = tab.url;
        var markdown = '[' + info.selectionText + '](' + url + ')';

        toClipBoard(markdown);


        function toClipBoard(text){
          var ta = document.createElement("textarea");
          ta.value = text;
          ta.style.position = "fixed";
          ta.style.left = "0";
          ta.style.top = "0";
      
          document.body.appendChild(ta);
          ta.select();
          document.execCommand("copy");
          ta.parentElement.removeChild(ta);  
        }
  }
});
```

## 同一フォルダに格納
![image.png](https://qiita-image-store.s3.amazonaws.com/0/124594/ff5a4437-5700-89c9-a257-94d44da23974.png)

# 拡張機能のテストインストール
### chrome
1. 拡張機能を開く。
※URLに「chrome://extensions」と入力

1. 右上のデベロッパーモードをオンにする。
1. パッケージ化されていない拡張機能を読み込む。
1. 上記で作成したフォルダを参照する。
※各ファイルがutf-8でないとエラーになる。

### edge
1. 開発者向け設定を開く。
※URLに「about:flags」と入力

1. 「開発者向け設定」の[拡張機能の開発者向け機能を有効にする(これによりデバイスが危険にさらされる可能性があります)]にチエックをつけ Edge を再起動する。
1. 右上の設定から「拡張機能」をクリックする。
1. 一番下にある「拡張機能の読み込み」をクリックする。
1. 上記で作成したフォルダを参照する。
※各ファイルがutf-8でないとエラーになる。

# 動かしてみる
メニューにもでてきて、コピーにも成功。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/124594/b609b02e-31f5-f5cf-fcc2-4938fea40607.png)
なんかカッコいいからプログラミング始めてみたwww 

はじめまして！
大学で物理を専攻している、Gisan_nameruと申します。

プログラミングは初心者の初心者で、偉そうなことは言えませんが、プログラミングを始めたキッカケだけは...
ということで、私から、プログラミングを始めたいけど腰がなかなか上がらない方にイイことを教えちゃいたいと思います！！(プロの方ごめんなさい!)

#①私がプログラミングを始めた理由
　就活中、なりたい職種が定まらず、とりあえず色々な業界の説明会に行っていましたが、ある日、とある会社の説明会で、IoT(Internet of Things)業界に興味を持ち始め、「プログラミングかっけぇ」となったのが始まりです。

#②プログラミングをやってトクすること
  てなわけでトクすることを並べてみます！

- パソコンの性能(CPU,GPU,メモリ等)をフルに活かせる
- 退屈なPC作業(メール送信、Excelワーク等)を自動化できる
- モノが動く仕組みを知ることができる
- オリジナルのアプリケーションを作ることができる
- 何もかもを"いい感じ"にできる

...はあ、なんていいことだらけなんだ...:innocent::innocent::innocent:

#③オススメのプログラミング言語
　プログラミング言語自体に得意とするものがあって、一概にどれが良い悪いは言えませんが、私がオススメしたい言語を3つ紹介しようと思います。

###1位 Python

え？バカなの？とおっしゃる方もいるかと思いますが、私はPythonを推します。
確かに、人気プログラミング言語ランキングで、JavaScriptやRubyが2トップのような気もしますが、これからの時代はPythonです。(謎の断言)
Pythonは、最近オブジェクト指向(のような)言語になり、AIや機械学習の分野で脚光を浴びていて、しかもとってもわかりやすい言語なんです！


##2位 C++

2位にランクインしたのは、超王道プログラミング言語のC++です。こちらは事象駆動型シミュレータ、(簡単にいうと、コンピュータに何かしらの刺激を与え、何かをさせるようなこと)を記述するために、C言語を拡張したものです。
私も最初は、C++でプログラミングを始め、基礎的な部分を学びました。
是非、プログラミング始めたい方は、C++でおみくじを作ることをオススメします！

##3位 Ruby
国産プログラミング言語で、Matzこと、まつもとゆきひろさんが中心となって開発されてきました。私は、Rubyをほとんど触ったことがなく、良い点をあまり挙げられませんが、関数の美しさ、Ruby on Railsといったツールなど素晴らしい環境がどんどん出来てきている言語です。また、サポートが日本語なのもありがたいですよね！1ヶ月以内に始められたらと思います。

今回3つ紹介させていただきましたが、他にも何百種類何千種類の個性的な言語があります。プログラミングは他人から勧められてやるものではなく、自分がしたいことはどの言語でできるのか、逆も然りですが、自分で見つけることが重要です。

#④最後に
ここまで読んで下さり、ありがとうございました。私自身プログラミングを始める前は「難しい」「身につくか心配」といったイメージでしたが、始めると意外と単純なことの積み重ねなことに気づき、驚いています。プログラミングは、PCの操作スキル向上や誰かの役に立つためだけでもいいので、絶対やっておくべきだと思います。
みんなで一緒にキーボード壊れるまでプログラミングしましょう！！


それでは。

#⑤おまけ
プログラミング専用のMacBookPro買うために貯金始めました。
購入次第MacBookProの"エライところ"を紹介したいと思います。(時期は不明)
Rails: ツイートアプリ開発で使ったコマンドのまとめ

初めてのツイートアプリが開発できたので、復習と頭の整理をかねてまとめました。
開発の流れに沿って登場順です。

##データベース準備まで
- mkdir projects
「projects」というディレクトリを作成する

- rails new application -d mysql
 「new application」というアプリケーションを「mysql」データベースを使用して作成する

- bundle install 
Gemfileの内容にしたがってGemをbundlerを利用してインストールする

- bundle update 
Gemのバージョン指定を管理している「Gemfile.lock」というファイルを更新する（Gemに対してバージョン指定を行った場合に行う）

- rake db:create
 database.ymlの内容に基づいてデータベースを新規作成する（何も起こっていないように見えるけど大丈夫）

## コントローラ
- rails g model tweet
「tweet」というモデルを作成する。（モデルクラス名はすべて小文字、単数形 ）　app/models ディレクトリに tweet.rb というファイルが作成される 。db/migrate ディレクトリにマイグレーションファイルが作成される。

- rails g controller tweets
「tweets」というコントローラを作成する。app/controllers ディレクトリに tweets_controller.rb というコントローラファイルが作成される。


##ビューファイル
※コマンドでなく手動で※ App/views/コントローラ名 のディレクトリに作成する

## モデル
- rails g model tweet
「tweet」というモデルを作成する ※モデルクラス名はすべて小文字、単数形 
app/models ディレクトリに tweet.rb というファイルが作成される db/migrate ディレクトリにマイグレーションファイルが作成される

- rake db:migrate 
マイグレーションファイルの実行（→テーブルの作成、更新）

- rake db:rollback
 データベースを最新のマイグレーションファイルを実行する前に戻す 

- bundle exec
 2つ以上のrailsアプリケーションを同じバージョンのRubyを利用して作成している際に使用する 
e.g.) bundle exec rake db:migrate
VisualStudio2017でガルーンAPIを使ってファイル添付メッセージを送ってみる

# 偉大なる先人
[VisualStudio2017でガルーンAPIを使ってメッセージを送ってみる](https://qiita.com/HAGITAKO/items/b684f4e31552e5a5db69)
SOAPど素人なこともあって、ガルーンAPIの実装でかなり悩んでたところ
こんな素敵な記事を見つけて一命を取り止めました。ありがたや。
感謝と尊敬の念を込めてタイトルパクりました。

# やりたいこと
上記のメッセージ送信APIに添付ファイルを追加する。

# 実装
メッセージ送信処理については上記記事に詳しく記載されているため割愛。
ファイル添付のリクエスト作成処理のみ抜粋。

```C#:FileMessageTest.cs

// 添付したいファイルのパス
string[] fileDirArray = { @"C:\hoge.jpg", @"C:\fuga.jpg" };

// 添付ファイル実体配列
MessageCreateThreadTypeFile[] files = new MessageCreateThreadTypeFile[0];
// 添付ファイル情報配列
contentFile[] cFiles = new contentFile[0];

// ファイル数分ループ
for (int cnt = 0; cnt < fileDirArray.Length; cnt++)
{
    string fileDir = fileDirArray[cnt];
    string fileName = fileDir.Substring(fileDir.LastIndexOf('\\') + 1);

    //------------------
    // ファイル実体
    //------------------

    // 1.添付するファイルをバイト配列にする
    FileStream fs = new FileStream(fileDir, FileMode.Open, FileAccess.Read);
    byte[] bs = new byte[fs.Length];
    fs.Read(bs, 0, bs.Length);
    fs.Close();

    // 2.ファイル設定
    MessageCreateThreadTypeFile file = new MessageCreateThreadTypeFile();
    file.content = bs;
    file.id = cnt.ToString();

    // 3.添付ファイル配列に追加
    Array.Resize(ref files, cnt + 1);
    files[cnt] = file;

    //------------------
    // ファイル情報
    //------------------

    // 1.ファイル情報設定
    contentFile cFile = new contentFile();
    cFile.id = cnt.ToString();
    cFile.size = (ulong)bs.Length;
    cFile.name = fileName;
    cFile.mime_type = "image/jpeg";

    // 2.添付ファイル配列に追加
    Array.Resize(ref cFiles, cnt + 1);
    cFiles[cnt] = cFile;
}

// 添付ファイル実体配列、添付ファイル情報配列をそれぞれセット
messageThreadType.file = files;
threadType.content.file = cFiles;

```

# 調査結果

## ファイル形式について
Reference.cs内でバイト配列からBase64形式にデシリアライズしてくれてるっぽい。
`[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, DataType="base64Binary")]`

## ファイル実体と情報について
ファイル自体のバイト配列とファイルの情報(ファイル名、サイズ、MIME_TYPE)は全然違うとこに持ってた。
それぞれのidでお互い紐づいている模様。
EC-CUBE4 を CentOS7 ベースの Docker で動かす

## Dockerfile

```
FROM centos:centos7
RUN yum update -y
RUN yum install -y epel-release
RUN yum install -y http://rpms.remirepo.net/enterprise/remi-release-7.rpm
RUN yum install -y php72
RUN yum install -y php72-php
RUN yum install -y php72-php-pecl-zip
RUN yum install -y php72-php-mbstring
RUN yum install -y php72-php-xml
RUN yum install -y nodejs
RUN yum install -y autoconf
RUN yum install -y automake
RUN yum install -y libpng-devel
RUN yum install -y libpng12-devel
RUN yum install -y php72-php-pdo
RUN yum install -y php72-php-phar
RUN yum install -y php72-php-mbstring
RUN yum install -y php72-php-zlib
RUN yum install -y php72-php-ctype
RUN yum install -y php72-php-session
RUN yum install -y php72-php-json
RUN yum install -y php72-php-xml
RUN yum install -y php72-php-libxml
RUN yum install -y php72-php-openssl
RUN yum install -y php72-php-zip
RUN yum install -y php72-php-curl
RUN yum install -y php72-php-fileinfo
RUN yum install -y php72-php-intl

RUN yum install -y php72-php-cli
RUN yum install -y git

RUN cd /usr/bin/; ln -s php72 php
RUN mkdir /var/www/html/ec4
WORKDIR /var/www/html/ec4
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
RUN php composer-setup.php
RUN php -r "unlink('composer-setup.php');"
RUN php composer.phar create-project ec-cube/ec-cube ec-cube "4.0.x-dev" --keep-vcs

RUN yum install -y net-tools

WORKDIR /var/www/html/ec4/ec-cube
EXPOSE 8000

CMD bin/console server:run 0.0.0.0:8000
```

## Build & Run

```
docker build -f Dockerfile -t eccube4cent .
docker run -d -p 8080:8000 --name eccube4cent eccube4cent
curl http://127.0.0.1:8080/
```
delegateについて

#delegateとは
あるメソッドの処理を他のメソッドに任せることができる

#delegateのメリット
##書く文字が少なくなる
コーディングする際に、書く量を減らせます

以下のような場合。。。。

```book.rb
#t.string :title
#t.integer :author_id
belongs_to :author
```

```author.rb
#t.string :name
has_many :books
```

こんな風にかくと。。。。

```book.rb
#t.string :title
#t.integer :author_id

belongs_to :author
delegate :name, to: :author

```

```author.rb
#t.string :name
has_many :books

```

コンソール上でこんなことができます。

```
#コンソール

$book = Book.first
$book.name
#=> authorのインスタンスからnameの情報をとることができる


```


#メソッドを再利用できる

```
def fuga
 fuga
end


def hoge
 hogehogehoge
 hogehogehoge
 hogehogehoge
 ・・・・・・・・
end

delegate :fuga, to: :hoge

```

このようにメソッドが二つあり、一つが（今回はhoge）めちゃくちゃ難しいメソッドの時とかでも、
hogeメソッドを完全理解せずとも、メソッドの再利用ができます。


#delegateをちょろっと解剖

delegateを使わず同じ機能を実装するとなると、下のようになります。
book.rbにdelegate :name , to: :author書く場合は、代わりに下のようにかけます。

```book.rb
belongs_to :author
def name
  author.name
end
```

```author.rb
has_many :books

```
Webデータを活用！WebサイトからデータをExcelに取り込む方法

![excel-0.png](https://qiita-image-store.s3.amazonaws.com/0/262932/0179df94-5701-db64-6923-9f2b964d7379.png)

Excelは、様々なデータを集計・分析できる表計算ソフトです。書式とスタイル、検索・置換、数式と関数、グラフの作成、データベースなど様々な機能があります。ほとんどの場合、Webサイトから情報を取得して、データをExcelにインポートして、いろいろな分析で、知りたいとこを得る必要があります。この記事では、WebデータをExcelにスクレイピングするいくつかの簡単な方法を紹介します。

 

#Webクエリを使ってWebデータを取得する

Webページからデータをコピペすることを除いて、Webクエリは、標準的なWebページからデータをExcelにすばやく取り込むのに使用されます。ネット上にあるさまざまなデータをExcelの表として取り込み自まに加工することができます。しかもネット上のデータが更新されればExcel上のデータも自動で更新することだってできます。

 取り込みの手順は次の通りです：

1. 『データ』タブ → 『外部データの取り込み』 → 『Webから（Webクエリ）』を選択します。

2. アドレスに取り込みたいサイトのURLを入力し、移動をクリックして接続します。

3. そうすると、取り込める表の横に黄色の矢印マークが表示されます。

4. 取り込みたい表の左上にある『→』矢印マークをクリックし、範囲選択します。

5. 右下の『取り込み』ボタンをクリックし、インポートする位置のセルを指定すると、Excelに表が取り込まれます。

 

株価や為替、天気などの情報は日々変わっていきます。そのようなデータは、最新の情報を取得したいときに、データを自動更新を設定するすればよいです。

 『データ』タブ → 『接続』 → 『プロパティ』ボタンをクリックして『接続のプロパティ』ダイアログを開きます。ここでは接続名とかも設定でき、『ファイルを開くときにデータを更新する』にチェックを入れておくと、ファイルを開く際に自動更新できます。また、更新の頻度も1時間ごとなど、自由に変更することができます。

 

#Excel VBAを使ってWebデータを取得する

VBA（Visual Basic for Applications）とは、Microsoft Officeに含まれるアプリケーションソフトの拡張機能で、利用者が簡易なプログラムを記述して実行することで複雑な処理の自動化などを行なうことができるものです。一般に「マクロ」と呼ばれ、このようなExcelファイルは**.xlsmとして保存されます。

インストールしたままの状態のExcelではVBAプログラミングのための開発タブが隠されています。ですから、使用する前にリボンに開発タブを表示する必要があります。『ファイル』タブ→オプションでExcelのオプション』ウィンドウを開きまして，『リボンのユーザー設定』→メインタブの『開発』にチェックを入れます。これでOKです。

VBAはVBE(Visual Basic Editor)という専用のアプリケーションを使って編集をしていきます。先ほど追加した開発タブからVisual Basicを選択してく、VBEが立ち上がります。

VBAを使ってWebサイトからデータをExcelに取り込むには、いくつかのリクエストをWebページに送信し、これらのWebページから返されたデータを取得するためのVBAスクリプトを作成または取得する必要があります。 XMLHTTPと正規表現でVBAを使ってWebページを解析するのは一般的です。Windowsでは、WinHTTPまたはInternetExplorerでVBAを使って、WebサイトからExcelにデータをスクレピングできます。VBAの使用は少し複雑なので、詳しい操作は次回にしましょう。オンラインでVBAの使い方には豊富な資料と学習フォーラムがあるので、興味がある方はすぐに使用できるVBAスクリプトを直接検索して使えます。 

 

#自動Webスクレイピングツール

 VBAコードを設定しようとしていなくWebページからデータをExcelに速く取り込む簡単な方法を探している人にとっては、[Webスクレイピングツール](http://jp.octoparse.com/)またはAPI経由でデータをスクレイピングのをお勧めします。Webスクレイピングツールのほとんどはコードを書くことなく使いやすいです。スクレイピングツールを使って、すぐにWebサイトからデータをスクレイピングし、Excelにエクスポートすることができます。様々なスクレイピングツールには長所と短所があり、プロジェクトを完成させるためには適当なものを選ぶことができます。

[この記事](https://qiita.com/Octoparse_Japan/items/2f80077a1594c9bb01ec)をチェックして、[TOP30の無料Webスクレイピングツール](https://qiita.com/Octoparse_Japan/items/2f80077a1594c9bb01ec)を試してみてください。

 

#プログラミング言語を使ってWebクローラーを構築する

 一般的に、プログラマを中心にPHP、Python、Perl、Rubyなどのプログラミング言語でWebクローラーを作成し、WebページをスクレイピングしてデータをExcelにインポートする人がいます。この場合、データ取得は楽になりますよね。

                                                                                            

#データ取得の代行サービスに任せる

複雑なスクレイピング作業に貴重な時間をかかりたくないて、データだけを入手したい場合は、データ取得作業を豊富な経験と専門知識を持っている[スクレイピングチーム](https://www.octoparse.jp/)に任せることが最良の選択です。あるWebサイトに制限や著作権表示があるため、データの取得は非常に難しいので、熟練したスクレイピングチームは、適切な方法でWebサイトからデータを取得し、必要とするデータフォーマットで納品できます。
Docker for Mac (Windows) 上のPHPアプリをデバッグ実行する

Docker for Mac/Windowsで動作しているPHPアプリを、VS Codeからデバッグする方法です。

Docker for Mac/Windowsで起動したコンテナでは、`host.docker.internal`というDNS名で、ホストのIPアドレスを引くことができるようになっています。

* [Networking features in Docker for Mac](https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds)
* [Networking features in Docker for Windows](https://docs.docker.com/docker-for-windows/networking/#use-cases-and-workarounds)

Xdebug の設定の`xdebug.remote_host`に、この値を指定することで、コンテナ内のPHPとデバッガが通信できるようになります。

```
xdebug.default_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 0
xdebug.remote_enable = 1
xdebug.remote_host = "host.docker.internal"
xdebug.remote_port = 9000
```

![img5.png](https://qiita-image-store.s3.amazonaws.com/0/135726/584ab423-126c-98db-7f9a-076d4e26e3f0.png)

仮想環境でのPHPデバッグについて、詳しくは、[Vagrant(+Docker) 上のPHPアプリをデバッグ実行する](https://qiita.com/xanagi/items/b127ed3e5476cfd8eda7)をご覧ください。

* サンプル https://github.com/xanagi/docker-for-mac-php-vscode
matplotlib でレーダーチャート

基本は https://matplotlib.org/examples/api/radar_chart.html で良いのですが、
手元の環境、

```
$ python --version
Python 3.6.5 :: Anaconda, Inc.

$ pip list
matplotlib                         2.2.2
```
では、パッチが必要だったのでメモ。

```patch
--- radar_chart.py.org
+++ radar_chart.py
@@ -39,6 +39,7 @@
     theta = np.linspace(0, 2*np.pi, num_vars, endpoint=False)
     # rotate theta such that the first axis is at the top
     theta += np.pi/2
+    theta = np.where(theta > np.pi * 2, theta - np.pi*2, theta)
 
     def draw_poly_patch(self):
         verts = unit_poly_verts(theta)
```

時計回りの場合

```python
    theta = np.linspace(np.pi/2, np.pi/2-2*np.pi, num_vars, endpoint=False)
    theta = np.where(theta < 0, theta + np.pi*2, theta)
```