OmniAICreator/Qiita-1.07M huggingface dataset:
配列の中の要素の種類数を得る

結論から

# コード
```swift
extension Array where Element: Equatable{
    var categoryCount: Int {
        get{
            var dic = [Element]()
            for item in self{
                if nil == dic.index(of: item){
                    dic.append(item)
                }
            }
            return dic.count
        }
    }
}
```

# その他
何も書くことないです。
ソースのどっかにこれコピペしたら使えるはずです。
push, popしか出来ないStack

まずは結論から

# コード
```swift
struct Stack<Element>{
    public private(set) var items : [Element]
    
    init() {
        items = [Element]()
    }
    
    init(_ value : [Element]) {
        items = [Element](value)
    }
    
    mutating func push(_ item: Element){
        items.append(item)
    }
    
    mutating func pop() -> Element?{
        return items.popLast()
    }
}
```

# 経緯
普通の配列にも`popLast`があるにはあるんですけど，他の方法でアイテムを編集できてしまったりするので，push, popしかできないものがほしいなぁと思ったので。
一応中身の個数とか知りたい場合もあるかと思って配列の中を見ることは出来ます。
bottle.py + waitressでPythonのみで動作可能なWebサーバ

タイトルを読んだ人は「そんなのPythonの標準ライブラリを使えばできるよ」かもしれません。それは仰る通りですが、同期処理かつシングルスレッド実装という欠点があるため大量の画像やリソースを読み込むようなユースケースによっては「もたつきすぎる」と感じることがあります。

もう少しちゃんとしたWebサーバを導入できれば良いのですが、特殊な開発環境、デモ向け環境では手軽にApacheやNginxやpipライブラリを導入することができなかったりします。

`bottle.py`と`waitress`により、ApacheやNginxやpipライブラリを別途インストールすることなく動作可能なそこそこレスポンスの良いWebサーバを実現できます。


# 概要

以下の`bottle.py`と`waitress`を同梱する形でWebサーバを配布します。

- `bottle.py` はPythonのシンプルなWebフレームワークです。Pythonファイル1個で構成されています。今回利用するWebサーバ実装である`waitress`にも対応します。
- `waitress` はPythonで実装されたマルチスレッドかつ非同期処理実装のWebサーバです。性能面ではC言語などで実装されたWebサーバには遠く及びませんが、Pythonの標準Webサーバと比較すればかなりレスポンス面で優れています。

上記のWebサーバには以下のメリットがあります。

- Python2.7/3.5が入っている環境であれば動作する。(対象バージョンはもっと広いかも)
- マルチプラットフォームで動作する。(Windows, Linux等)
- マルチスレッドかつ非同期処理の実装であるため、Pythonの標準ライブラリHTTPサーバよりも高速。

# 対象者

以下の項目に当てはまる人が対象です。

- Pythonに同梱されている標準Webサーバは遅すぎるため使いたくない。
- しかし色々な環境(異なるマシン、異なるOS)で動かすため、Apache、Nginx、pipのサードパーティライブラリ等はインストールしたくない。

> 補足:
> ちなみに「Pythonすら入れたくない」という場合は、Node.jsが組み込まれているElectronという選択肢もあります。Pythonだと配布する際に色々と頭を悩ましますが、JavaScript/Node.jsはこのあたりが大分楽なので羨ましいです。

# 手順

以下のディレクトリ構成をもつ資材を作成する手順を示します。

```
mywebapp/
    server.py  (自分で作るPythonスクリプト)
    libs/
        bottle.py
        waitress/
            ... (色々入るため省略)
```

以下のシェルコマンドを実行することにより、必要なPythonライブラリのダウンロードおよび解凍が行われます。

```bash
mkdir mywebapp
cd mywebapp
touch server.py
mkdir libs
cd libs
curl -OsL https://raw.githubusercontent.com/bottlepy/bottle/0.12.13/bottle.py
curl -sL https://github.com/Pylons/waitress/archive/v1.1.0.tar.gz | tar xz --strip=1 waitress-1.1.0/waitress
cd ..
```

`server.py` には以下のソースコードを記述します。

- sys, osモジュールを使用してlibs配下のPythonモジュールを参照できるようにPATH設定しています。
- bottle.pyのrun関数のserver引数には`server="waitress"`と指定してください。他の引数は自由です。

```py3
import sys
import os
# bottle.py, waitressのPATH設定
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'libs'))
from bottle import route, run, template

@route('/hello/<name>')
def greet(name):
    return template('<b>Hello {{name}}</b>!', name=name)

# bottle.py起動時にWebサーバとしてwaitressを指定
run(server="waitress", host='localhost', port=8080)
```

これで準備完了です。以下のコマンドでserver.pyを起動すると、bottle.py + waitress でWebサーバが稼働状態となります。あとはブラウザで `http://localhost:8080/hello/world` にアクセスすれば、Hello Worldページが表示されます。

```bash
python server.py
```

bottle.pyについてはQiitaに色々な記事があるので、そちらを参照してください。
MacOS上にVagrantで立ち上げたUbuntu上にDockerを入れてみる

## 環境
```
MacOS Sierra 10.12.6
```
ドットインストールの動画を参考に。
https://dotinstall.com/lessons/basic_docker/27701

## VagrantでUbuntuを立ち上げ

http://www.vagrantbox.es/
からイメージを取得。名前は`Official Ubuntu 14.04 daily Cloud Image amd64 (Development release, No Guest Additions)`。
対応するURLをコピーしてくる。

適当にプロジェクト用のディレクトリを作成し、Boxを追加。
Boxにはtrusty64という名前をつける。
（名前は多分なんでもいいけど、ubuntuのバージョン14がtrustyと呼ばれているらしい）

```
$ mkdir MyVagrant
$ cd MyVagrant
$ vagrant box add trusty64 https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box
```

Docker用のディレクトリを作成し、そこでvagrant立ち上げ。

```
$ mkdir Docker
$ cd Docker
$ vagrant init trusty64
```

Vagrantfileができるので、それを編集。

```
$ vim Vagrantfile
```


ipアドレスを変えたいんですって。
35行目あたり？の設定のところをコメントアウト外して、

```
config.vm.network "private_network", ip: "192.168.55.44"
```

とする。
（これって必ず必要なんだろうか。）

で、

```
$ vagrant up
```
として起動。

## Ubuntuの上にDockerを立ち上げる

どうやらDockerのインストール手順が、動画の内容とは変わっているらしい。（2018.01.27現在）

https://docs.docker.com/install/linux/docker-ce/ubuntu/#install-docker-ce
を参考にDocker ceなるものを入れていく。

リポジトリをセットアップするらしい。


```
$ sudo apt-get update
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
```

次に`DOCKER CE`をインストール

```
$ sudo apt-get update
$ sudo apt-get install docker-ce
```

プロダクションシステム上では、必ずしも最新のバージョン使わないほうがいいんじゃないって書いてあるけど、とりあえず最新っぽいやつのバージョン指定して入れておく。

```
$ apt-cache madison docker-ce
```
で使えるバージョンがリスト表示されるから、その中で適当なやつ指定する。

```
$ sudo apt-get install docker-ce=17.12.0~ce-0~ubuntu
```
テスト的なやつ

```
sudo docker run hello-world
```

僕は`sudo docker run hello-world`というメッセージとともに２０行くらいつらつらとメッセージが表示されました。
多分、インストール成功したということでしょう！
webpackの導入を最小単位で試してみる

## webpack is 何？
[webpack](https://webpack.js.org/)とはJavaScriptをまとめてくれるモジュールバンドラーです。なぜまとめる必要があるのか？それは、一度にウェブサーバーと通信できるファイル数は限られているため、ファイルサイズの小さいファイルを細切れで転送するより、大きいファイルを一度に転送した方が、効率が良いからです。

それだけなら、他のツールでも実現可能ですが、
webpackの場合は、標準仕様のES Modulesが使えたり、node_modulesのモジュールを結合できるとのこと。とすると他のツール（Gulp, Grunt...）はnode_moduleを結合してくれないという事なのか・・？

それだけでなく、CSSや画像のバンドルもできるとのことですが、CSSはイメージできるとして、画像のバンドルってなんだ？次回調べてみます。

それでは早速実践してみましょう。


## 手を動かす
本当にゼロの状態から始めます。
所要時間：5mins程度

### 1.まずは、ディレクトリを作って、初期化。

```
mkdir sample
cd sample
npm init -y
```
package.jsonが生成されます。


### 2.webpackをインストール
```
npm install -D webpack 
```
scriptのところに`"build": "webpack"`を追記しましょう。

```json
{
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "^3.10.0"
  }
}
```
`devDependencies`のところにwebpackが追加されています。

### 3.バンドルするJSを用意する。
ディレクトリ内にテキトーに`src`とかでディレクトリを切って、main.jsとsub.jsみたいな２つのファイルを用意しましょう。内容は下記のような感じ。

```javascript:main.js
// sub.js ファイルを読み込む。
import {hello} from './sub';
// sub.jsに定義されたhello関数を実行。
hello();

```
```javascript:sub.js
// export文を使ってhello関数を定義。
export function hello() {
  alert('helloメソッドが実行された。');
}
```

### 4. webpack.config.jsを作成

```javascript:webpack.config.js
module.exports = {
  // メインとなるJavaScriptファイル
  entry: './src/main.js',

  // ファイルの出力先設定
  output: {
    // ディレクトリ名
    path: `${__dirname}/`,
    // ファイル名
    filename: 'bundle.js'
  }
};
```

### 5. webpackによるbuild

```
npm run build
```
これで、main.jsとsub.jsが統合され、ひとつのbundle.jsというファイルができました。
HTMLで読み込んで、ブラウザでアラートが表示されるか確認してみましょう。

```html:index.html
<script src="bundle.js"></script>
```
![Screen Shot 2018-01-27 at 20.04.35.png](https://qiita-image-store.s3.amazonaws.com/0/209160/568fc859-b451-a50c-3c9c-ebf17bba09b0.png)

表示されました。
JavaScriptで、オブジェクトに値を紐付けたい

JavaScriptで、キーと値の対応を取るような構造を考えていたときに、少し悩むことがありました。

# 他言語と比較して

RubyやJavaでは、`Hash`のキーには文字列や数値だけでなく、任意のオブジェクトを入れることができます。そして、「オブジェクトとしての同一性」以外に「内容の同一性」を考える、別次元での等値判定が用意してあります。

一方で、JavaScriptには連想配列を実現する手段として、「`Object`」と「`Map`」があります。[詳しい記事](https://qiita.com/raccy/items/816a322fb330193e788b)があるので中身は省略すると、

* `Object`…キーは文字列しか使えない、`toString`や`__proto__`のように特殊な動作をするキーもある
* `Map`…オブジェクト型についてはオブジェクトの同一性判定しかない

という状況なので、（JavaScriptにそもそもオブジェクトが「値として同一」だということを判定する仕組み自体ないですが）「値として同一」なオブジェクトをキーに処理を行いたい、となると、なかなかうまく行きません。

# JSON化の罠

幸い、今回キーにしたいオブジェクトは、「`Object`」「文字列」「配列」「数値」「ブール値」「`null`」を組み合わせた、JSONにできるオブジェクトなので、「JSONをキーにすれば適当な方法で管理できるんじゃないか」とも、いったんは思いました。

ただ、RubyやPHPでは連想配列の順序が保証されるのに対して、JavaScriptもJSONも、キーの順序は**不定**となっています。つまり、「キーも値もすべて同じ」オブジェクトがあったとして、それをJSON化しても、JSONがどんな順序になるのか**制御する方法もない**わけで、単純な手法では同じJSONを生成することができません。

```js
// falseとなる可能性が高いけど、それも保証されない
console.log(JSON.stringify({foo: '1', bar: 2}) === JSON.stringify({bar: 2, foo: '1'}));
```

# 探せばあった

そこで行き詰まっていたところ、npmに[json.sortify](https://www.npmjs.com/package/json.sortify)というものがありました。名前のとおり、キーをソートしてJSONを生成するルーチンで、「A deterministic version of `JSON.stringify`」、つまり同じキーと値の組み合わせなら必ず同じJSON文字列を生成する、とありました。今回やりたいことにぴったりです。

…とおもったら、JavaScriptとしての規定がないからわざわざ入れようというはずなのに、「先に入れたキーが先に出力される」というJavaScriptエンジンの挙動に依存していて、「これはどうなんだ」という気分になってしまいました。
ニコ技深圳観察会用自己紹介文

# 0. お断り

BLOGは10年くらい前までやっていたのですが途中でやめてしまい、最近はQIITAに初心者向けハンズオン記事を書いています。昨年初めて深圳に行った時もこんな記事書きました。

[Cloud103]番外編：深圳のススメ
https://qiita.com/nagahisa/items/933f25dfcda3cdb695ee

QIITAがBLOGかと問われると「うーむ」って感じですが、ご容赦いただけばと:sweat:


# 1. 自己紹介

名前は永久健三（ながひさ　けんぞう）で、年齢は本日(2018/1/27)時点で57歳です。
永久という苗字は出身地(広島)では割と多いのですが、東京に出てきてからは２－３人しか見かけていません。以下によるとかなり珍しい苗字みたいです。

永久姓 全国分布
https://name.sijisuru.com/Area/map/%E6%B0%B8%E4%B9%85

# 2.何を仕事にしてるか

昨年度までは法人向けクラウドサービス(IaaS)の企画を行っていました。
企画っていうとカッコよさげですが、開発以外の何でも屋で、ＰＭ(Project Manager)職って感じです。IaaS提供側でもお客様のM2M/IoTニーズに答える必要があるので、いろいろエッジ系を調査しているうちにエッジデバイスに嵌ってしまっています。
まぁ、もともと立ち上げ初期の日本Androidの会でこんな発表するなど、ガジェット好きだったので:smile:

おじさんのぬるーい話(Keyboad)
https://www.slideshare.net/leopard.android/keyboad

今年度からは企画部門から技術部門に移り「品質管理部」という部署に移って、渋谷にある開発子会社に出向しています。渋谷の会社では、今までオンプレだったサービス基盤をPublic Cloudに移したり、開発品質上げるために障害管理を導入したりしています。

# 3.自分の時間で何を作ってるか

まだまともな形あるものを作るところまで行けてませんが、エッジ～クラウド連携をいろいろ勉強しています。
昨年は、「DragonBoard41oCで何か作ろう！」ってイベントに参加したのですが、ブレッドボード上で動作はするものの、形ある実用品にできないとう失態をやらかしました。

Dragonboardで買い物メモ
https://www.slideshare.net/leopard.android/20170722dragonboard


![20180127-01.PNG](https://qiita-image-store.s3.amazonaws.com/0/79389/2cae833a-45d0-f314-8aaa-d4fd0aa1b9f6.png)

# 4. 中国経験など

2012-2013年にちょうど１年間上海駐在していました。
ただ、仕事は英語で行う契約で、用意されていたアパートは外人用（ドイツ人が多っかった）、しかも一緒に行った日本採用の中国人エンジニアがずっと日本語で話してくるので中国語はさっぱりです。
帰国後にその中国人エンジニアが日本語を忘れないために僕を練習台に使っていたと白状しました:imp:

まあ、一人でご飯食べたり、タクシー乗ったりは~~できます~~できると思います。

# 5. その他

高須さんの本(メイカーズのエコシステム)や藤岡さんの本(ハードウェアのシリコンバレー深センに学ぶ)にはすごーく刺激を受けました。多謝！

最近うなったのはこの本です。

現代中国の父 鄧小平（上・下）
https://www.amazon.co.jp/dp/4532168848/
https://www.amazon.co.jp/dp/4532168856/

かなり読み応えのある本ですが、もう一度読みたいなと思っています。

とり急ぎ（後でもちっと綺麗にしておきます:sweat:)。
VMD-Lifting がやっていること

[GitHubのWiki](https://github.com/errno-mmd/VMD-Lifting/wiki/VMD%E2%80%90Lifting%E3%81%8C%E3%82%84%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E3%81%93%E3%81%A8)に移行しました。
intra-mart実践入門の作成記録 #008 プロジェクトマネジメント編目次

# プロジェクト途中で失敗が見えていることもある
　[前回](https://qiita.com/hiroaki-kushida/items/b44d3640b0dd76db28d1)は組織編の目次でしたが、今回はプロジェクトマネジメント編の目次を作成しました。完成時には一番初めの章に来るかと思います。

　結果が過程の中で確定してしまうケースは多々あります。プロジェクトであっても、「完了報告(結果)」を待たずして「進め方(過程)」を見ただけで「あぁ、このままでは失敗するなぁ」と感じる場面は多々あります。その多くは技術的問題ではなく、マネジメント的問題です。専任のプロジェクトマネージャーや組織長クラスの経験者が揃っているチームなら問題ないかもしれません[^1]。

　ともかくとして、自社開発するときのリソース状況から苦戦しやすいポイントと思われるので、プロジェクトマネジメントについてだけで一章を割きます。書きたいと思っている内容は次の節です。

# プロジェクトマネジメント編目次
<dl>
  <dt>プロジェクトの成功と失敗</dt>
  <dd>遂行上の成功</dd>
  <dd>影響上の成功</dd>
  <dt>ミッションの確認</dt>
  <dd>ゴール・目的・目標を共有する</dd>
  <dd>『我々』の範囲はどこまでか</dd>
  <dd>求められているものと目指すもの</dd>
  <dt>失敗要因を避ける</dt>
  <dd>ミッションを忘れたなら「手段が目的になる」</dd>
  <dd>計画を立てられないなら「戦線は無意味に拡大する」</dd>
  <dd>計画の見直しを行わないなら「大本営発表が負けるまで続く」</dd>
  <dd>交渉を後回しにするなら「選択肢は殲滅戦か無条件降伏になる」</dd>
  <dd>役員を味方にできないなら「空から槍が降ってくる」</dd>
</dl>

[^1]: ですが、そのレベルのメンバーがアサインされる規模のシステムなら、そもそもこの本のコンセプトから外れているはずです。
自作サーバーの設置とXenServerを導入してみる

# 1.はじめに
　自作サーバーに憧れてたのでとりあえず作ってみました。
　用途はFactorioっていうゲームの身内鯖とマイニング用ですがこれはまた別の投稿で。
　ちなみに、初投稿です。
# 1.1 使用したソフト
 - XenServer7.3
 - Rufus
  -インストール用のUSBメモリが必要 

# 2.材料
　まずは素材から
　【CPU】AMD CPU Ryzen 3 1300X
　【CPUクーラー】上記の付属品
　【メモリ】W4U2400CM-8GPC4-19200(DDR4-2400) 8GBx2枚
　【マザーボード】ASRock AB350 Pro4
　【SSD】前のPCから流用
　【HDD】同じく流用
　【電源】またまた流用
　【ケース】そんなものはありません。
　【グラフィックボード】GTX 960 (マイニングのため)
　ディスプレイなどは今使っているPCにつないでます。 
　今回、サーバーということなのですが、予算の関係上ケースはともかくHDDの冗長性も確保しないというあってはならない構成ですがご了承を。
# 3.実装
　サクッとパーツと組み上げてソフトのほうに行きましょう。

# 3.1. XenSeverの導入

- XenServerの配信サイト( https://xenserver.org/overview-xenserver-open-source-virtualization/download.html )にアクセスしてインストールメディア(iso)とXenCenterのインストーラーを手に入れる。
- Rufusを配信サイト( https://rufus.akeo.ie/?locale=ja_JP )よりダウンロードしてUSBに書き込む
 - この時、画面上部の「パーティション構成とターゲットシステムの種類」の欄を「MBR BIOS または UEFI-CSM コンピューター用のパーティション構成」に変えておく。
- 書き込みが終わったらXenServerをインストールするPCに刺す。
 - その際、USBを優先的に起動するようにBIOSの設定を変えておく。
- 起動したらさっそくインストール
 - この時、keymapで少し迷ってしまったが、jp106を選んでおけば良さそう。
 - あと、パスワードを入力するときは後で使うので適当にしない。
- あとは流れに沿ってやるだけ。
 - DHCPがどうのこうのの設定は所有するルーターがバッファロー製だったのでオート設定で通した。
- インストールが終わったら再起動して今度はホストPCの方にXenCenterをインストールする。
- XenCenterを起動してAdd New Serverをクリックして新しいサーバを追加する。
 - IPアドレスはXenServerをインストールしたPCの最初の画面に表示されているアドレスを入力するだけ。
 - UsernameはrootでPasswardはさっき入力したものをここで使う。
- 無事インストールできました。

# 4. 最後に
- これでサーバーは完成したので今後、最終目標のwindowsとfedoraを入れる
- 割りとすんなり行けたので書くことが少なくてどうしようかと。
- 今後編集して覚書みたいな投稿を修正していきます。

# 参考
https://vivibit.net/xenserver7-install/
https://orebibou.com/2014/05/xenserver-%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/
仮想通貨Menero(XMR)のCPUマイニング

　ServersMan@VPSのリソース制限が余りに厳しいので他所へ移行することになり、解約手続きをしたのですが、タイミングが悪く26日以降は翌月末までの契約となったので、せっかくなので仮想通貨Menero(XMR)をxmrigでCPUマイニングさせてみました。

### マイナーのビルド

　ビルドに必要なパッケージをインストールします。

```
sudo add-apt-repository ppa:jonathonf/gcc-7.1
sudo add-apt-repository ppa:acooks/libwebsockets6
sudo apt-get update
sudo apt-get install git build-essential cmake libuv1-dev libmicrohttpd-dev gcc-7 g++-7
```

　xmrigをビルドします。デフォルトでドネートレベルが5%あるので必要であれば*make*の前に*xmrig/src/donate.h*を修正して下さい。

```
git clone https://github.com/xmrig/xmrig.git 
cd xmrig
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 -DWITH_AEON=OFF -DWITH_HTTPD=OFF -DUV_LIBRARY=/usr/lib/x86_64-linux-gnu/libuv.a
make
sudo cp xmrig /usr/bin
```


### デーモン化

init.dスクリプトを書いて、リブート時に自動起動するように指定。

```
sudo cp /etc/init.d/skeleton /etc/init.d/minerd
sudo chmod +x /etc/init.d/minerd
sudo vi /etc/init.d/minerd
```

```text:/etc/init.d/minerd
：
DESC="miner daemon"
NAME=xmrig
DAEMON=/usr/bin/$NAME
DAEMON_ARGS="-a cryptonight -o {プールアドレス} -u {アカウント名} -p {パスワード} -t {スレッド数}"
：
```

※パラメータは各プールの仕様に合わせて下さい。

```
sudo update-rc.d minerd defaults
```

### リソース制限対策

4時間おきにリブートするように指定。

```
sudo crontab -e
```

```text:crontab
0 */4 * * * /sbin/shutdown -r now
```

### ハッシュレート

ServersMan@VPS Entryでは**10H/s**以下となります(GTX750Tiでも200H/s弱)。
CPUマイニングに特化した仮想通貨の方がマシだと思うので、そちらも追って別の記事で試してみたいと思います。

---
バーチャル夕張: http://153.126.198.223/ (新VPS、ドメインvyuubari.com移管中)
Bitcoin: 1PGrE58W6921iVNTMFPAQGBsiHTx7WmdY2
(a == 1 && a == 2 && a == 3)をちゃんと判定させる

#周回遅れぎみだけどやってみた

元ネタ: [Can (a ==1 && a== 2 && a==3) ever evaluate to true?](https://stackoverflow.com/questions/48270127/can-a-1-a-2-a-3-ever-evaluate-to-true)
独自クラスを作って==演算子を実装するのはいいんだけど、だいたい「常にtrue」を返すだったので、ちゃんと値を持っているか確認してその結果を返すやつを作ってみた。

#仕様

+ 複数の整数値を格納できるクラスを作成
+ ==演算子は「その比較値を格納していればtrueを返す」
+ 複数の値をセットしたり削除したりできるように+=で追加、-=で削除する機能も実装

#実装したクラス

```csharp
using System;
using System.Collections.Generic;
using System.Linq;

class MultiValueInt
{
	protected HashSet<int> values;

	//コンストラクタ
	public MultiValueInt() => values = new HashSet<int>();
	public MultiValueInt(int val) : this(new int[] { val }) { }
	public MultiValueInt(IEnumerable<int> vals) => values = new HashSet<int>(vals);

	//追加
	public static MultiValueInt operator +(MultiValueInt target, int val) { target.values.Add(val); return target; }
	public static MultiValueInt operator +(MultiValueInt target, IEnumerable<int> source) { source.Select(val => target.values.Add(val)); return target; }
	public static MultiValueInt operator +(MultiValueInt target, MultiValueInt source) { return target + source.values; }

	//削除
	public static MultiValueInt operator -(MultiValueInt target, int val) { target.values.Remove(val); return target; }
	public static MultiValueInt operator -(MultiValueInt target, IEnumerable<int> source) { source.Select(val => target.values.Remove(val)); return target; }
	public static MultiValueInt operator -(MultiValueInt target, MultiValueInt source) { return target - source.values; }

	//比較
	public static bool operator ==(MultiValueInt target, int val) => target.values.Contains(val);
	public static bool operator !=(MultiValueInt target, int val) => !target.values.Contains(val);

	//オーバーライドしないとなんか警告が出る
	public override bool Equals(object obj) { if (obj is MultiValueInt src) { return src.values.All(val => this.values.Contains(val)); } else return false; }
	public override int GetHashCode() => this.values.GetHashCode();
}
```

#テストコード

```csharp
static void Main()
{
	var a = new MultiValueInt(new int[] { 1, 2, 3 });
	Console.WriteLine($"(a==1 && a==2 && a==3) : {a == 1 && a == 2 && a == 3}");	//true
	Console.WriteLine($"(a==1 && a==2 && a!=3) : {a == 1 && a == 2 && a != 3}");	//false

	a -= 2;
	Console.WriteLine($"(a==1 && a==2 && a==3) : {a == 1 && a == 2 && a == 3}");	//false
	Console.WriteLine($"(a==1 && a!=2 && a==3) : {a == 1 && a != 2 && a == 3}");	//true
}
```

#HashSet&lt;T&gt;について

あまり使われてるのを見かけたことがないけど、「その値をすでに使っているかどうかを知りたいだけ」という場合などには使いやすい。(数が多いとList&lt;T&gt;などより高速)
実質的には「Dictionaryのvalueがなくてkeyだけのやつ」なんだけど、valueに入れるものがなくてkeyだけをセットしてるDictionaryがあったらHashSet&lt;T&gt;に置き換えると記述がすっきりする。
「すでにセットしている値を追加」や「セットされてない値を削除」をしようとした場合は何も変化せず例外も投げないのでコードがシンプルになる。
「valueのないDictionary」だから格納順序は保証されない。
TravisCIでデプロイする際、bowerでインストールされるファイル群から不要なものを削除する

bowerを使うと、パッケージによっては本番環境には不要なものもインストールされることがある（ReadMeなど）。
使わないものをデプロイするのは無駄なので、それらを除外するようTravisCIの設定を変更した。

例）jqueryのdistフォルダのみを残し、不要なファイル／フォルダを削除する
.travis.ymlに`before_deploy`ブロックとして追記（languageはbash）。
<pre>before_script:
  - npm install -g bower
  - bower install
before_deploy:
  - find wwwroot/lib/jquery -maxdepth 1 -type f | xargs rm -rf
  - rm -rf wwwroot/lib/jquery/src
  - rm -rf wwwroot/lib/jquery/external
</pre>

もっとシンプルな書き方がありそう。
metabaseでGoogleAnalyticsに接続するときエラーが出る

##metabaseでGoogleAnalyticsに接続するときエラーが出る

理由はmetabaseの[バグ？](http://discourse.metabase.com/t/cannot-get-auth-code-for-google-analytics-connection/1680)っぽい

何かしらのアクション（Click hereとか）を行うと `Client ID:` `Client Secret:` `Auth Code:` の最後や最初に半角スペースがAddされてしまう。
取り除いて再度`Save`をクリックしましょう。

###GoogleAnalyticsのClient IDについての注意

<img width="851" alt="スクリーンショット 2018-01-27 18.23.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/164563/a9210b62-a33b-5e1f-925a-58ce025631ab.png">

`Click here`の後の画面では、`その他`を選ぶこと。

<img width="555" alt="スクリーンショット 2018-01-27 18.23.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/164563/149118bd-29dc-2c0a-80f9-2f6aa4e53539.png">
ropsten上でeth送る、のメモ

自分向けのメモとして書いとく。

もうデプロイしてる状態で、consoleに接続する。

```
ROPSTEN_MNEMONIC='OOOOOOOO' INFURA_ACCESS_TOKEN='OOOOOOO' truffle console --network ropsten
```
接続できたら、
```
contract = MyToken.at(MyToken.address)
contract.transfer('_送り先のアドレス入れる_', 1e18)
```
で、logsにちゃんと意図した送り先とか入ってたらOK
cmakeを使って、clang-tidyやclang-formatを行う

C/C++でコードを書く場合、`clang-tidy`や`clang-format`はとても便利です。
CMakeで、任意のターゲット[^1]に対して、`clang-tidy`や`clang-format`を行えるようにしました。

[^1]: グローバルに設定したら、ExternalProject(googletest)でえらいことになってしまった

```cmake:FormatFilesWithClangFormat.cmake
option(FORMAT_FILES_WITH_CLANG_FORMAT_BEFORE_EACH_BUILD
  "If the command clang-format is avilable, format source files before each build.\
Turn this off if the build time is too slow."
  ON)
find_program(CLANG_FORMAT_EXE clang-format)

function(clang_format target)
  if(CLANG_FORMAT_EXE)
    message(STATUS "Enable Clang-Format ${target}")
    get_target_property(MY_SOURCES ${target} SOURCES)
    add_custom_target(
      "${target}_format-with-clang-format"
      COMMAND "${CLANG_FORMAT_EXE}" -i -style=file ${MY_SOURCES}
      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
      )
    if(FORMAT_FILES_WITH_CLANG_FORMAT_BEFORE_EACH_BUILD)
      add_dependencies(${target} "${target}_format-with-clang-format")
    endif()
  endif()
endfunction()
```

```cmake:DoClangTidy.cmake
cmake_minimum_required(VERSION 3.6)
option(CLANG_TIDY_ENABLE
  "If the command clang-tidy is avilable, tidy source files.\
Turn this off if the build time is too slow."
  ON)
find_program(CLANG_TIDY_EXE clang-tidy)

function(clang_tidy target)
  if(CLANG_TIDY_EXE)
    if(CLANG_TIDY_ENABLE)
      message(STATUS "Enable Clang-Tidy ${target}")
      set_target_properties(${target} PROPERTIES
        C_CLANG_TIDY "${CLANG_TIDY_EXE};-fix;-fix-errors"
        CXX_CLANG_TIDY "${CLANG_TIDY_EXE};-fix;-fix-errors")
      endif()
  endif()
endfunction()
```

```cmake:使い方
include(DoClangTidy)
include(FormatFilesWithClangFormat)

set(target nice_app)
add_executable(${target}
  main.cpp
)
clang_format(${target})
clang_tidy(${target})
```

## 解説
`FormatFilesWithClangFormat.cmake`/`DoClangTidy.cmake`を`include`します。
すると、関数`clang_tidy(target)`/`clang_format(target)`が定義されます。これを呼ぶとターゲットのビルド時に`clang-tidy`/`clang-format`が行われるようになります。
また、有効/無効化やコマンドパスを設定するオプションも設定されます。`ccmake`等で編集できます。

チェック内容やインデント設定等は、上記cmakeファイルを（コマンド引数に足す）のではなく、`.clang-tidy`/`.clang-format`ファイルで設定するのがおすすめです。

## 参考

- [冬休み到来! clang-tidy で安心安全な C/C++ コーディングを極めよう! - Qiita](/syoyo/items/0e75410c44ed73d4bdd7)
- [CMakeでビルドしているコードにclang-tidyを実行する - Qiita](/yoyomion/items/8ff1f5a63b4b4f757732)
- [C++コードのデトックス - Qiita](https://qiita.com/MitsutakaTakeda/items/6b9966f890cc9b944d75)
metabaseのデータを永続化 docker-compose版

## metabaseのデータを永続化 docker-compose版
metabaseの環境構築、インストールをDockerで行ったが、データを永続できなかったのでデータを永続化した。
他のコンテナも利用したいのでdocker-composeを利用する。

host側に`/metabase` を作っておきましょう。
**注意：権限が誤っているとmetabaseコンテナが落ちますので注意が必要です**

```dockerfile:metabase/Dockerfile
FROM metabase/metabase

MAINTAINER xxxxx
```

```dockerfile:docker-compose.yml
### Metabase Container #########################################
    metabase:
        build: ./metabase
        volumes:
            - /metabase:/metabase.db:cached
        ports:
            - "80:3000"
```

`volumes:` のところがポイントになります。

また、`ports:` も `"80:3000"` とすることで、3000→80とできるので、AWSでALBの裏に置きやすいですね。
素数を判定

Javaで入力された数が素数かを判定するプログラムです。
素数でない数字の場合は入力値以下で最大の素数を表示します。

```Java:Main.java
import java.util.Scanner;
public class Main{
	//表示される素数
	static int primeNum = 0;
	//入力値が素数化を判定するフラグ
	static boolean isPrime = true;
	
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		int num;
		//2未満の数や整数以外の入力の際はやり直し
		do {
			try {
				num = Integer.parseInt(sc.next());
				if(num < 2) {
					System.out.println("2以上の整数を入力してください。");
				}
			}catch(NumberFormatException e) {
				System.out.println("半角整数で入力してください。");
				num = 0;
			}
		}while(num < 2);
		//素数を探す
		searchPrime(num);
		//表示するメッセージ
		String msg = String.format("%dは素数です。", num);
		if(!isPrime) {//入力値が素数ではなかった場合、メッセージを変更
			msg = String.format("%dは素数ではありませんでした。近い素数は%dです。"
				,num,primeNum);
		}
		System.out.println(msg);//表示
		sc.close();
	}

	public static void searchPrime(int num){
		if(checkPrime(num)){//素数であったなら引数をprimeNumに代入
			primeNum = num;
			return ;
		}//素数でなかったなら一つ小さい数を調べる＆素数ではなかったフラグ
		isPrime = false;
		searchPrime(num - 1);
	}

	public static boolean checkPrime(int num){
		if(num < 2){//2以下ならば素数ではない
			return false;
		}
		if(num == 2){//2ならば素数
			return true;
		}
		if(num % 2 == 0){//偶数ならば素数ではない
			return false;
		}
		//3以上、numの平方根以下の数で割り切れるか調べる
		for(int i = 3; i <= Math.sqrt(num); i ++){
			if(num % i == 0){//割り切れる場合は素数ではない
				return false;
			}
		}
		//割り切れなかった場合素数
		return true;
	}
}

```
OpenVPNにてNATの設定をしても、VPN経由でアクセス出来ないとき

以前下記記事で、OpenVPNを利用してVPN経由でアクセスするような処理を記載した。

[OpenVPNをAmazonLinuxにインストールして、VPN経由で外部ネットワークにアクセスする](https://qiita.com/megadreams14/items/0d5201245ec33ae463f4)


あれから半年近くたち、新たにVPN環境を構築する必要があったのだが、その際にVPN経由で特定のサイトにアクセスしようとすると、NATの設定がうまく効いていないのか、サイトに接続できずにハマってしまったので、その時の対処メモ


# 環境

- Amazon Linux

```bash
$ cat /etc/system-release
Amazon Linux AMI release 2017.09
```

- OpenVPN

```bash
$ openvpn --version
OpenVPN 2.4.4 x86_64-redhat-linux-gnu [Fedora EPEL patched] [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Nov  1 2017
library versions: OpenSSL 1.0.2k-fips  26 Jan 2017, LZO 2.08
```

- iptable

```bash
$ iptables --version
iptables v1.4.18
```

## OpenVPNの設定

特定のサイトに対してのみVPN経由でアクセスするといったことを実現したかったので下記のような設定をしてみた。

```/etc/openvpn/server.conf
##################
## 一部抜粋
##################


# VPNで接続してきたクライアントに割り振るIPアドレスを定義
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt

# VPN経由でアクセスさせたいIPアドレスを記載する
push "route xxx.xxx.xxx.xxx 255.255.255.0"

# DNSの設定は、一旦外部DNSの設定をしておく
push "dhcp-option DNS 8.8.8.8"

# 全ての通信をこのVPNサーバ経由にする設定はOFFとする
# push "redirect-gateway def1"
```

## iptablesの設定

10.8.0.0/24のネットワークからのアクセスをeth0のネットワークインタフェースを利用してインターネットに出ていく設定。

```bash
$ iptables -t nat -A POSTROUTING -o eth0 -s 10.8.0.0/24 -j MASQUERADE
$ service iptables save
```

念のため設定を確認

```bash
$ iptables -L -n -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  10.8.0.0/24          0.0.0.0/0  
```

これらの設定だけでよかったと思っていたが、VPNに接続して、
上記で指定した「xxx.xxx.xxx.xxx」にアクセスしても通信中のまま何も起きず...


# 解決方法

VPNには接続できており、OpenVPNの設定で指定したサイトに対してのみ接続できない状況だったので、NAT周りが怪しいとは思って調査しました。

そして、本当にたまたま見ていた「[iptablesを利用してNATサーバを構築](http://techblog.raccoon.ne.jp/archives/47152095.html)」の記事にて、
パケットを転送するためには、「/etc/sysctl.conf」の「net.ipv4.ip_forward」をONにする必要があるとの記載が...なんとそうなのか...

```/etc/sysctl.conf
# 0 だとIPv4でパケットの転送がされない
# net.ipv4.ip_forward=0
net.ipv4.ip_forward=1
```

念のためiptablesとopenvpnを再起動することで接続できるようになりました。


んーこの設定見つけるまで1日近く使ってしまった...
もっとインフラ詳しくならないとなー><


# 参考

- [iptablesを利用してNATサーバを構築](http://techblog.raccoon.ne.jp/archives/47152095.html)
スクロール時にふわっと現れる画像　（jQuery無しで）

何番煎じかも分からないが、スクロールした時にふわっと現れる画像や文字をjQuery無しで実装した。

```css
.fadein {
  opacity: 0;
}
.fadein.is-active {
  opacity: 1;
  transition: all ease 0.65s;
}
```

```js
// 表示する閾値。適当に調整する。
const screenOffset = window.innerHeight / 2 

const elements = document.getElementsByClassName('fadein')
for (let element of elements) {
  window.addEventListener('scroll', () => {
    if (window.scrollY + screenOffset > element.offsetTop) {
      element.classList.add('is-active')
    }
  })
}
```

```html
  <p style="height: 100vh">Prints out this usage information.</p>
  <img class="fadein" src="https://www.google.co.jp/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png">
```

Reactでやるなら、`componentDidMount` に書けば良い。

こちらを参考にさせて頂きました。

http://brian.hatenablog.jp/entry/floating-fade-in
動画ファイルのスクリーンショットを横に並べた画像をいい感じに生成する

生きていると『動画ファイルの0.1秒ごとのスクリーンショットを10枚横に並べた画像を動画ファイルの秒数毎に作る』必要が出ることがごく稀にあります。しかもその画像ファイルはできる限りクオリティを下げずに容量を小さくしたいということがあります。

そんな時の方法を紹介します。

## 動画ファイルのスクリーンショットをいい感じに取る

ffmpegを使います。

```bash
TARGET=$1
TMPDIR=`mktemp -d`
# -ssが開始秒数 -tが取得秒数 -rが秒あたりのコマ数
ffmpeg -loglevel panic -ss 0 -i ${TARGET} -vsync 2 -r 10 -an -f image2 "${TMPDIR}/%03d.png"
```

これでffmpegを使って動画ファイルのスクリーンショットがいい感じに取得できます。ここでjpegではなくpngで出力しているのは画像の劣化を避けるためです。

## 画像をいい感じに結合していい感じに圧縮する

おなじみのImageMagickと[mozilla/mozjpeg](https://github.com/mozilla/mozjpeg)を使います。動画ファイルの秒数は30秒だとします。

```bash
# ファイル名からディレクトリを作る
# cf: http://www.kishiro.com/FreeBSD/get_filename_in_shellscript.html
filename=${TARGET##*/}
TARGET_DIR=${filename%.*}
if [ -e ${TARGET_DIR} ]; then
  echo "${TARGET_DIR}ディレクトリが存在しています" 1>&2
  exit 1
fi
mkdir ${TARGET_DIR}

for i in {0..29}; do
  # ffmpegが01始まりでファイルを作るのでやむを得ずファイル名を全部書き出している
  # サンプリングやクオリティをいじって調整する
  convert -resize 6400x360 +append $(printf "${TMPDIR}/%02d1.png" ${i}) $(printf "${TMPDIR}/%02d2.png" ${i}) $(printf "${TMPDIR}/%02d3.png" ${i}) $(printf "${TMPDIR}/%02d4.png" ${i}) $(printf "${TMPDIR}/%02d5.png" ${i}) $(printf "${TMPDIR}/%02d6.png" ${i}) $(printf "${TMPDIR}/%02d7.png" ${i}) $(printf "${TMPDIR}/%02d8.png" ${i}) $(printf "${TMPDIR}/%02d9.png" ${i}) $(printf "${TMPDIR}/%02d0.png" $((i+1)))  pnm:- | cjpeg -sample 2x2,1x1,1x1 -progressive -optimize -quality 55 > $(printf "${TARGET_DIR}/%02d.jpg" ${i})
  # jpegtran
  jpegtran -copy none -optimize -outfile $(printf "${TARGET_DIR}/%02d.jpg" ${i}) $(printf "${TARGET_DIR}/%02d.jpg" ${i})
done
```

サンプリングについては以下のものが指定できます。詳しくは以下のURLを参考にしてください。

```
-sample 1x1,1x1,1x1
-sample 2x1,1x1,1x1
-sample 2x2,1x1,1x1
-sample 4x2,1x1,1x1
-sample 4x1,1x1,1x1
```

[ImageMagick で JPEG の形式を変換 - awm-Tech](http://blog.awm.jp/2016/01/26/jpeg/#%E3%82%AF%E3%83%AD%E3%83%9E%E3%82%B5%E3%83%96%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AA%E3%83%B3%E3%82%B0)

`jpegtran`を使うとjpegファイルのメタデータを削除してくれるので、不要なデータを削除することができます。画質は劣化しません。

皆様にそんな機会があるのかはよく分かりませんが、もしそういう機会があればぜひお使いください。
Raspberrypi3でlirc設定して赤外線リモコン受信するまで

記事を見ると色々書いてあるが，今時点(2018/01/27)では以下の手順でうまく動作した．
全てラズパイ上，もしくはsshでラズパイに接続して作業を行う．
`sudo su`とかで`root`になっておくと手っ取り早い．
### lircnの入手
`sudo apt-get install lirc`

### 設定
1. /boot/config.txtの編集  
24番pinをin，25番pinをoutに設定する例：下記を追記  
```
dtoverlay=lirc-rpi:gpio_out_pin=24,gpio_in_pin=25,gpio_in_pull=up
```
1. /etc/lirc/hardware.confの編集　　
![スクリーンショット 2018-01-27 16.34.27.png](https://qiita-image-store.s3.amazonaws.com/0/138229/bd6dec42-4e2d-8049-f88e-1f9dc11db8e3.png)

1. /etc/lirc/lircd.confの編集
冒頭の`#UNCONFIGURED`を消す
1. 再起動
```sudo reboot```

※ `/etc/init.d/lirc restart`などのコマンドでlircの再起動ではうまくいかず，ラズパイ自体の再起動が必要だった．
### 確認方法
* dmesg | grep lirc
![スクリーンショット 2018-01-27 16.35.58.png](https://qiita-image-store.s3.amazonaws.com/0/138229/16be2d7c-673c-23c3-9279-7aaee7ef0ab8.png)

* lsmod | grep lirc
![スクリーンショット 2018-01-27 16.36.27.png](https://qiita-image-store.s3.amazonaws.com/0/138229/c19a82a5-3cad-2039-fcfd-e2412dea5b01.png)

上記のようになっていれば設定は終了

### 赤外線の受信
* 赤外線リモコン受信モジュール：PL-IRM0101-3([データシート](http://akizukidenshi.com/download/ds/paralight/DS-27-01-0001%20PL-IRM0101-3%20B1.pdf))
PL-IRM1261-C438([データシート](http://akizukidenshi.com/download/PL-IRM1261-C438.pdf))も使ってみたがリモコンを向けてもいないのに信号が止まらなくてイマイチだった．
(繋ぎ方はシート見て頑張って)

* 受信　　
    * lircデーモンの停止  
    `/etc/init.d/lirc stop`
    * `mode2 -d /dev/lirc0`で待ち受けが始まる　　
     
    ![スクリーンショット 2018-01-27 17.22.21.png](https://qiita-image-store.s3.amazonaws.com/0/138229/08a9fa5a-5747-3681-719e-b03c538b946e.png)  
受信モジュールに向けてリモコンのボタン押してみてこんなのが出てこれば受信している．

### 参考
* [RaspberryPi3でlircを使ってリモコン化する時の注意事項まとめ](https://qiita.com/ponkio-o/items/4e7f8dd6e05378ca9ceb)
* [Amazon Echo で TVリモコン操作への道 (RPizero & AWSIoT & Lambda & AlexaSkill) 前編](https://qiita.com/toguma/items/57d6faed119c41bd4332#_reference-791787b387e92abac21c)
* [Slack経由で家の外からエアコンをon, offできる装置を、Raspberry Piで作ってみた。（しかも御坂美琴ちゃんが応答してくれる）](https://qiita.com/KAKY/items/55e6c54fa2073cdc0bbe)
* [RaspberryPi3とhomekitとwebIOPiで家電操作する](https://qiita.com/caad1229/items/eac59fc5615ff5701e86)
* [Raspberry Pi のGPIO経由で入力信号を連続的に取得](https://hack-le.com/44771052-2/)
* [https://qiita.com/ww24/items/32d2a78c20e6dcc2e68c](https://qiita.com/drafts/adffa56be113be79f3b4/edit)
Berkeley DB 6.2インストール手順


Berkeley DBのインストールメモ。
MacのHigh Sierra(10.13.2)にインストール。
※homebrewでインストールしたほうが早いです・・・

#1.Berkeley DBのダウンロード
[Oracleのダウンロードページ](http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html)からダウンロードしてくる。
※この際、私は「Berkeley DB 6.2.32.tar.gz」を取得しました。

#2.インストール
適当なフォルダに解凍した後、インストールする。

```
cd ./db-6.2.32/build_unix
../dist/configure --prefix=/usr/local/
make
sudo make install
```

#参考
[Berkeley DB 4.8 インストール手順](https://qiita.com/murabiton/items/0ac1731ead1a3883babc)
xampp 1.8.0設定 備忘録

# xampp設定
- ver 1.8.0, 1.6.6a
    - apache 2.4.2
    - mysql 5.5.25a
    - php5 5.4.4
    - control panel v3.0.12

- インストール時で日本語の文字化けはしなかった。
- それ以降のxamppのバージョンは日本語が文字化けする。対策方法をネットで検索して実行してもうまく日本語は表示されない。

## mysqlに日本語の取扱を設定する
[client]に以下を追加

```xamppp\mysql\bin\my.ini(conf)
default-character-set = utf8
skip-character-set-client-handshake
```
はじめてのCircleCI2.0

CircleCI2.0をこれからはじめて使おうという方向けのチュートリアルです。

この記事では、とにかく簡単にCircleCIを動かしてみます。

# 事前準備
## CircleCIに登録

まだ登録してない人はサインアップしてください。

今回はGitHubと連携した前提で進めるので、GitHubアカウントでサインアップするのがおすすめです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83325/5d761a0a-a414-e3e6-fcd4-78bb3f805e5d.png)

# GitHubリポジトリを作る

GitHubで`circleci-hands-on`リポジトリを作りました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83325/07bbc650-3951-1042-0914-3241c92715d9.png)

# CircleCIでプロジェクトを追加する

「PROJECTS」から「Add Project」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83325/4b5e2fde-91c1-25e3-a188-fb168d1e0e97.png)

GitHubのリポジトリがリストされるので、その中から、紐づけたいリポジトリの「Setup project」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83325/172ab227-724f-7787-52e7-fb4a9eba9cd7.png)

# プロジェクトをセットアップする

「Operating System」や「Platform」をはデフォルトのままで。

「Language」を選択するとそれに合ったサンプルのconfig.ymlが最下部に表示されます。

今回は「Other」にしておきます。

# 設定ファイルの作成

さて、ソースコードの方に戻ります。

先程作成した、`circleci-hands-on`リポジトリに`.circleci/config.yml`を追加してpushします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83325/9d33b454-95f9-2007-fdeb-343430d1c9ff.png)

「Copy to clipboard」ボタンを押すと以下のサンプルがコピーできます。

```yaml:.circleci/config.yml
version: 2
jobs:
  build:
    docker:
      - image: debian:stretch
    steps:
      - checkout
      - run:
          name: Greeting
          command: echo Hello, world.
      - run:
          name: Print the Current Time
          command: date
```

# ビルドしてみる

pushしたら「Start building」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83325/e5df3c55-20b1-1bcf-5858-631b18966904.png)

成功しました！

それぞれのステップでやっていることを見ていきます。

## Spin up Environment

dockerのimageをpullしてきて、環境変数をセットしています。環境変数はCircleCIがデフォルトでセットするものと自分でセットしたものがセットされます。

## Checkout code
`steps`の`checkout`に該当するステップです。
GitHubから`sawadashota/circleci-hands-on`リポジトリをcloneしてきています。

## Greeting

以下に該当する処理です。

```yaml:.circleci/config.yml
      - run:
          name: Greeting
          command: echo Hello, world.
```

`echo Hello, world.`が実行されたことと、`Hello, world.`が標準出力されたことがわかります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83325/c36c1878-13b6-057c-e505-5405622e69b0.png)

## Print the Current Time

上記、`Greeting`と同じように、コマンドと標準出力が表示されています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83325/725f473e-71bc-0d6e-4ecf-2edecc4c16b5.png)


# まとめ

手始めにCircleCIのサンプル通りに動かしてみました。

[次の記事](https://qiita.com/sawadashota/items/d1382b1e1b9a5595ab66)ではアプリケーションをビルドしてみたいと思います。
Git subtree で push できないときの対処法

このメモでは、git の subtree で push しようとしたら

    error: failed to push some refs to (リモートの名前)
    hint: Updates were rejected because the tip of your current branch is behind
    hint: its remote counterpart. Integrate the remote changes (e.g.
    hint: 'git pull ...') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.

のエラーが出て、pull してから push しても同じエラーが出て困ったときに使えた方法を紹介します。

## 動作環境

もしかしたら環境の違いで結果が変わるかもしれませんので、一応環境も載せておきます。

- OS: Windows 10 上の Virtual box の ubuntu 16.04 LTS
- git のバージョン: 2.7.4

## 症状

普通に

    git subtree push --prefix=(ディレクトリ) (リモート) (ブランチ)

で push すると

    error: failed to push some refs to (リモートの名前)
    hint: Updates were rejected because the tip of your current branch is behind
    hint: its remote counterpart. Integrate the remote changes (e.g.
    hint: 'git pull ...') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.

が表示され、素直に

    git subtree pull --prefix=(ディレクトリ) (リモート) (ブランチ)

しても

    From (リモート)
     * branch            (ブランチ)     -> FETCH_HEAD
    Already up-to-date.

と表示され、そのあとまた push しても同じエラーメッセージが出て push できない。

## 解決法

https://stackoverflow.com/questions/13756055/git-subtree-subtree-up-to-date-but-cant-push
https://stackoverflow.com/questions/33172857/how-do-i-force-a-subtree-push-to-overwrite-remote-changes
の情報を基に

    git push (リモート) `git subtree split --prefix=(ディレクトリ) --onto=(リモート)/(ブランチ)`:(ブランチ)

としてみたら push してくれました。
なお、このコマンドでもダメな場合、自己責任でこのコマンドの最後に`--force`を付ければ無理やり push することもできます。

## あとがき

subtree を使い始めてから数日に一回はこの解決法に助けてもらっているのですが、どうにかならないものでしょうか…。
HTML CSS メモ

HTML・CSSについて知識０から学んでます。
学んだことをまとめていきます。

知識がアップデートされたら、その都度更新していきます。

「基本設定・コンテンツ設定の書き方」
　●基本設定とコンテンツの設定はコードを分けて記載する。
　●理由はブラウザのウインドウ幅を変えても常にコンテンツ部分が中央に配置されるようにするため
　
　　コードはこんな感じ・・・
　　ーーーーーーーーーーーーーーーーーーーーーーーーー

```html
<div id="header">基本設定</div>
<div id="headerArea">コンテンツ設定</div>
```
　　ーーーーーーーーーーーーーーーーーーーーーーーーー

「margin」
●widthで幅をそもそもの幅を指定しないと、反映されない
Raspberry Pi 3 Model B + Raspbian セットアップメモ(2018/1)

# この記事は？
2018/1下旬にラズパイを買って最初にやっておいたことのメモ

# 前提条件(環境)と準備したもの
- Raspberry Pi 3 Model B
- Raspbien 9.1(Strech)
- Windows10(母艦)
- 有線LAN

# 自分がやりたいこと
- すべての操作は母艦からSSH接続をして行いたい

# Step.1 WindowsPC上でRaspbianをSDカードにセットアップする
以下のページから最新版を取得・セットアップする
Download Raspbian for Raspberry Pi
https://www.raspberrypi.org/downloads/raspbian/

セットアップ後、エクスプローラでSDカードを探すとBootという名前のドライブがある。
ドライブ直下に「ssh」というからファイルを作成する。
このファイルを作成しないと、SSH接続できない。

# Step.2 母艦からSSH接続
セットアップしたSDカードをラズパイに挿して電源投入。
一時的に母艦からキーボード・マウス・ディスプレイを拝借し、接続する。

Raspbianのデスクトップが表示されることを確認したら、ネットワーク接続しIPアドレスを確認する。

```
$ ifconfig
(以下略)
```
IPアドレスの確認ができたら、キーボード・マウス・ディスプレイを母艦に戻し、SSHクライアントから接続する。
> 初期ID : pi
> 初期PASS : raspberry

# Step.3 各種初期設定
## passwordの変更

```
$ passwd
```

※あとで鍵認証に切り替えるかもしれないけど、とりあえず初期パスワードから変更しておく

## いろいろ最新化する

```
$ sudo apt-get update && sudo apt-get upgrade
```

デスクトップ関連の更新に時間がかかるかもしれないけど、気長に

## タイムゾーン変更・時刻設定・NTP設定

時刻を確認。時計が狂っていたら調整する。

```
$ date
Sat 27 Jan 07:02:52 UTC 2018
$ sudo timedatectl set-timezone Asia/Tokyo
$ date
Sat 27 Jan 16:03:06 JST 2018
$ sudo date -s "2018/01/27 11:22:33"
```

```
$ sudo apt-get -y install ntp
$ sudo cp -a /etc/ntp.conf{,org}
$ sudo vi /etc/ntp.conf
(サーバを変更する)

$ diff /etc/ntp.conf{,.org}
20,24c20,24
< #pool 0.debian.pool.ntp.org iburst
< #pool 1.debian.pool.ntp.org iburst
< #pool 2.debian.pool.ntp.org iburst
< #pool 3.debian.pool.ntp.org iburst
< pool ntp.nict.jp iburst
---
> pool 0.debian.pool.ntp.org iburst
> pool 1.debian.pool.ntp.org iburst
> pool 2.debian.pool.ntp.org iburst
> pool 3.debian.pool.ntp.org iburst
$ sudo systemctl restart ntp.service
$ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 ntp.nict.jp     .POOL.          16 p    -   64    0    0.000    0.000   0.001
+ntp-a2.nict.go. .NICT.           1 u    3   64    1   32.717   -5.815   3.567
+ntp-b2.nict.go. .NICT.           1 u    5   64    1   29.213   -1.731   2.830
-ntp-b3.nict.go. .NICT.           1 u    2   64    1   21.659    2.012   9.937
*ntp-a3.nict.go. .NICT.           1 u    3   64    1   31.226   -4.710   3.584
```

# 無線LANの設定
[Raspberry Pi 3 Model B + Raspbian ネットワーク設定(2018/1) - Qiita](https://qiita.com/nyoki/items/115aad9ca6b343afb266)
オイラー法で解く連立微分方程式

# なぜ連立微分方程式を学ぶのか
２階微分方程式は運動方程式・２重振り子などいろんな場面で使うものです。オイラー法で２階以上の微分方程式を解くために連立微分方程式が必要になります。また、この考え方はルンゲクッタでも使います。

# 方法
n階微分方程式はn次１階連立微分方程式に直すことができます。例えば、$ \frac{d^2y}{dx^2} = -x $という方程式を解きたい場合、

```math
\begin{eqnarray}
  \left\{
    \begin{array}{l}
      \frac{dy}{dx} = v \\
      \frac{dv}{dx} = -x
    \end{array}
   \right.
\end{eqnarray}
```

という風に直せます。連立微分方程式に直したら、今度はオイラー法の出番です。ここではとりあえず、初期値として$ x_0 = 0, v_0 = 0, y_0 = 1 $とします。これを解いたら$ y = sin(x) $と同じグラフになるはずです。

まず、$ v_1 $の値を求めます。$ \frac{dv}{dx} = -x $という式を使えばいいので、$ v_1 = v_0 + ( - x_0) \Delta x = 0 $になります。
つぎに$ y_1 $の値を求めます。$ \frac{dy}{dx} = v $という式を使えばいいので、$ y_1 = y_0 + v_0 \Delta x = 0 $になります。
$ x_1 = x_0 + \Delta x $は説明いりませんよね。

同じように$ y_2, v_2, x_2 $を求めて、次に$ y_3, v_3, x_3 $を求めて......という操作を繰り返していくだけです。
Elixirのiexでエラーの色を変える

以下をiexで実行するとエラーやスタックトレースの表示色を変えることができます。

```elixir
IEx.configure(
  colors: 
      [eval_error: [IO.ANSI.color(5,1,1)], 
       stack_info: [IO.ANSI.color(1,2,1)] ]
)
```

`~/.iex.exs`に上記をそのまま書けば、iex起動時にデフォルト色が変更できます。


その他の設定については[ドキュメント](https://hexdocs.pm/iex/IEx.html#configure/1)をご覧ください。
ListViewで削除確認ダイアログを表示する方法

###やりたかったこと
ListViewのitemを長押し
→確認ダイアログを表示
→「OK」のときだけitemを削除する

###解決法
- `onItemLongClick`の中でダイアログを作る

```java
// listViewはMainActivity内のListViewとする
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setMessage("削除しますか？")
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // remove item from ArrayList
                        data.remove(position);
                        // update ListView
                        adapter.notifyDataSetChanged();
                        Toast.makeText(MainActivity.this, "削除しました", Toast.LENGTH_SHORT).show();
                    }
                })
                .setNegativeButton("キャンセル", null)
                .setCancelable(true);
        // show dialog
        builder.show();
         return false;
    }
```

###公式のやり方
https://developer.android.com/reference/android/app/DialogFragment.html
より抜粋

- 呼び出し元のActivityに各Buttonをクリックしたときの処理をメソッドとして書いておく
- DialogFragment内では、`getActivity().doPositiveButton()`で、そのメソッドを呼ぶだけ

```java
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    int title = getArguments().getInt("title");

    return new AlertDialog.Builder(getActivity())
            .setIcon(R.drawable.alert_dialog_icon)
            .setTitle(title)
            .setPositiveButton(R.string.alert_dialog_ok,
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        ((FragmentAlertDialog)getActivity()).doPositiveClick();
                    }
                }
            )
            .setNegativeButton(R.string.alert_dialog_cancel,
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        ((FragmentAlertDialog)getActivity()).doNegativeClick();
                    }
                }
            )
            .create();
}
```

###追記: カスタムadapterを使ったときの、itemの削除方法
https://stackoverflow.com/questions/7372301/how-do-i-delete-an-item-from-my-custom-base-adapter

>You do not delete from the adapter ! You delete from the items ! and the adapter is between your items and the view. From the view you can get the position and according the position you can delete items. Then the adapter will refresh you views.

>That means you need to do something like this

> ```java
>items.remove(position);
>adapter.notifyDataSetChanged()
>```
Googleスプレッドシート　データの抽出方法まとめ

プログラミングではないですが、シート間などで値を参照するのに便利なので共有します。
これくらいはさくっとできないとビジネスパーソンとしてノーバリューですね。

ちなみになんですが、大学生が勉強すべき（もちろん大人も）スキルランキング１位はExcel(スプレッドシート)だと個人的には思います。
また最近はExcelよりスプレッドシートのほうが使用機会が多いのではないでしょうか。その割にネット上の情報はExcelのものが圧倒的に多いのでスプレッドシート絡みの発信も増やしたいと思います。



#Query関数とは？
スプレッドシート独自の関数で、指定したデータの抽出をするのに用いる関数です。条件も複数設定できるので指定したデータを抽出して挿入するというような使い方もできます。
基本形は以下の形です。

```
=QUERY(データ、クエリ、[見出し]）
#データ：クエリ関数を実行する抽出元データの範囲を表す。
#クエリ：クエリ言語で記述された関数の実行対象クエリのこと。
#見出し：データ上部の見出しの行数。

```
パット見コピペで良いように思えますが、コピペだと元データを変更した際に変更が反映されないので関数を用いる必要があります。
#使い方
今回は以下のような名簿データからデータを部分的に抽出するような作業を行うと想定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/222924/4f1abcde-9125-f89e-ac70-ba4c3b346064.png)


別シートにてQuery関数を記述していきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/222924/891de76c-914c-d88e-f51e-5895520c2b94.png)

今回の記述内容を説明すると
`=query('名前一覧'!A1:Z1000,"where D='東京都'")`

一つ目の要素は「名前一覧」というシート上の抽出したいデータの範囲を指定しています。
二つ目の要素を説明する該当データ範囲の中で抽出したい条件を記述しています。
この部分代表的な条件の記述方を紹介しておきます。

```
①select
データ範囲において抽出したい行を指定します。順番の並び替えなども可能です。
(例）Query(A1:F,”Select A,C,E,F“)
A１からFの範囲の中でA,C,E,F列を抽出します。

②Where
抽出する際のデータを細かく指定できます。条件は複数指定可能です。
(例）Query(A1:F, ” Where C = ‘みかん’ “)
A１からFの範囲の中でC列がみかんのものを抜き出します。

③order by
データを抽出した後適切な条件で並び替えて挿入します。asc(昇順)又はdesk(降順)と表す。
(例)Query(A1:F,” Where C = ‘みかん’ Order by B asc “)
A１からFの範囲の中でC列がみかんのものをB列を基準に昇順（asc）に並べ替える。

```
そして計算式を実行すると以下のように条件を満たすデータのみが抽出されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/222924/6ff5653d-38c6-b8b0-3f85-9de60ce195ee.png)


#importrange関数について
今回紹介した内容では同じファイル内でのデータのやり取りしかできません。そこで異なるファイル間でやり取りするのに用いるimportrange関数を簡単に紹介しておきます。
構文は以下の通りです。
`＝IMPORTRANGE(スプレッドシートキー, 範囲の文字列)`
スプレッドキーとはファイルを判別するキーです。以下の通りURLの一部に組み込まれてます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/222924/bbf5f9c1-9f22-68e6-39ee-dce255cc73c0.png)
範囲の文字列はそのファイル内でデータ範囲を指定します。これはQuery関数でも使いましたね。

#おわりに
小さな企業だと顧客管理や営業リスト、マーケティングデータ管理など多くの場面でスプレッドシートを導入しているケースが多いと思います。基本的な知識はインプットし事務作業は自動化した上で創造的な活動時間を増やしていきたいですね。

#参照
・[スプレッドシートquery関数の使い方！vlookupより断然オススメ！](https://xn--t8j3bz04sl3w.xyz/spreadsheet/query/1893/2/)
・[スプレッドシート関数（Query）の便利な使い方](https://www.eigyoh.com/column/column_29/)
・[【スゴイ】スプレッドシートimportrange関数の使い方！他シートのデータを取り込めるゾ！](https://xn--t8j3bz04sl3w.xyz/spreadsheet/importrange/1856/)
HTML CSS 要素メモ

HTML・CSSについて知識０から学んでます。
学んだことをまとめていきます。

知識がアップデートされたら、その都度更新していきます。

・clear：both；
　→前のfloatの処理を打消す

・border-bottom
　→下ボーダーのスタイル・太さ・色を指定する

・ul
　→リストを記述

・li
　→ulやolの子要素として、中の各項目を記述する（必ず親要素に囲まれる必要がある）
 
・a
　→リンクを記載する```<a herf=”リンク”>表示文字列</a>```

・text-align
　→その要素のborderの範囲内で、左右真ん中に寄せる

・possition
　→ボックスの位置が絶対か相対かを決める

・line-height
　→上下の行間を指定する

・no repeat
→背景画像を繰り返さない
なぜバックアップが必要の4つの理由

企業としてバックアップは存亡にかかる重要なことです。しかし、個人としてバックアップする習慣がある人が少ないです。PC障害などにあったら、常に[ファイル復旧](https://jp.easeus.com/data-recovery-software/drw-free.html "ファイル復旧")の方法を探しています。では、なぜバックアップが必要ですか。以下の画像をみるとわかるかもしれません。
![Reasons to backup your data Infographic.png](https://qiita-image-store.s3.amazonaws.com/0/203250/6926efbd-3146-5d2f-645b-0cb538f56fb6.png)

参考サイト:https://www.storagecraft.com/blog/top-five-reasons-to-back-up-your-data/
https://jp.easeus.com/knowledge-base/difference-between-backup-and-clone.html
https://jp.easeus.com/backup-software/free.html
Visual Studio 2017 Visual C++ による Win32 スタティックライブラリの開発

#はじめに
スタティックライブラリは、アプリケーションに静的にリンクされるライブラリで、アプリケーションのビルドのときにリンクされます。ライブラリに含まれる関数は exe ファイルに組み込まれるので、DLL のようにファイルをパスの通ったフォルダなどに配置しておく必要はありません。

DLL の場合は、他のアプリケーションとライブラリを共有できますが、スタティックライブラリでは、exe ファイルにライブラリが組み入れられるので、他のアプリケーションとの共有はできません。

DLL の場合は、実行時に LoadLibrary API 関数などにより、公開関数のロード/実行が可能ですが、スタティックライブラリでは、そのようなことはできません。

#プロジェクトの作成
「新しいプロジェクト」ダイアログで「Windows デスクトップ」を選び、プロジェクト一覧の中から「スタティックライブラリ」を選んで OK ボタンをクリックします。

![VCProj_StaticLib.png](https://qiita-image-store.s3.amazonaws.com/0/62802/f376ec01-41df-d09d-f9b4-c3cabc361593.png)


プロジェクトが作成されると、最初はヘッダーファイルもソースファイルも入ってないので、プロジェクトを選んで「追加」コンテキストメニューからヘッダーとソースファイルを追加します。下の例では、StaticLib1.h と StaticLib1.cpp を追加しました。

![StaticLibProj.png](https://qiita-image-store.s3.amazonaws.com/0/62802/c6df38ae-ad39-ede3-3f2e-26c2377ceda0.png)



#サンプル
このサンプルは、現在のマシン上に接続されているドライブ一覧を取得する関数をスタティックライブラリとして実装したものです。

DLL と違ってスタティックライブラリでは、モジュール定義ファイルや export 宣言などのようなものは不要です。グローバルな関数はすべて公開されます。

##StaticLib1.h
ヘッダーファイルでは関数のプロトタイプを宣言します。このファイルは、stdafx.h にインクルードしておく必要があります。

```C++
#pragma once

#include <Windows.h>

extern "C" int GetLogicalDriveCount();
extern "C" BOOL GetLogicalDriveString(int, LPWSTR, int);
```

##StaticLib1.cpp
C++ ソースファイルでは、関数の具体的な実装を記述します。

```C++
#include "stdafx.h"
#define BUFFSIZE 1024

// 論理ドライブの数を得る。
int GetLogicalDriveCount()
{
	WCHAR buffer[BUFFSIZE];
	DWORD ret = GetLogicalDriveStrings(BUFFSIZE, buffer);
	if (ret == 0 || ret > BUFFSIZE)
		return -1;
	
	// '\0' の数を数える。
	int c = 0;
	int i = 0;
	while (!(buffer[i] == '\0' && buffer[i + 1] == '\0'))
	{
		if (buffer[i] == '\0')
			c++;

		i++;
		if (i >= BUFFSIZE)
			break;
	}
	c++;
	return c;
}

// 指定された番号(0,1,2,3..)の論理ドライブ名を得る。
BOOL GetLogicalDriveString(int n, LPWSTR drive, int m)
{
	WCHAR buffer[BUFFSIZE];
	DWORD ret = GetLogicalDriveStrings(BUFFSIZE, buffer);
	if (ret == 0 || ret > BUFFSIZE)
		return FALSE;

	lstrcpyn(drive, buffer, m);
	LPCWCHAR p = buffer;
	int c = 0;
	while (c < n)
	{
		while (*p != '\0')
			p++;
		p++;
		lstrcpyn(drive, p, m);
		c++;
	}

	return TRUE;
}
```

##テストプログラム
このテストプログラムでは、ライブラリ関数 GetLogicalDriveCount でドライブ数を取得して、GetLogicalDriveString 関数を使って、具体的なドライブ名を取得して表示しています。

StaticLib1.h はスタティックライブラリ・プロジェクトからコピーしてプロジェクトに含めます。このヘッダーは stdahx.h にインクルードしておく必要があります。

ライブラリファイル (StaticLib1.lib) がソリューションの Debug フォルダにできているはずなので、それをプロジェクトのプロパティの「リンカー」「入力」の「追加の依存ファイル」に追加しておきます。（これによりスタティックライブラリがビルド時にリンクされる)

![StaticLib_Library.png](https://qiita-image-store.s3.amazonaws.com/0/62802/14e2fc93-6eca-efe1-4426-7dcd34d84cd7.png)


テストプログラムソースを下に示します。

```C++
// TestStaticLib1.cpp : アプリケーションのエントリ ポイントを定義します。
//
#include "stdafx.h"
#define DRIVELEN 128

int main()
{
	WCHAR drive[DRIVELEN];

	// ドライブの数を得る。
	int n = GetLogicalDriveCount();
	if (n < 0)
	{
		printf_s("Error.\n");
		getchar();
		return 1;
	}
	else
	{
		printf_s("ドライブの数 = %d\n", n);
	}

	// ドライブ一覧を表示する。
	for (int i = 0; i < n; i++)
	{
		GetLogicalDriveString(i, drive, DRIVELEN);
		wprintf_s(L"%s\n", drive);
	}

	getchar();
    return 0;
}
```

下のイメージはこのテストプログラムの実行例です。

![StaticLib1_Test.png](https://qiita-image-store.s3.amazonaws.com/0/62802/bf789eb6-3add-f198-bbb9-f50fa0577f1b.png)

-