OmniAICreator/Qiita-1.07M huggingface dataset:
http-proxy-middleware を使用してダミーの API を用意

# http-proxy-middleware を使用してダミーの API を用意

サーバサイドで API が用意されてないから API 連携できない・・・という場合に
[http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) によりダミーの API を用意します。

Nuxt.js 使ってます

## スタブを用意

public な感じでアクセスできるところにスタブの JSON を用意します。
Nuxt.js なので `static/stubs/` として用意します。

```json:static/stubs/user.json
[
  {
    "id": 1,
    "name": "ROU"
  },
  {
    "id": 2,
    "name": "TK"
  },
  {
    "id": 3,
    "name": "JG"
  },
  {
    "id": 4,
    "name": "KNSRU"
  }
]
```

これでとりあえずどこからでも？アクセスできる JSON が用意されました。

## http-proxy-middleware の設定

API としてアクセスしたい URL はだいたい `/api/user/` などです。
そして実際に渡したいモノは `static/stubs/user.json` のレスポンスです。
そのようにアクセス可能となるよう設定をします。

`nuxt.config.js` ですが `webpack.config.js` などでもそう変わりはないはず・・・です

```js:nuxt.config.js
const config = {
  ・・・
  proxy: {
    '/api/user': {
      target: 'http://localhost:3000/stubs',
      pathRewrite: {
        // /api/user/～ -> http://localhost:3000/static/stubs/user.json
        '^/api/user/': 'user.json',
      },
    },
  },
  ・・・
};
export default config;
```

## 実際に GET してみる

実際に axios などで取得してみます。

```js:pages/index.vue
  mounted() {
    this.$axios.get('/api/user/').then(response => {
      console.log(response);
    });
  },
```

結果・・・

![api-ppoi-response.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116435/932fa523-2d49-1896-d2b1-760d69015c2d.jpeg)

4 名のユーザの情報が取得されました。
いかがでしたでしょうかいかがでしたでしょうか
アジャイルとウォータフォールの選択基準を考える

# アジャイルとウォータフォールの選択基準を考える

## 概要

ここ2-3年の間にウォータフォール、アジャイルの両方のプロジェクトを行いました。共に数千万円の中規模プロジェクトです。

コスト、期日、品質の全てで期待された結果を出しており、システム開発プロジェクトとしては成功と言って良いと思います。

ウォータフォールで失敗し、アジャイルで成功したという話は多いのですが、両方成功した前提で語られることは少ないと思い、実際にやってみた感想を纏めてみました。
何かの参考になれば幸いです。

なお、対照実験ではないため、同条件で比較したという話ではありません。

## 筆者の立ち位置

両プロジェクトで、システムアーキテクト、プロジェクトマネージャです。
企画、要件定義から関わっています。

## プロジェクトの特徴

### ウォータフォールプロジェクトの特徴

ウォータフォールプロジェクトは、以下の特徴がありました。

- 既存業務システムのバッチ処理に関するパフォーマンス改善が目的
- バッチ処理結果を利用する画面側は原則変更しない
- 要件は固定
- 社内 + オフショアで開発
- 期間は約一年

### アジャイルプロジェクトの特徴

アジャイルプロジェクトの特徴は以下の通りです。

- 新規業務システム開発が目的
- 特殊なUIを実装
- サーバレスなど新規性のある技術を多く採用
- 社内 + 国内開発会社で開発
- 期間は約半年

## どちらの開発手法を採用すべきか?

やる事が明確ならウォータフォール、そうでなければアジャイルと言われます。
まさにそれが正しいことを実感しました。

ウォータフォールプロジェクトはリファクタリング目的であり、要件の固定を前提条件としました。
新規システム開発でも要件の固定自体は難しくなく、要件定義と設計・実装の契約を分け、設計以降は要件を固定することが一般的だと思います。

問題は固定したはずの要件について、実際に作ってみるまで本当の意味での合意が難しいという点にあります。
要件に対し、実際にどうなるのか見た事がないのであれば、要件の固定は不可能ということです。

このため、現実的にウォータフォールを採用できるのは、リファクタリング、ユーザの操作性に影響しないシステムリプレース、原因が特定された障害対応などに限定されます。

明確にウォータフォールが適しているのでなければ、アジャイルを採用すべきと言えます。

## どちらの方が品質が良くなるか?

開発手法が直接品質に影響することは無いと感じました。
不具合の発生率に違いはありません。

ビジネス要求を受けて要件が変化することが多い中で、ウォータフォールでは変化への対応が難しいため、結果的に品質が低いと評価されるのだと思います。

## どちらの方が予定のコストに収まりやすいか?

そもそも予定のコストを算出できるのであれば、ウォータフォールで良いと思われます。
要件が固定できずに厳密なコストを算出できないのであれば、アジャイルを採用します。

コストの振れ幅を抑えたいのであれば、ウォータフォールを選択するための条件を整える必要があります。
[不確実性のコーン](https://tech.nikkeibp.co.jp/it/article/COLUMN/20131001/508039/)を参考に、`設計完了`に近いことが条件です。

条件を満たさないのにウォータフォールを選択すると、高い確率でコストが超過します。

## どちらの方が納期を守りやすいか?

考え方はコストと同じです。

## どちらの方が高スキルが必要か?

どちらの方が要員の調達が楽か?と言い換えてもいいと思います。

ウォータフォールの場合は、要員のスキルに幅を持たせることができますが、プロジェクトに必要なスキルを厳密に定義する必要があります。
アジャイルの場合は、同じレベルの要員で揃える必要があります。要員のスキルに幅があると機能しません。

どちらを採用しても要員の調達が楽ということはありません。
難しさのベクトルが異なるだけです。

## 技術的課題が多い場合はどちらを採用すべきか?

開発手法に解決策を求めるべきでは無いと思われます。
アジャイルを選択しても、課題が解決出来る可能性に影響はありません。

プロジェクトを計画する段階で、課題の洗い出し、課題の解決、システム構築の3段階に分割しておく必要があります。

## どちらの方が管理が楽か?

一般的にウォータフォールの方が楽だと言われます。
しかしながら、不測の事態が発生した場合に、ウォータフォールではプロジェクトの再構成に多大なコストがかかります。

不測の事態が発生しないプロジェクトは存在しないため、事前に完全な予定を組み立てないアジャイルの方が心理的な負担は少ないと思われます。

## どちらの方が開発者は楽か?

考える事が限定されるため、ウォータフォールの方が楽に感じるかもしませんが、作業スケジュールが厳密に管理されるため、心理的負担が大きいと考えられます。

管理と同様に、アジャイルの方が[心理的安全性](https://bizhint.jp/keyword/101187)を確保しやすいのがメリットです。

## どちらがステークホルダーの理解を得られやすいか?

予定をコミットするウォータフォールになります。
ただし、ウォータフォールを選択できる条件を満たすことが難しいため、ステークホルダーだけをみて開発手法を選択すると失敗します。

ウォータフォールは選択できる条件が厳しい開発手法です。
ステークホルダー側もこのことを理解し、条件を満たしていることを確認する手順が必要です。

## 結論

ウォータフォールが適切であるという十分な確信が得られない場合は、アジャイルを選択すべきです。

ウォータフォールの方が採用するための敷居が高いことから、[私は間違っていた。ごめん。ウォーターフォールは何のメリットも無い](http://simplearchitect.hatenablog.com/entry/2016/06/20/080807)のように一律アジャイルという選択も妥当だと思われます。
ルートDNSの構築（CentOS7）

##今回の構築
どうも。Marnyです。今回構築するのは、
####「ルートDNS」
です。

そもそも、DNSの構築したことがない人もいると思いますが、今回は忘れないためにもルートDNSについて解説していきたいと思います。

##今回の環境
・CentOS7
・bind 9.9.4

###DNSについて
そもそも。ルートDNSの構築ってなんじゃい。って思う人もいると思います。まぁそれもそのはず。
>ルートDNSは世界に13台しかありません。

ルートDNSというのは、名前からもわかる通りDNSを集約するものです。
今回の構築は、
・ドメイン構造
・DNSの書き方
については知識がないと今回の構築は難しいと思います。

###今回のドメイン図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450534/c39f34c5-c5e7-6338-70fc-9bf745c3863e.png)


みずらいかもですが、今回のドメイン図は上図になります。
同じ色のとこが管理している空間です。（例）青色→ns,practice1,1の空間を管理しています。

####[解説]
>皆さんが捜査する端末の場所は、丸の部分です。（rootのみドメインとしても考えてください）
つまり、この場合rootの端末、practice1の端末、practice2の端末と3端末あります。

####IPアドレス
rootDNS=192.168.1.253/24
practice1=192.168.1.1/24
practice2=192.168.1.2/24

####インストールするもの
・bind
・bind-utils
この二つをyumすればいいです


##やっとこさ構築ですよ…
やっぱDNSって難しいですね（笑）構築に一か月くらい努力したんですよね…

とはいっても、普通のDNSが構築できないと詰むんで、DNSの純粋な構築等はまた今度やります。

####ルートDNSって何が違うのか
普通のDNSと何が違うのか、大きく言うと
>named.confファイル,正引きファイル,逆引きファイルの書く量、内容がちがう

って感じです。
ルートDNSは先ほどのドメイン図にもありましたように、かなりの量を管理しています。
つまり、正引きファイル、逆引きファイルの書く量が異常です（笑）

ためしに、どんな感じで書くかの例を置いときます（example.comのファイル）

```
$TTL    86400
@       IN      SOA     sever.root.example.com. root.root.example.com.(
                        2019090600      ; Serial
                        10800           ; Refresh
                        3600            ; Retry
                        604800          ; Expire
                        86400           ; Min
)

                        IN      NS      root.example.com.
practice1               IN      NS      ns.practice1.example.com.
practice2               IN      NS      ns.practice2.example.com.
root                    IN      A       192.168.253.100
```
僕はINの前のドメインは省略します
このように、practice1,practice2の管理をnsに委譲させるっていう情報だけここに書きます。
これをrootの管理しているドメイン空間分つくります（絶望）
この正引きファイルの書き方がわからない場合は、ルートDNSではなく、普通のDNSを作りましょう。
ちなみに、逆引きファイルを作成する場合、PTRレコードは必要ないです。

こんな感じでゴリゴリ書いていく感じです。

###まとめ
どうでしたでしょうか（笑）
ぶっちゃけ自分の語彙力も相まって理解できないかもですが、雰囲気としてなんとなくわかってもらえるといいと思います。

時間があれば次回はDNSの構築について一から完全解説してやりたいなと思います。

ではではー
【Django入門】簡単なブログページを作る際の大まかな流れ　～ブログモデル編～

はじめに
===
[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしている<小栗>です。
「プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。

この記事は、[【Django入門】簡単なブログページを作る際の大まかな流れ　～アプリケーション編～](https://qiita.com/keitaro-o/items/3ceda0f3031d11bdfd69)
こちらの記事の続きです！

[Django Brothers](https://www.djangobrothers.com/)というサイトをまとめた
記事になっているので、Django初心者にはおすすめです！

データベースを作る
===
データベースは表のようになっており、テーブルと呼ばれます。
そして、新たにテーブルを作る際、モデルを使います。
モデルとは、データベースとやりとりをするクラスのことです。
クラスとはオブジェクトの設計図のような役割を果たす物です。
このモデルは、各アプリケーション内の``models.py``に記述します。

この内容について以下で説明します。

```python:/django_bog/blogs/models.py

from django.db import models

class Blog(models.Model):
    title = models.CharField(blank=False, null=False, max_length=150)
    text = models.TextField(blank=True)
    created_datetime = models.DateTimeField(auto_now_add=True)
    updated_datetime = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title
```

``from django.db import models``について
Djangoにおけるモデル型の基本形で、Blogモデルに継承させて作成していきます。
このクラスをもとに作られたインスタンスはデータベースに保存するという設定をしています。

#####``title = models.CharField(blank=False, null=False, max_length=150)``について
3行目の内容は、``title``というフィールド（列）名をつけています。
この``title``には``models.CharField``という型が指定されていて、文字列を入力できる様にしています。
``blank=False, null=False``はフィールドが空白であることは許容されないという意味です。
``max_length=150``はタイトルが最大150文字という制限がかけられています。

#####``created_datetime, updated_datetime``について
これらのフィールドでは、``models.DateTimeField``という型が指定されているので、日時情報が保存されるようになっています。
引数で``auto_now_add, auto_now``が与えられているので、それぞれインスタンスが作成された日時、更新された日時が自動的に保存されます。

#####``def __str__(self)``について
これは各インスタンスを表示する際に利用する文字列を表しています。
つまり、ブログ一覧のようなページで、タイトルを表示するのか、本文を表示するのか、はたまた追加日時を表示するのかといった設定ができます。
``return self.title``とするとタイトルが、``return self.text``とすると本文が表示されるということです。

マイグレーション
===
データベースを作成する際の流れは**「models.pyファイルで設計 → マイグレート処理で反映」**です。
従って先ほどまで作っていたmodels.pyファイルをマイグレートしてデータベースに反映させる必要があります。
その際に必要なコマンドは以下の二つです。

```terminal:django_blog
$ python manage.py makemigrations
$ python manage.py migrate
```
#####``$ python manage.py makemigrations``について
django_blog/blogs/migrationsディレクトリの中にマイグレーションファイルが新たに追加されます。
マイグレーションファイルとはmodels.pyファイルで作成したデータベースの設計情報がまとめられたものです。

#####``python manage.py migrate``について
マイグレーションファイルの情報をデータベースに反映させるコマンドです。

※models.pyファイルを変更した際はその都度、マイグレード処理が必要になります。


Adminページを利用する
===

#####スーパーユーザーアカウントを作成
``$ python manage.py createsuperuser``

Adminページを編集するために、``admin.py``ファイルを編集します。
#####BlogモデルをAdminに追加する
```python:django_blog/blogs/admin.py
from django.contrib import admin 
from .models import Blog　#admin.pyファイルと同じ階層にあるmodels.pyファイルで定義したBlogモデルをインポートしている。

admin.site.register(Blog) #インポートしたBlogモデルを、Adminページで利用できるようにしている。
```
Yamahaルーターで自前DNSをDHCPで配る方法

# はじめに
どこのルーターでもDNSを変える事ってできると思うんですが、ルーター自体の使うDNSとDHCPで配るDNSって変えたいことありますよね。
自分はLAN内で名前を振っているサーバーがあるので、自前DNSというかルーター内での名前解決を優先したかったのですが、少しハマった？ので忘備録までに…。

# 起きたこと
Yamahaルーターに、以下の設定をしていたのですが、

```bash
dns server 1.1.1.1 1.0.0.1 # ルーター内での名前解決のため
ip host xxx.local 192.168.0.xxx # LAN内サーバーの名前解決のため
```

DHCPで配られるDNSのIPが`192.168.0.1, 1.1.1.1, 1.0.0.1`になってしまってました。
そのため、名前解決に使用されるDNSが分散され、1/3の確率でしか`xxx.local`が引けなくなっていました。
そう、`dns server`で設定したDNSはDHCPで配布されるDNSに自動で設定されるのです。

# 直し方
行ったことは単純で、DHCPで配るDNSを手動で設定しただけです。

```bash
dhcp scope option 1 dns=192.168.0.1
```

これで、うまいことルーターだけがDNSとして配布されました。
ドキュメントちゃんと読まないとだめですね…。
[C#] 数値型間でGenericに型変換したい

# 数値型間でGenericに型変換したい

こういうことがやりたいんです。

```C#
static TResult Convert<T, TResult>(T number)
{
	return (TResult)number; // エラー: 型 'T' を 'TResult' に変換できません
}

static void Main(string[] args)
{
	double x1 = 137.036;
	int y1 = Convert<double, int>(x1);
	Console.WriteLine(y1);  // 137

	int x2 = 42; // 42
	long y2 = Convert<int, long>(x2);
	Console.WriteLine(y2);  // 42

	sbyte x3 = -1;
	byte y3 = Convert<sbyte, byte>(x3);
	Console.WriteLine(y3);  // 255
}
```

これがアップ/ダウンキャストのみならば次のようにできます。

```C#
static TResult ConvertViaObject<T, TResult>(T number)
{
	return (TResult)(object)number; // object型を経由する
}

static void Main(string[] args)
{
	int[] array = new int[] { 1, 1, 2, 3, 5 };
	IReadOnlyCollection<int> collection = ConvertViaObject<int[], IReadOnlyCollection<int>>(array);
	IList<int> list = ConvertViaObject<IReadOnlyCollection<int>, IList<int>>(array);
}
```

同じことをすればビルドは通ります。しかし実行時に落ちます。

```C#
double x1 = 137.036;
int y1 = ConvertViaObject<double, int>(x1);  // System.InvalidCastException
```

## 解決法1: System.Convert.ChangeType
`System.Convert` にはType型を引数に取る`ChangeType`という関数があります。
ただし、これはcheckedで変換されるようです。それでもかまわない、その方が良いという場合はこれが使えます。
また、型変換をユーザー定義した場合は使えません。

```C#
static TResult ConvertViaChangeType<T, TResult>(T number)
{
	unchecked  // 無意味
	{
		return (TResult)Convert.ChangeType(number, typeof(TResult));
	}
}

static void Main(string[] args)
{
	double x1 = 137.036;
	int y1 = ConvertViaChangeType<double, int>(x1);
	Console.WriteLine(y1);  // 137

	int x2 = 42;
	long y2 = ConvertViaChangeType<int, long>(x2);
	Console.WriteLine(y2);  // 42

	sbyte x3 = -1;
	byte y3 = ConvertViaChangeType<sbyte, byte>(x3); // System.OverflowException
	Console.WriteLine(y3);
}
```

## 解決法2: 場合分け

**ゴリ押し** ~~呼び出し側で分けた方が良いんじゃないか~~
T4テンプレートを使えば、まあ全列挙も出来るでしょう。
ユーザー定義型変換は都度追加する必要があります。


```C#
static TResult ElefantConvert<T, TResult>(T number)
{
	if (typeof(T) == typeof(sbyte) && typeof(TResult) == typeof(sbyte))
	{
		return (TResult)(object)number;
	}
	if (typeof(T) == typeof(sbyte) && typeof(TResult) == typeof(byte))
	{
		return (TResult)(object)(byte)(sbyte)(object)number;
	}
	if (typeof(T) == typeof(sbyte) && typeof(TResult) == typeof(short))
	{
		return (TResult)(object)(short)(sbyte)(object)number;
	}
	/*
	 * 
	 */
	if (typeof(T) == typeof(byte) && typeof(TResult) == typeof(sbyte))
	{
		return (TResult)(object)(sbyte)(byte)(object)number;
	}
	/*
	 * 
	 */

	throw new NotSupportedException();
}
```

## 解決法3: 動的に

この記事の本題はこれです。
dynamic型を経由することで期待通りの動きになります。
ユーザー定義型変換も使えます。

```C#
static TResult ConvertViaDynamic<T, TResult>(T number)
{
	return (TResult)(dynamic)number;
}

static void Main(string[] args)
{
	double x1 = 137.036;
	int y1 = ConvertViaDynamic<double, int>(x1);
	Console.WriteLine(y1);  // 137

	int x2 = 42; // 42
	long y2 = ConvertViaDynamic<int, long>(x2);
	Console.WriteLine(y2);  // 42

	sbyte x3 = -1;
	byte y3 = ConvertViaDynamic<sbyte, byte>(x3);
	Console.WriteLine(y3);  // 255
}
```
【Markdown】 httpリンクをリンクさせたくない

とある資格の受験に向けて、問題集の内容をQiitaの限定共有記事にまとめてたんですが、HTTPリンクを入力するとき、そのまま入力しちゃうと、
http://qiita.com
のようにリンクを貼ってしまうので、どうにかできないものかと思い、試行錯誤したので、そのアウトプット。

###やりたかったこと。
markdown（Qiitaのエントリ）で\<a>タグのhref属性で書いたhttpリンクをリンクさせず、ただの文字列として表示したい。

###やったこと。
下記２点（３点）でとりあえず私の目的は達成できたのでよしとしました。

①まず、\<a>タグ自体はバックスラッシュ("\")でエスケープ。

これだけだと下記入力がおかしな表示内容に変換されてしまう。↓↓

```html:入力内容
\<a href="http://qiita.com">qiita\</a>
```

【表示結果】
\<a href="http://qiita.com">qiita\</a>

②http://~の文字列をバッククオート("`")でインラインコード化

すると、上記表示が下記のように変化。

```html:入力内容
\<a href="`http://qiita.com`">qiita\</a>
```

【表示結果】
\<a href="`http://qiita.com`">qiita\</a>

ここまでやってから、最初から下記③でよかったじゃん、、、となりました。

③\<a>タグ全体をバッククオート("`")でインラインコード化

```html:入力内容
`<a href="http://qiita.com">qiita</a>`
```

【表示結果】
`<a href="http://qiita.com">qiita</a>`


####所感
エントリに残すほどでもないかもしれませんが、困って焦っている時ほど難しく手間のかかる方法に発想が向きやすい性格なので、「もっとシンプルに考えろ！」という反省として残しておきます。
project euler 36 + 2進数変換

http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2036

> Problem 36 「二種類の基数による回文数」
> 585 = 1001001001 (2進) は10進でも2進でも回文数である.
> 
> 100万未満で10進でも2進でも回文数になるような数の総和を求めよ.
> 
> (注: 先頭に0を含めて回文にすることは許されない.)

ワンライナーで行けた。

```js
(max=>(
  ( rev=n=>String(n)
             .split("")
             .reverse()
             .join(""), 
    b
  )=>[...Array(max)]
      .map((_,i)=>++i)
      .filter(e=>String(e)==rev(e))
      .filter(e=>(b=Number(e).toString(2))==rev(b))
      .reduce((a,c)=>a+c, 0) // 872187
)())(1000000)
```

これワンライナーで行けるのはNumber#toString(radix)のおかげだと思う。

ちなみに真面目に2進数化する処理を書いてみるとこんな感じに。

```js
const bin = n =>{
  let a = String(n).split("").map(Number), b = [];
  while( a.some(e=>e>0) ){
    for(let i = 0, s = a.length, c; i < s; i++){
      c = a[i]%2, a[i] -= c, a[i] /= 2;
      if(i+1 < s){ a[i+1]+=c*10; continue; }
      b.push(c);
    }
  }
  return b.reverse().join("");
};
```
Travis CI で "Skipping a deployment with the <PROVIDER> provider because this branch is not permitted: <BRANCH>" と言われるときは多分 deploy: on: branch: <BRANCH> が足りない

## 概要

Travis CI でジョブが実行されたものの

```
Skipping a deployment with the <PROVIDER> provider because this branch is not permitted: <BRANCH>
```

みたいなメッセージが出力されててデプロイできてない！　どうして！
という場合は `.travis.yml` の `deploy` 要素に `on: branch: <BRANCH>` が足りてないはずなので追加しましょう、というお話です。完。


## 例

GitHub と Travis CI を連携させていて「`master` ブランチは本番環境に、`develop` ブランチは開発環境にデプロイしたいよー」という状況があるとします。
このとき一旦 `develop` ブランチについての設定だけ `.travis.yml` に書いたとします。

こんな感じ：

```yaml:.travis.yml
branches:
  only:
    - develop
deploy:
  provider: script
  ...
script:
  - ...
```

「`branches` の `only` に `develop` を指定したしこれでいけるやろ」と思って `develop` ブランチのファイルに変更を加えてジョブの経過を見守るんですが、そこで

```
Skipping a deployment with the script provider because this branch is not permitted: develop
```

とか言われてデプロイできないんですね。しょんぼりですね。

こうなってしまうのは `deploy` 要素に `on: branch: develop` がないからです。
なのでこの設定を追加します。
こんな感じ：

```yaml:.travis.yml
branches:
  only:
    - develop
deploy:
  provider: script
  on:                # 追加
    branch: develop  # 追加
  ...
script:
  - ...
```

これで OK 。


## おまけ：`branches` と `deploy`

### `branches`

`branches` に指定するのは「デプロイするブランチ」ではなく「ビルドする (もしくはしない) ブランチ」です。
もっと細かく言うと「ビルドを実行するためのトリガーとする (もしくはしない) ブランチ」です。

`branches` に `only` 要素を設定すると、そこに指定したブランチが更新された場合にビルドを実行します (セーフリスト) 。
`only` ではなく `except` 要素を設定すると、そこに指定したブランチ **以外** が更新された場合にビルドを実行します (ブラックリスト) 。
`only` と `except` の両方が設定された場合は `only` の方が有効になります。
デフォルト (どちらも省略した場合) では `gh-pages` を除く各ブランチが更新された場合にビルトを実行するようです [^1] 。

[^1]: `gh-pages` は GitHub Pages 用の (GitHub における) 特別なブランチ。ただし、現在は `master` ブランチを GitHub Pages で公開することができるのであまり意識しなくてよいはず。

詳細は Travis CI 公式の [Building Specific Branches](https://docs.travis-ci.com/user/customizing-the-build/#building-specific-branches) を参考にしましょう。


### `deploy`

`deploy` にはビルドで作成された資材のデプロイについての設定を記述します。
`deploy` の `on` 要素の中にデプロイするための条件を指定することができ、条件の種類の 1つに `branch` があります。文字通り「そのブランチであればデプロイする」というものです。
`deploy: on: branch: develop` は「ブランチが `develop` であればデプロイする」ということになります。
デフォルト (`branch` が省略された場合) ではデプロイの対象として `master` ブランチが採用された状態になります。

こちらの詳細は [Conditional Releases with `on:`](https://docs.travis-ci.com/user/deployment/#conditional-releases-with-on) を参考にしましょう。


**おしまり**
Go1.13で導入されたsyscall/jsのjs.CopyBytesToGoとjs.CopyBytesToJSを試してみた

Go 1.13がリリースされたので、`syscall/js` に新しく追加された`js.CopyBytesToGo`と`js.CopyBytesToJSS`を試してみました。

`js.CopyBytesToGo`はUint8arrayをGoのバイトスライスにコピーします。`js.CopyBytesToJSS`はGoのバイトスライスをUint8Arrayにコピーします。

元々は、[`TypedArrayOf()`](https://github.com/golang/go/blob/2bd767b1022dd3254bcec469f0ee164024726486/src/syscall/js/typedarray.go) を使っていたのが、1.13で、`CopyBytesToGo`と`CopyBytesToJS`に置き換わっています。

# js.CopyBytesToGo
## Go側の使用例
Javascriptのuint8arrayをGoのバイトスライスに変換する例です。`js.CopyBytesToGo` は、第一引数がGoのバイトスライス、第二引数がJavascriptのUint8arrayです。

```golang
func PassUint8ArrayToGo(this js.Value, args []js.Value) interface{} {
	received := make([]byte, args[0].Get("length").Int())
	_ = js.CopyBytesToGo(received, args[0])
	fmt.Println(received)
	return nil
}


func registerCallbacks() {
	js.Global().Set("PassUint8ArrayToGo", js.FuncOf(PassUint8ArrayToGo))
}

func main() {
	c := make(chan struct{}, 0)
	registerCallbacks()
	<-c
}
```

## javascript側の使用例
javascript側からは以下のようにGoの関数を呼び出します。

```javascript
function passUint8ArrayToGo(){
	array_to_pass = new Uint8Array([0, 9, 21, 32])
	console.log(array_to_pass)
	PassUint8ArrayToGo(array_to_pass)
}
```

出力は以下のようになります。

```sh
Uint8Array(4) [0, 9, 21, 32]  # console.log()での出力
[0 9 21 32]                   # fmt.Println()での出力
```

# js.CopyBytesToJS
## Go側の使用例
js.CopyBytesToJSは、第一引数がUint8Array、第二引数がバイトスライスです。注意点は、srcの長さとdstの長さの短いほうの要素だけがコピーされる点です。なので、javascriptから渡したUint8Array
生成時に長さをちゃんと設定しておく必要があります。

```golang
func SetUint8ArrayInGo(this js.Value, args []js.Value) interface{} {
	_ = js.CopyBytesToJS(args[0], []byte{0, 9, 21, 32})
	return nil
}


func registerCallbacks() {
	js.Global().Set("SetUint8ArrayInGo", js.FuncOf(SetUint8ArrayInGo))
}

func main() {
	c := make(chan struct{}, 0)
	registerCallbacks()
	<-c
}

```

## javascript側の使用例
javascript側からは以下のようにGoの関数を呼び出します。Uint8Arrayを生成したときに長さを与えていない例と与えている例を書いています。

```javascript
function setUint8ArrayInGo(){
	array_to_set = new Uint8Array()
	SetUint8ArrayInGo(array_to_set)
	console.log(array_to_set)

	array_to_set = new Uint8Array(4)
	SetUint8ArrayInGo(array_to_set)
	console.log(array_to_set)
}
```

出力は以下のようになります。

```sh
Uint8Array []
Uint8Array(4) [0, 9, 21, 32]
```

# ソース
githubに置いておきました。

https://github.com/neko-suki/syscal_js_1.13

<!-- 1.12での使い方はこの辺 https://github.com/hajimehoshi/ebiten/blob/master/internal/jsutil/go112_js.go -->
GAS で zip を返す API を作りたかった

ただの備忘録です

## `doGet` から ZIP をダウンロードできるようにしたかった

GAS では HTTP アクセスを受け付けるウェブアプリ的なものが作成できますが、以下の要件を満たす必要があります。

> **Requirements for web apps**
> A script can be published as a web app if it meets these requirements:
> 
> - It contains a `doGet(e)` or `doPost(e)` function.
> - The function returns an HTML service `HtmlOutput` object or a Content service `TextOutput` object.
> 
> (雑な日本語訳)
> **ウェブアプリの要件**
> 以下の要件を満たしている場合、スクリプトをウェブアプリとして公開できます。
> 
> - `doGet(e)` または `doPost(e)` 関数があります。
> - これらの関数は HTML サービスの `HtmlOutput` オブジェクトまたはコンテンツ・サービスの `TextOutput` オブジェクトを返します。
> 
> [Web Apps | Apps Script | Google Developers](https://developers.google.com/apps-script/guides/web#requirements_for_web_apps)

つまりバイナリである ZIP ファイルを返してダウンロードことはできません。

## base64 エンコードする

仕方ないのでみんな大好き base64 エンコードします。

``` ts
const file = Utilities.newBlob('', 'text/plain', 'test.txt').setDataFromString('test', 'utf-8');
const zip = Utilities.zip([file], 'test');
const base64 = Utilities.base64Encode(zip.getBytes());
return ContentService.createTextOutput()
  .setContent(base64)
  .setMimeType(ContentService.MimeType.TEXT);
```

URL の発行時は**次のユーザーとしてアプリケーションを実行:**を**自分**、**アプリケーションにアクセスできるユーザー:**を**全員（匿名ユーザーを含む）**に設定することで、認証が不要になります。（つまり URL さえ知っていれば誰でもアクセスできてしまうので注意。）

後はダウンロードする側でデコードすれば普通の ZIP になります。

``` bash
GAS_URL=# GAS の URL
curl -L ${GAS_URL} | base64 -d > test.zip
unzip test.zip
cat test.txt
test
```
Reactでの二重ループ

## Reactチュートリアルで作るマルバツゲームの盤面を二重ループで作成する

React、Javasctipt初心者であり、非常に手こずったためメモ。

```React:index.js
class Board extends React.Component {
    renderSquare(i){
        return (
            <Square 
                value={this.props.squares[i]} 
                onClick={() => this.props.onClick(i)}
            />
        );
    }
    Content(i){
        let content=[];
        for(let j=i;j<i+3;j++){
            content.push(this.renderSquare(j));
            }
        console.log(content);
        return content;
    }
    render(){
        let items = [];
        for(let i=0;i<9;i=i+3){
            items.push(<div className="board-row" key={i}>{this.Content(i)}</div>); 
        }
        
        return(
            <div>
                {items}
            </div>
        );
    }
}
```

普通にDOMをfor文に入れても記述できず、配列にpushしたものをレンダリングする必要がある。
また、二重ループの場合は、for文内でpush後にjsコードを記述することができないため、関数を用いる必要がある。
ここで、無名関数で行いたいところであるが、無名関数で行うと、「renderのなかでreturnを返すな」というwarningが出る。そのため、class内でメソッドを定義し、それを用いることになる。

一応これの通りにチュートリアルのコードを書き換えれば、二重ループでマスがレンダリングできる。

おそらくもっとスタイリッシュでクレバーな書き方があると思うけれどとりあえず。
これから先、二重ループを用いる時のためにメモをしておく。
初心者がサイコロを振るDiscord Botを作った

初投稿です。
Python初心者故至らぬ点等多々あると思いますが、気軽に読んでくださると幸いです。
アドバイス等していただけるととても嬉しいです。

2019/09/09 受け取ったメッセージのサイコロの面数と個数を変数に受け渡す所と、サイコロの目の総和を計算する部分を改良しました。素晴らしいアドバイスありがとうございます！

# 今回作るものの目標
Discordで`!dice AdB`(Aはさいころの個数、Bはさいころの面数、ABともに1以上)と入力すると、サイコロを振った結果を表示するBotを作る。

# 環境
* Windows10
* discord.py 1.2.3
* Python 3.7.3

# 事前準備
botの準備
>
Pythonで簡単なDiscord Botの作り方
https://qiita.com/PinappleHunter/items/af4ccdbb04727437477f
Discord Bot 最速チュートリアル【Python&Heroku&GitHub】
https://qiita.com/1ntegrale9/items/aa4b373e8895273875a8

この記事がとてもわかりやすいです。

# botの作成
```python:main.py
import discord
import sys

# さいころの和を計算する用の関数
from func import  diceroll

TOKEN = '任意のトークン'

client = discord.Client()

@client.event
async def on_ready():
    print('--------------')
    print('ログインしました')
    print(client.user.name)
    print(client.user.id)
    print('--------------')
    channel = client.get_channel('チャンネルID')
    await channel.send('楽しいTRPGを始めましょう！')

@client.event
async def on_message(message):
    if message.author.bot:
        return
    if message.content.startswith("!dice"):
        # 入力された内容を受け取る
        say = message.content 

        # [!dice ]部分を消し、AdBのdで区切ってリスト化する
        order = say.strip('!dice ')
        cnt, mx = list(map(int, order.split('d'))) # さいころの個数と面数
        dice = diceroll(cnt, mx) # 和を計算する関数(後述)
        await message.channel.send(dice[cnt])
        del dice[cnt]

        # さいころの目の総和の内訳を表示する
        await message.channel.send(dice)

client.run(TOKEN)
```
次に和を計算する関数の内容です。

```python:func.py
import random

def diceroll(cnt, max):
    total = 0
    num_list = []
    for i in range(0, cnt):
        # ランダムに1からサイコロの面数までの和を取得しリストに入れる
        num = random.randint(1, max)
        num_list.append(num)
    # さいころの目の総和を計算しリストに入れる
    total = sum(num_list)
    num_list.append(total)
    return num_list
```

# 結果
ちゃんと総和、内訳ともに表示しました。
![saikoro_bot.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481328/fd5b6fb7-cb87-0e30-c84a-9a5d33f8b5f3.png)


ちなみに100d100くらい大きくてもでも表示してくれます。（そんなことしないだろうけど）
![saikoro_bot2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481328/60eb288c-4545-afa3-d395-c389ecdd3414.png)

# おわりに
初めてDiscordのBotを作ってみましたが、思ったより気軽に作れて楽しかったです。
サイコロの総和の計算だったり、命令の受取方だったりいろいろ不格好な場所があるので、これからよりPythonを精進して改良していければなと思います。
他にも色々Bot作ってみたい。

# 参考
事前準備で述べたすばらしい記事及びそのサンプルコード
>
Pythonで簡単なDiscord Botの作り方
https://qiita.com/PinappleHunter/items/af4ccdbb04727437477f
Discord Bot 最速チュートリアル【Python&Heroku&GitHub】
https://qiita.com/1ntegrale9/items/aa4b373e8895273875a8
Android 10も出たしCSSでダークモードに対応する方法を調べてみた

ダークモードに対応したAndroid 10がリリースされました。

これでスマホ２大巨頭であるiOS、Androidがダークモードに対応したことになります。

# @media (prefers-color-scheme)でかんたんに対応できる！

以下ようにすることでダークテーマのときのスタイルを設定することができます。

```css
@media (prefers-color-scheme: dark) {
  /* スタイル */
  ...
}
```

<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="result" data-user="tkt989" data-slug-hash="KKPQPRW" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="dark mode">
  <span>See the Pen <a href="https://codepen.io/tkt989/pen/KKPQPRW/">
  dark mode</a> by tkt989 (<a href="https://codepen.io/tkt989">@tkt989</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

以前でもアプリやWebサービスが独自にダークモードに対応していましたが、
「読みやすい」「オシャレ」などの理由で、使っている人が多かったのではないでしょうか。

しかし、iPhoneXなど有機ELを搭載したデバイスが増えてきたことにより、バッテリー持ちが良くなるという実用的なメリットも出てきました。
バッテリー持ちについては、Googleも認めています！

参考： [ダークモードはバッテリーの持ちにヨシ！とGoogleがキッパリ。ただし有機ELに限る | ギズモード・ジャパン](https://www.gizmodo.jp/2018/11/dark-mode-is-effective-for-power-saving.html)
Elmでベタ打ちしていたcssを別ファイルに切り出したい時に便利な正規表現

elmでベタ打ちしていたcssを別ファイルに切り出したい時がある

``` elm:切り出し前.elm
    div
        [ div
            [ class "class"
            , style "background" "white"
            , style "position" "absolute"
            , style "width" "80vw"
            , style "height" "50vh"
            , style "margin" "auto"
            , style "top" "0"
            , style "right" "0"
            , style "bottom" "0"
            , style "left" "0"
            , style "border-radius" "10px"
            , style "border" "1px"
            ]
            [ text "hoge"
            ]
        ]
```

コピペしただけだと（当然だが）syntaxが違うので動かない

``` css:コピペしただけ.css
            , style "background" "white"
            , style "position" "absolute"
            , style "width" "80vw"
            , style "height" "50vh"
            , style "margin" "auto"
            , style "top" "0"
            , style "right" "0"
            , style "bottom" "0"
            , style "left" "0"
            , style "border-radius" "10px"
            , style "border" "1px"
```

コピペして切り出したCSSもどきに対して、下記の正規表現をかけるとCSSの文法通りの形に変えられる

``` text:vscodeの場合
, style "(.*)" "(.*)" -> $1: $2;
```

``` text:sedとかの場合
, style "(.*)" "(.*)" -> \1: \2;
```

結果

``` css:result.css
	background: white;
	position: absolute;
	width: 80vw;
	height: 50vh;
	margin: auto;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	border-radius: 10px;
	border: 1px;
```
【ネットワーク基礎】1.ネットワークの概要

ネットワークとは、コンピュータを電波やケーブルなどで接続し、情報交換ができる仕組みのことです。
これは僕が一番大事だと思うことです。多分、ネットワークと聞くと抽象的でなんとなくなイメージを持っていると思いますが、
コンピュータ同士を接続する仕組みだという具体的なイメージを持っていないと、
後で頭の中が整理できず困ることになるのでしっかりイメージ付けておきましょう（経験談）


#LANとWAN

ネットワークは、LANとWANに分類することができます。

●LAN
「無線LAN」など聞き馴染みがあると思います。
**LANとは、近くのコンピュータ同士が接続されたネットワークのことです。**

極小単位で考えると、２台のPC同士をなんらかのケーブルで繋ぐことによって情報交換ができればLANというネットワークの完成です。

LANはLocal Area Networkの略で、限定されたエリアにおけるネットワークという意味です。

各会社、学校、家などの単位でLANが構築されています。

![IMG_0045.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479095/b422706c-12c1-f226-2df8-8975d981af79.png)
手書きで申し訳ありません。

●WAN
あまり聞き馴染みがないと思います。僕はありませんでした。
**WANとは、LANとLANを接続したネットワークです。**

本社と支社をつないでいるのもWANです。
自分の家の無線LANと友達の家の無線LANを繋いでいるのもWANです。

![IMG_0046.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479095/ca77d1d3-471f-c154-ee9f-dc40af61fd46.png)


現在、LANとLANを接続する役目を果たしているのは電気接続事業者とISPです。
図は極小視点でイメージしたものなので、電気通信事業者とISPは関わっていない前提です。

電気接続事業者とISPについてはすぐ下で説明するので読み進めてください。


#インターネット

聞き馴染みありすぎる言葉だと思います。
ですが、これも最初は抽象的でよくわからないと思うのでしっかり頭に入れておくといいと思います

インターネットと聞くと、わけわからないけど色んな人と通信できるすごいものでしょ。って思うと思いますが、単に無数のLANが接続されてできたものです。
つまり巨大なWANです。

単に無数のLANが接続されているといいましたが、なんの工夫もなしにケーブルでLAN同士を繋いでも
ケーブル接続費に無駄にお金がかかります。
なぜかというと、今いる家のLANと日本中のLANを全通りつなぐと大変なことになりますよね。笑
全通り繋がないとしたら、下流に存在しなければいけないLANが出てきます。
すると、上流のLANが故障したら、下流のLANは接続不可能になります。
そこでISPが登場しました。

具体例をあげてみます。

WANを構築するために大学や研究機関のLANをそれぞれ相互接続していたとします。
費用がかかるので全通りケーブルで繋がず、下図のような構成になっていたと思います。

![IMG_0044.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479095/66e78982-1b74-7608-f797-7d0ce87646a4.png)


ですが、これだとAのLANが故障すれば下流のB,Cは接続ができなくなってしまいます。

そこで、「うちが安定した接続を保障するから、みんなうちに繋ぐといいですよ（お金はとりますが）」という組織ができました。
これがISP（インターネットサービスプロバイダ）です。
最初は非営利団体だったみたいです。

そして、「うちはそれぞれケーブルをつないであげるよ（お金はとるけど）」と協力する組織ができました。
これが電気接続事業者です。

ISPは

もちろん例なので本当にこのような流れでてきたかはわかりませんが、
インターネット、ISP、電気通信事業者を理解する上では問題ないと思います。

見ると理解が深まる
・ISP
https://ja.wikipedia.org/wiki/インターネットサービスプロバイダ
・ISPと通信事業者
https://www1.gifu-u.ac.jp/~hry_lab/book/1provider.pdf
・ARPAnet（インターネットの起源）
https://ja.wikipedia.org/wiki/ARPANET

※今回紹介したこと以外にもIXなどの色々な事業が存在しますが、今回はネットワークの基本の概要について書いているのでインターネットの詳しい説明については今後書く予定です。
（僕もまだまだ勉強しないといけないのもあるので）

#豆知識
インターネットで大きな役割を果たしているのがISPと電気通信事業者だということは分かっていただけたと思いますが、インターネット上にこの二つの要素では足りないのです。
それは、コンピュータです。コンピュータを提供する会社があります。
スマホの場合、auやsoftbankなどがあります。

つまり、インターネット上に必要な要素は
・コンピュータメーカー
・電気通信事業者
・ISP
ということになります。


#まとめ
・ネットワークにはLANとWANがある
・LANは組織内でのネットワーク
・LANとLANを繋ぐのがWAN
・インターネットは無数のLANの接続による巨大なWAN
・インターネットはコンピュータメーカー、電気通信事業者、ISPによって成り立っている。
MATLABでフィッティング


# はじめに
実験装置から得た信号から，パラメータを抽出するためにフィッティングを行うことがあるかと思います（頻繁に）．一方で，「いざ信号を得たのにやり方がわからない！」という初心者もいらっしゃるのではないでしょうか．事実，私も初めは何をすればいいのやらわからず調べ調べでなんとか出来るようになりました．本稿ではそのクイックスタートと注意点を述べ，さっそく取り掛かれるようにしたいと思います．

## 用いるデータと解析式
ここでは，汎用性を考えて非線形データを用います．非線形データができれば，線形データは取るに足りません．
（※線形データは別のコマンドでより簡単に行えます）

後にフィッティングを理論式で行うために，今回はローレンツ関数を用います．データを再現する理論式は次式で表されるものとしましょう．

```math
y = S\frac{W^2}{(x-x_0)^2 + W^2} + A\frac{(x-x_0)W}{(x-x_0)^2 + W^2}  
```

ここで，

$S$ : 対称ローレンツ関数の係数
$A$ : 反対称ローレンツ関数の係数
$x_0$ :　$x$方向のずれ
$W$ : 信号の線幅（半値半幅）

とします．
これらが求めたいパラメータです．

##　いざフィッティング
フィッティングした結果を下に示しました．

![STFMR_spectrum2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384231/1562f0e6-6997-9569-ee55-d5463ae73433.png)


上の図が，実験データとそのフィッティング．
下の図は，フィッティングデータをさらに分解したものです（理論式を参照）．

このように，任意の関数について，理論式があれば基本的になんでもフィッティングすることができます．
ただし，フィッティングの方式（LM法など），フィッティングの開始点の有無にもよってもその可否が決まってしまうため，適宜パラメータを調節する必要があります．

##コード
以下に用いたコードを示します．


``` Fitting.m
clc
clear all

#データのインポート
data = dlmread('4171003-12.txt100mW-7.0GHz.txt'); 

#データの前処理
N_data=size(data,1); 
N_data1_end = N_data/2-N_data1_start; 
N_data2_start = N_data/2+N_data1_start; 
N_data2_end = N_data-N_data1_start; 

for i = N_data1_start : N_data1_end
    x1(i-N_data1_start+1) = data(i,1);
    y1(i-N_data1_start+1) = data(i,2)*1e+6;
end

x1 = x1';
y1 = y1';

for j = N_data2_start : N_data2_end
    x2(j-N_data2_start+1) = data(j,1);
    y2(j-N_data2_start+1) = data(j,2)*1e+6;
end

x2 = x2';
y2 = y2';

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%フィッティング形式の設定
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
f1 = fitoptions('Methods','NonlinearLeastSquares',...
                'StartPoint',[10 -50 40 10 0],...
　　　　　　　　　　'Algorithm','Levenberg-Marquardt') 
f2 = fitoptions('Methods','NonlinearLeastSquares',...
                'StartPoint',[10 50 -40 10 0],...
                'Algorithm','Levenberg-Marquardt') 

           
%フィッティング式
ft1 = fittype('S*W^2/((x-H_res)^2+W^2)+A*((x-H_res)*W)/((x-H_res)^2+W^2)+Y','options',f1);
ft2 = fittype('S*W^2/((x-H_res)^2+W^2)+A*((x-H_res)*W)/((x-H_res)^2+W^2)+Y','options',f2);

%フィッティングされるパラメータの確認（一度確認すればなくても良い）
coeff = coeffnames(ft1) 

%フィッティング．引数に(x1,y1)，フィッティング形式にft1などとする．
[curve1] = fit(x1,y1,ft1)
[curve2] = fit(x2,y2,ft2)

%フィッティングされたパラメータをparameter1, 2に格納．
parameter1 = coeffvalues(curve1);
parameter2 = coeffvalues(curve2);


%フィッティングパラメータを取り出し．
H1_res = parameter1(2);
S1 = parameter1(3);
A1 = parameter1(1);
W1 = parameter1(4);
Y1 = parameter1(5);

H2_res = parameter2(2);
S2 = parameter2(3);
A2 = parameter2(1);
W2 = parameter2(4);
Y2 = parameter2(5);

```





データの前処理は，データ形式によって方法が異なるでしょう．
MATLABで用いるフィッティングでは，x, yをリスト形式で持っておけば"fit(x,y,ft)"によって無事に行えます．
得られたパラメータを用いて，グラフにするなりするのはより簡単に行えるでしょう〜
【C#】文字列とenumの変換テクニック集

# はじめに
文字列とenumを相互に変換することが結構多いため、テクニック集としてまとめることにしました。
同じ境遇にあったC#erの皆さんにも伝わればいいなと思います。

サンプルコードで使用するenumを毎回記述するのは冗長なため、ここに記述しておきます。
（適当にサンプル用に定義しただけなので、このenumに意味はほとんどありません。）

```cs
enum Authority
{
    ReadWrite,  // 読み書き可能
    Read,       // 読み込み専用
    None        // 権限なし
}
```

# 文字列 から enum への変換
文字列からenumへ変換する際に整数型にキャストしてからenumへキャストしたりしていませんか？

```cs
Authority auth = (Authority)int.Parse("1");  // こんな感じ
Console.WriteLine(auth);
```

```sh:出力結果
Read
```

いちいち整数型にキャストするのは面倒ですよね。
`Enum.Parse(Type, String)`を使えば整数型へのキャストは不要です。

```cs
Authority auth = (Authority)Enum.Parse(typeof(Authority), "1");
Console.WriteLine(auth);
```

```sh:出力結果
Read
```

さらに嬉しいことに`Enum.Parse(Type, String)`は名称からenumを取得することもできます。

```cs
Authority auth = (Authority)Enum.Parse(typeof(Authority), "Read");
Console.WriteLine(auth);
```

```sh:出力結果
Read
```

名称の大文字小文字が合わないというときは`Enum.Parse(Type, String, Boolean)`を使いましょう。
第3引数に`true`を指定すれば、大文字と小文字を区別せずに変換できます。
ちなみに以下の例で`true`を指定しない場合は`System.ArgumentException`が発生します。

```cs
Authority auth = (Authority)Enum.Parse(typeof(Authority), "read", true);
Console.WriteLine(auth);
```

```sh:出力結果
Read
```

```sh:trueを指定しない場合の出力結果
System.ArgumentException: 要求された値 'read' が見つかりませんでした。
```

`.NET Core`であれば`Enum.Parse`にジェネリックバージョンがあるようで、以下のような記述も可能です。
enumへのキャストが無い分スッキリした記述になっています。
（`.NET Framework`でもできるようになるといいなぁ）

```cs
Authority auth = Enum.Parse<Authority>("Read");
Console.WriteLine(auth);
```
```sh:出力結果
Read
```

```cs
Authority auth = Enum.Parse<Authority>("1");
Console.WriteLine(auth);
```
```sh:出力結果
Read
```

# enum から 文字列 への変換
今度は逆にenumから文字列へ変換する場合を考えてみます。
enumを整数型にキャストしてから文字列に変換したりしてませんか？

```cs
string authValue = ((int)Authority.ReadWrite).ToString(); // こんな感じ
Console.WriteLine(authValue);
```

```sh:出力結果
0
```

そんなときは`Enum.ToString(String)`を使って書式を指定すればキャストせずとも文字列を取得できます。
指定できる書式については、[こちら](https://docs.microsoft.com/ja-jp/dotnet/api/system.enum.tostring?view=netframework-4.8#System_Enum_ToString_System_String_)を参照してください。

```cs
string authValue = Authority.ReadWrite.ToString("d");
Console.WriteLine(authValue);
```

```sh:出力結果
0
```

# まとめ
文字列とenumの変換についてまとめてみました。
Enumクラスについてもっと知りたい場合は[こちら](https://docs.microsoft.com/ja-jp/dotnet/api/system.enum?view=netframework-4.8)のドキュメントをご覧ください。
この記事でC#のコードが少しでも綺麗になれば幸いです。

それではまた。
TomoProg
【GAS】Webページが更新されたらGmailに通知する

#2021/2/23追記
以下の記事がより新しいです．キャッシュを利用した改良版です．
【GAS】メールに含まれるURL先の更新を自動で確認
https://qiita.com/golyat/items/3798f17f1836fcffe993
# 概要
GASによるウェブページの汎用的な簡易更新チェッカーです。任意のWebサイトの更新をGmailに通知します。
スマホからの利用を想定してGmailの下書きにURLを貼り付ければ通知してくれます。
作った動機は宅配のページ確認が面倒くさかったからです。

### UI
- スマホで更新確認したいサイトを見つける
- Gmailに共有またはURLコピーでGmailの下書き保存
- サイトが更新された場合はメールで通知してくれる
- 更新確認をやめる場合は下書き削除

### プログラムのフロー
- Gmail下書きからURLを取得
- GASでUrlFetch
- ページ中の文字列をハッシュ値に変換
- 古いハッシュ値と比較
- ハッシュ値が変化していればメール通知とプロパティ更新

#ソース
```javascript
function webMonitor() {
  const myThreads = GmailApp.search('in:draft');
  const myMsgs = GmailApp.getMessagesForThreads(myThreads);
  const urls = myMsgs.map(function(msg) {
    return msg[0].getPlainBody().match(/(http(s)?:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+)/gi);
  }).filter(function(x) {
    return x != null;
  });
  
  urls.map(function(url) {
    const response = UrlFetchApp.fetch(url);
    //文字コード(UTF-8など)の取得(適当、なくてもいいかもしれない)
    const code = response.getHeaders()['Content-Type'].slice(19);
    const html = response.getContentText(code);
    //タイトルとボディーの取得(適当、見た目の問題なので必要ない)
    const title = html.match(/<title>([\s\S]*?)<\/title>/i)[0].replace(/(<|{)("[^"]*"|'[^']*'|[^'">])*(>|})/g,'')
    const body =  html.replace(/<head>[\S|\s]*?<\/head>/g,'').replace(/(<|{)("[^"]*"|'[^']*'|[^'">])*(>|})/g,'').replace(/\s+/g, "");
    //文字コードの総和でハッシュ値化。
    const hashValue = makeHash(body);
    //プロパティにアクセス。プロパティは実行終了後も保存される。
    //文字列全部はサイズが大きすぎるのでハッシュ値化。
    //オブジェクトも保存できない。初期値null。プロパティのkeyにはURLを使う。
    //数字を保存しても文字列として出てくる。
    const dp = PropertiesService.getScriptProperties(); 
    const beforeValue = dp.getProperty(url);
    
    if(hashValue != Number(beforeValue)) {
      dp.setProperty(url, hashValue);
      if(beforeValue != null) {
        GmailApp.sendEmail('xxx@email.address', '【update】'+ title, url)
      }
    }
  });
  
  function makeHash(str) {
    var sum = 0;
    for(var i = 0; i < str.length; i++) {
      sum += str.charCodeAt(i)
      sum %= 1000000
    }
    return sum;
  }
}
```

#終わりに
ハッシュ値がぶつかることもあるので100%通知されるとは限らない。個人利用ということで気にしない。
ちゃんと通知させたい方はハッシュ関数をもっとちゃんとしたものにすると良いかもしれない。
GASに限りませんがフェッチする頻度が高いとGASサーバにも相手サーバにも負荷をかけることになるのでご利用は計画的に。
サイトによってはフェッチできないのでエラー処理で通知はあった方がいいかもしれない。
LINE、Slack、Twitterでやりたい方はそれぞれのAPI叩いてください。
#更新
2019.9.20:ちょっとした書き換え。修正。

#参考資料
https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app
https://developers.google.com/apps-script/reference/url-fetch/http-response
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt
組み込みソフトウェアの問題を機械学習で解決しようとして失敗した話

# はじめに
現在組み込み系ソフトウェア開発に従事しておりますが、私が担当している機能では慢性化している問題があり、ある日上司より、「この問題の解決に取り組んでくれ」と振られたので、問題解決に取り組んでいく過程で機械学習アルゴリズムを使ってみたけどうまくいかなかった、というお話です。


# どんな問題に対して機械学習使おうとしたの？
詳しくは書けませんが、簡単に説明すると異常か正常かを分類して、異常と判断した時は適切な処理をする、といった具合です。

ただし様々な事情があり、今回改修をする上で「正常時を異常時と判定することは不可」という条件付きになります。


# どんな機械学習アルゴリズムを使ったの？
ロジスティック回帰分析を使いました。そもそもロジスティック回帰は統計モデルか機械学習アルゴリズムか意見が分かれそうですが、一応ここでは機械学習ということで説明を続けます。(はっきりと決められているなら教えていただけると幸いです・・)

# どうやってモデルの訓練をしたの？
日頃から様々なデータを取得していたので、トレーニングデータにはそれらのデータを使いました。

職場にPythonや機械学習ライブラリ等はないので、モデルのトレーニングは仕方なくExcelのソルバー機能で行いました・・

データを集めて自分の手でラベル(異常か正常か)をつけ、Excelに突っ込んで一晩計算させてモデルをトレーニングさせました。

# どうやってソフトウェアに組み込んだの？
Excelでの計算が終わると、重回帰分析の係数に当たる値が表示されるので、その数字をソフトウェアのソースコード内に組み込みました。

ロジスティック回帰分析は重回帰分析で結果を出力した後、さらに計算式を用いて最終的な確率を算出させます。


```c
#define KEISU1 100 /*Excelから取り出した値*/
#define KEISU2 200 /*Excelから取り出した値*/
#define TEISU  50 /*Excelから取り出した値*/

y = KEISU * x1 + KEISU2 * x2 + TEISU

prob = 1 - (1/exp(-y))

```

xiはパラメータになります。
probが異常が発生している確率になります。

実際には100個近い特徴を使ってモデルを作成しました。

# で、どうだったの？
先ほどのソースコードを組み込んでテスト動作をしました。果たして問題となっていた異常
の検出はできるのか。。。。

結果は、精度としては少し改善がみられました。が、エラー分析をしてみると正常時のある特定の場面において、高確率で異常を算出しまうようになりました。

冒頭でも述べましたが、「正常時に異常と判定してはいけない」という前提条件があり、これは当然許容できない問題となりました。

対策として正常なのに異常と判定してしまっているデータを増やし、再度モデルのトレーニングをしましたが、改善しませんでした。
恐らくその問題の状況というのは、本当の異常時とほぼ変わらないデータを算出しているのだと思われます。

たとえ全体的な精度が上昇したとしても、「正常時に異常と判定してはいけない」というルールがあるために、今回作成した機械学習モデルは製品版に組み込めませんでした・・


# まとめ
○○をした上で正常か異常かを判定する、といったようなルール付きだと、機械学習を使うことはなかなか難しいと感じました。

ましてや人間がデータを見て閾値を決めて判定をさせてる訳でなく、アルゴリズムが決めているので、まだまだ機械学習が浸透していない私の職場では人に説明するときに根拠などがなかなか伝わりにくい等の問題もありました。



機械学習難しい・・
ORA-12514: TNS:listener does not currently know of service requested in connect descriptor (Oracle 11g XE)

## 事象
- ローカル開発環境用のXEインスタンスにTNS接続できない
    - ```ORA-12514: TNS:listener does not currently know of service requested in connect descriptor```
- ローカル接続(sqlplus / as sysdba)は問題なし

## 解決した方法

- listener.ora のSID_LISTに明示的にXEのSID_DESCを追記、リスナー再起動により解消
- 発生原因は不明

```
SID_LIST_LISTENER =
  (SID_LIST =
    ### ここから↓ ###
    (SID_DESC =
      (GLOBAL_DBNAME = XE)
      (ORACLE_HOME = C:\oraclexe\app\oracle\product\11.2.0\server)
      (SID_NAME = XE)
    )
    ### ここまで↑ ###
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = C:\oraclexe\app\oracle\product\11.2.0\server)
      (PROGRAM = extproc)
    )
    (SID_DESC =
      (SID_NAME = CLRExtProc)
      (ORACLE_HOME = C:\oraclexe\app\oracle\product\11.2.0\server)
      (PROGRAM = extproc)
    )
  )

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
      (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
    )
  )

DEFAULT_SERVICE_LISTENER = (XE)
```
NEC UNIVERGE IX2105 で EtherIP のオーバーヘッドをみてみた

## 背景

NEC のイケてる VPN ルータで IPSec で暗号化せずに素の EtherIP だけでどのくらいオーバーヘッドがあるのか知りたくなった。

## 構成

(Internet) <-> IX2015 <- IPv6/EtherIP -> IX2015 <--> (PC)

* 2台の IX2105 は同じL2スイッチに接続。
* IPv6 で EtherIP トンネルを構成。

### config

```
ip ufs-cache enable
ipv6 ufs-cache enable

bridge irb enable

ike proposal ike_proposal encryption aes hash sha group 1024-bit
ike policy ike_policy peer <対向のIPv6アドレス> key <共有パスフレーズ> ike_proposal
ike keepalive ike_policy 10 3
ipsec autokey-proposal ipsec_proposal esp-aes esp-sha
ipv6 access-list ipsec_acl permit ip src any dest any
ipsec autokey-map ipsec_map ipsec_acl peer <対向のIPv6アドレス> ipsec_proposal

ipv6 dhcp client-profile dhcpv6_client
  information-request
  option-request dns-servers
exit

device GigaEthernet1
  vlan-group 1 port 1
  vlan-group 2 port 2
exit

interface GigaEthernet0.0
  no ip address
  ipv6 enable
  ipv6 address autoconfig receive-default
  ipv6 dhcp client dhcpv6_client
  no shutdown
exit

interface GigaEthernet1.0
  no ip address
  no shutdown
exit

interface GigaEthernet1:1.0
  no ip address
  bridge-group 1
  no shutdown
exit

interface GigaEthernet1:2.0
  no ip address
  bridge-group 2
  no shutdown
exit

interface Tunnel0.0
  tunnel mode ether-ip ipv6
  tunnel destination <対向のIPv6アドレス>
  tunnel source GigaEthernet0.0
  no ip address
  bridge-group 1
  bridge ip tcp adjust-mss 1404
  no shutdown
exit

interface Tunnel1.0
  tunnel mode ether-ip ipsec
  no ip address
  ipsec policy tunnel ipsec_map df-bit ignore out
  bridge-group 2
  bridge ip tcp adjust-mss 1312
  no shutdown
exit
```

## 測定

* 測定は Speedtest.net を利用。
* 測定先は OPEN Project (via 20G SINET)を指定。

### PC 直結 (比較のために測定)

#### 構成

(Internet) <--> (PC)

#### 結果

![Direct](https://www.speedtest.net/result/8569078994.png) 

### EtherIP

#### 構成

(Internet) <-> IX2015 <- IPv6/EtherIP -> IX2015 <--> (PC)

#### 結果

![EtherIP](https://www.speedtest.net/result/8569084204.png)

### EtherIP over IPsec (おまけ)

#### 構成

(Internet) <-> IX2015 <- IPv6/IPsec/EtherIP -> IX2015 <--> (PC)

#### 結果

![EtherIP over IPsec](https://www.speedtest.net/result/8569087352.png)

### まとめ

IX2105 を2台で構成した環境において EtherIP に通すと、スループットが約60%減、EtherIP over IPsec を通すと約75%減することを知ることができた。
AnacondaをインストールしてPython環境を構築してみるよん

#はじめに
自分がPythonを勉強しようと思った矢先にぶち当たったのは
**「で？なにからはじめりゃいいんじゃ？」**
である。

参考書買うなり、立ち読みするなり、ググるなりすると
書いてある内容どうこう以前に結構ハードルが高かったりする。
（だって、何言ってるかよくわかんないんだもん…）

誰か詳しい方がいたらその人と一緒にやるのがBestではあるが
そんな都合良くいなかったりする。

この方法がBestとは言わないが、「とりあえず意欲だけはある！」
って勢いがある人は深く考えずに以下の準備をしてみよう。

##Anacondaをインストールしてみる

1.Anacondaのインストーラをダウンロードする。
（OSは自分のPCに合わせて選ぼう。バージョンは3.7を選択する。赤矢印のとこ押すとダウンロードできますよ。）
　[リンク]（https://www.anaconda.com/distribution/）
  <img width="544" alt="無題.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493685/bd36daf8-172e-5d2c-8b49-cba8dcba3dc9.jpeg">

2.インストーラを実行する。
<img width="381" alt="無題.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493685/538b0316-0c08-52ad-4465-3bb1d1590f88.jpeg">

3.どんどん「Next」押していきます。（読むなとはいいません。でも自分は読めなかったので無心でポチってましたｗ）
  ただし、このタイミングはちょっと待って下さい。
<img width="375" alt="無題.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493685/25c221f7-f095-a2ab-578b-d94d7a851e5d.jpeg">
Anacondaのインストールのやり方は皆さんたくさん紹介しています。
その中でここだけはやけに意見が分かれます。（俺調べで50：50くらいです。）
上は非推奨とのことですが自分は下だとうまくいきませんでした。
なので上の「Add Anaconda ~」のほうにチェックしてください。
「Install」のボタンを押したらインストールが始まります。

インストール中の画面がおわると
あとは「Finish」が出るまで「Next」でいいです。

4.インストール後は「Anaconda　Navigator」を起動させます。（緑の〇みたいなアイコンのやつ）

5.この画面の「VS code」ってやつの「Install」もしくは「Launch」を押して下さい。
　すでにInstall済なら「Launch」って出ます。まだならインストールが始まります。
　ちなみにVS codeじゃなきゃダメってわけじゃないです。自分の使いやすさで選んだだけです。
　

<img width="678" alt="無題.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493685/fb1a5db9-6187-2b92-ce3a-cd7cfc4df599.jpeg">

6.VS codeを開きます。開いたら赤矢印の箇所を開きます。
<img width="512" alt="無題.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493685/23cb9938-8738-3e46-7a23-e6e7bd171d25.jpeg">

開いたらここで以下の２つは少なくともインストールしておきます。
（自分はこの２つで当分Python書いてた気がする…。まぁ、足りないようであればここは勉強して自分で入れてみてください。）
<img width="505" alt="無題2.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493685/7cbd22d4-8b1e-a93d-ffda-ecdb3a3f60f6.jpeg">

7.ひとまずはこれで終わり（なはず…）



どうでしょう？うまくできましたかね？
間違ってたり、わからない場所があれば教えていただけると助かります。
docker-composeでgpuを使う方法

## 準備
公式のDocker導入方法

https://docs.docker.com/install/linux/docker-ee/ubuntu/

docker、docker-composeがインストールされており、カレントディレクトリにdocker-compose.ymlがあるとする。

```docker-compoose.yml
version: '2.4'
services:
  nvsmi:
    image: ubuntu:16.04
    runtime: nvidia
    environment:
      - NVIDIA_VISIBLE_DEVICES=all
    command: nvidia-smi

```
NVIDIA_VISIBLE_DEVICESについては
[nvidia-container-runtime]
(https://github.com/nvidia/nvidia-container-runtime#environment-variables-oci-spec)

qiitaでは
[NVIDIA GPU が使える Docker イメージの作り方](https://qiita.com/hoto17296/items/be34849412e7ae9db6ff)



## DockerでのGPU使用方法
コンテナ内でgpuを使うには

```
$docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi
```

のように`--runtime=nvidia`でオプション設定する


Docker19.03以降では

```
$ docker run --gpus all --rm nvidia/cuda nvidia-smi
```

のように`--gpus all`でオプション設定する
[nvidia-docker wiki](https://github.com/NVIDIA/nvidia-docker/wiki)

## Docker-composeでのGPU使用方法
複数のコンテナを立ち上げるdocker-composeでgpuを使う方法がわからなかったので調べた。

docker-composeでもgpuを使うには`runtime`で設定するとのこと
[How do I specify nvidia runtime from docker-compose.yml?
](https://stackoverflow.com/questions/47465696/how-do-i-specify-nvidia-runtime-from-docker-compose-yml)


そこで上記のようにdocker-compose.ymlを作成

では、実行

```
$ docker-compose up                    
　ERROR: The Compose file './docker-compose.yml' is invalid 　because:
　Unsupported config option for services.nvidia: 'runtime'
```

あれ、gpuが使えない


docker-composeにruntimeが追加されたのは1.19以降
[Added support for the runtime option in service definitions](https://github.com/docker/compose/releases?after=1.20.1)
とのことなので、`$ sudo apt install docker-compose`でインストールしたdocker-composeのversionを調べると

```
$ docker-compose -v
　　docker-compose version 1.17.1, build unknown
```
バージョンが2.3より古い！！！

```
$ sudo apt remove docker-compose 
```
で削除

公式の[docker compose releases](https://github.com/docker/compose/releases)からver1.24.1をダウンロードして実行権限を与える

```
$ curl -L https://github.com/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose
```

docker-compose version確認

```
$ docker-compose -v
  docker-compose version 1.24.1, build 4667896b
```

実行してみると


```
$ docker-compose up
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254458/8ce52784-daf4-925a-3bb7-40e80a2a6eb9.png)



---
参考
[nvidia-dockerでGPUコンテナの作成](https://qiita.com/uni-3/items/f5911aaaa538b33f370f)
php-master-changes 2019-08-24

この日はメモリリークの修正、クロージャでの $this のアンバインド非推奨化の緩和、arginfo の PHP スタブへ移行、ZPP エラー時の RETURN_FALSE 削除、一部警告のエラーへの昇格、str_pad() のエラー条件の修正があった！

# 2019-08-24
## nikic: Fix arginfo leak when using disabled_classes
- https://github.com/php/php-src/commit/8807889ac280503d5cd1cd05804a6f278a40300e
- [7.4~]
- arginfo まわりのメモリリークの修正

## nikic: Relax closure $this unbinding deprecation
- https://github.com/php/php-src/commit/d1157cbce1f324362d1fe05aff3fb53ef248ad74
- [7.4~]
- クロージャでの $this のアンバインド非推奨化の緩和
- コンパイル時にフラグ付けてクロージャ内で実際に $this が使われてる場合に警告出すようにしている

## cmb69: Add ext/iconv stubs
- https://github.com/php/php-src/commit/d420336115cd5c0bf5b0a5df2c7acc0de76853ae
- ext/iconv で、arginfo を PHP スタブへ移行

## cmb69: Don't explicitly set return value on ZPP failure in ext/iconv
- https://github.com/php/php-src/commit/bba7f38c4f8cbdbac391739b0fc905aaa8a09ce9
- ext/iconv で、ZPP エラー時（例外を投げるようになる）の RETURN_FALSE を削除

## Girgias: Promote warnings to errors in str_repeat()
- https://github.com/php/php-src/commit/1059e3dc39b65719c414ec0f31f65a77192034ab
- [str_repeat()](https://www.php.net/manual/ja/function.str-repeat.php) の警告を例外投げるエラーへ昇格

## Girgias: Promote warning to error in zend_forbid_dynamic_call()
- https://github.com/php/php-src/commit/675e975185b21b99dbc5ca47cf2fdd4cd79e68a1
- 動的呼び出しできない関数を動的呼び出ししようとした際の警告を例外投げるエラーへ昇格

## Girgias: Remove 'bogus' error condition in str_pad()
- https://github.com/php/php-src/commit/9d18f23c4cb06f25c25a018d2c3c7c956462534b
- [str_pad()](https://www.php.net/manual/ja/function.str-pad.php) で INT_MAX より大きい pad はエラーに、という謎コードがあったのを削除
【docker compose】上手くいかないときの解決手順

##Docker でうまく反映されない場合のおまじない
以下の手順でコマンドを実行します。

```powershell:すべてのコンテナを停止する
docker stop $(docker ps -q)
```

```powershell:すべてのコンテナを削除する
docker rm $(docker ps -q -a)
```

```powershell:すべてのイメージを削除する
docker rmi $(docker images -q)
```

```powershell:キャッシュ使わないでビルド
docker-compose build --no-cache
```
```powershell:backgroundで起動
docker-compose up -d
```

これでうまくいかないなら
設定等を見直しています。