OmniAICreator/Qiita-1.07M huggingface dataset:
Magentaのdocker imageをmacbookで動かして画像変換したら真っ黒な画像が出てきた場合の対処法

#やりたいこと
Magentaのプリセットで用意されているモデルを使って、モネ風の画像に変換する。

##出来上がったもの
マシンスペックの関係で大きいファイルだと変換ができなかったので、以下の通り画像の一部分だけ切り取って変換しました

変換前
![IMG_1337 2.jpg](https://qiita-image-store.s3.amazonaws.com/0/44525/ad7d2af0-dc01-f1dc-c293-6111aa1bee0b.jpeg)


変換後
![all_monet_styles_0_100_1_100_2_100_3_100_4_100_5_100_6_100_7_100_8_100_9_100.png](https://qiita-image-store.s3.amazonaws.com/0/44525/5155327e-e6e2-a704-7d06-beca619a7595.png)

すごい！完全にモネ！
これを実現するためにハマったポイントが以下の通りです。

#ハマった現象
何度トライしても真っ黒な画像が出力されてしまいました。
実行時にエラーも出ず、心が折れてしまいそうになりました。

#原因はCPUでTensorFlowを動かしていたから
ググると以下のissueにたどり着きました

[Image stylization example only produces black images when run on CPU #570](https://github.com/tensorflow/magenta/issues/570)

MagentaはTensorFlowをバックエンドに使用しています。
TensorFlowは基本的にGPUの使用を前提にしているのですが、オプションとしてCPU上だけで処理をすることができます。
しかしMagentaのdocker imageの最新版（ `0.1.13` ）ではそのbug fix対応版が入っておらず、正常に動作しなかった結果、真っ黒な画像が出力されていました。

#古いバージョンのdocker imageなら動かせた
私が動作させることができたバージョンは `0.1.6` でした。
操作手順は以下の通りです。

##docker imageの取得と起動
```shell-session
$ docker pull tensorflow/magenta:0.1.6
$ docker run -it -p 6006:6006 -v /tmp/magenta:/magenta-data tensorflow/magenta:0.1.6
```
###フォルダ構成
```shell-session
magenta-data
└── img
    ├── original ← ソースとなる画像ファイル置き場
    └── generated ← 生成された画像が吐き出されるディレクトリ
```
##画像変換コマンド
```shell-session
$ image_stylization_transform \
      --num_styles=10 \
      --checkpoint=/magenta-models/multistyle-pastiche-generator-monet.ckpt \
      --input_image=/magenta-data/img/original/IMG_1337.jpg \
      --which_styles="{0:0.1,1:0.1,2:0.1,3:0.1,4:0.1,5:0.1,6:0.1,7:0.1,8:0.1,9:0.1}" \
      --output_dir=/magenta-data/img/generated/ \
      --output_basename="all_monet_styles"
```
ポイントとしては `--checkpoint` パラメータでプリセットのモデルファイルを指定すること、 `--which_styles` パラメータで、用意されているモデルのどれをどのくらいの割合で使うかという指定です。
詳しくは[こちら](https://soralab.space-ichikawa.com/2016/11/tensorflow-magenta/)の解説がわかりやすかったです。

#参考
[magenta/magenta/models/image_stylization at master · tensorflow/magenta](https://github.com/tensorflow/magenta/tree/master/magenta/models/image_stylization)
[TensorFlowのMagentaで高速に画風変換してみた](https://soralab.space-ichikawa.com/2016/11/tensorflow-magenta/)
[写真をモネ風タッチに変換する(magenta image_stylization)](https://qiita.com/tackey/items/405e2d1da87033104cdb)
git push/pullで403 Forbidden while accessingエラーが出た時の対処

git pullしたら403 Forbidden while accessing pullってでた。
困った。

```
error: The requested URL returned error: 403 Forbidden while accessing
```

gitのバージョンが古いのが問題っぽいのでアップデートしてみる（yumで入れたやつ使ってたので1.7.1とか使ってた）

```
$ sudo yum remove git
```
してから、

これのソースからインストールで2.4のやつをインストール
http://www.task-notes.com/entry/20150622/1434942000

できた。よかった。
目次

#ブログのインデックス

第1回：[Python インストール](https://qiita.com/billy-attack/items/017cb7d9c1524a6cb908)
第2回：[pyファイルの書き方](https://qiita.com/billy-attack/items/8487eb282727d4834230)
第3回：[基本構文](https://qiita.com/billy-attack/items/c16c6ff13d65812a2d11)
コンソールアプリケーションとしても振る舞えるXamarin.Macアプリケーションの作り方

## Problem
GUIアプリケーションとして通常のフローで立ち上げることができる。
しかしターミナルなどから引数を与えて立ち上げたときはそのまま標準出力に結果を返して終了する。
そういうことをmacOSアプリでやりたくなったときに参考にしてください。
方法論としてXamarin特有というわけではありませんが，ここではXamarin.Macを使って解説します。

## TL;DR
エントリポイント `Main.cs` で分岐します。

## Prerequisites
- Visual Studio for Mac Version 7.3 (build 799)
- Xamarin.Mac 4.0.0.214

ここで作ったサンプルは [GitHub:xamarin-mac-console-sample](https://github.com/ailen0ada/xamarin-mac-console-sample) に公開してあります。

## Solution
### プロジェクトを作る
Xamarin.Macプロジェクトを適当に作ります。詳しい手順は割愛しますが，ウィンドウが立ち上がるようにしておいてください。
![Screen Shot 2017-12-14 at 15.14.41.png](https://qiita-image-store.s3.amazonaws.com/0/34563/c67fef5d-c4cc-000b-c2c7-d59846784308.png)

### Main.csで引数をパースする
`Main.cs` はたいてい次のようになっているはずです。

```csharp:Main.cs
using AppKit;

namespace ConsoleSample
{
    static class MainClass
    {
        static void Main(string[] args)
        {
            NSApplication.Init();
            NSApplication.Main(args);
        }
    }
}
```

`NSApplication.Init` を呼ぶと，`NSNotificationCenter.DefaultCenter`やら，`NSFileManager.DefaultManager`などNS*系の静的インスタンスが確保され使えるようになります。つまり呼ばないとNS*系のなにがしかは使えたり使えなかったりします。だいたい使えません。

`NSApplication.Main` を呼ぶとアプリケーションの起動シーケンスに入り，`AppDelegate`へ制御が移っていきます。その前に引数をパースして処理を分岐するのが本稿の目的とするところです。ということで適当にコマンドラインパーサーをNuGet経由で入れるなり，自前でパースするなりしましょう。ここでは[dotnet-corefxlabリポジトリ](https://dotnet.myget.org/gallery/dotnet-corefxlab)で提供されている`System.CommandLine`を使います。雑ですがおおよそ次のようになるでしょう。

```csharp:Main.cs
using System;
using System.CommandLine;
using AppKit;

namespace ConsoleSample
{
    static class MainClass
    {
        static void Main(string[] args)
        {
            var input = string.Empty;

            ArgumentSyntax.Parse(args, syntax =>
            {
                syntax.DefineOption("i|input", ref input, true, "Something interesting.");

                syntax.ErrorOnUnexpectedArguments = false;
            });

            if (string.IsNullOrEmpty(input))
            {
                NSApplication.Init();
                NSApplication.Main(args);
            }
            else
            {
                Console.WriteLine($"{input.Length} - {input}");
            }
        }
    }
}
```

プロジェクトの設定から引数を指定してデバッグする，ターミナルから引数を与えて起動するなどで動作を確認できます。ターミナルから起動したい場合は `app/Contents/MacOS/` にエントリポイントがあります。
![Screen Shot 2017-12-14 at 15.27.56.png](https://qiita-image-store.s3.amazonaws.com/0/34563/462c7abb-d142-0654-12fc-c1f3987863b8.png)
![Screen Shot 2017-12-14 at 15.28.16.png](https://qiita-image-store.s3.amazonaws.com/0/34563/8f0ba052-eb9e-453a-a996-b47fa36ce477.png)

```shell
% ./ConsoleSample.app/Contents/MacOS/ConsoleSample -i Hello
5 - Hello
```

当然ながら，何も引数を与えなければウィンドウが立ち上がり，通常のアプリとして振る舞います。

## Conclusion
`Main.cs` で起動前になんでもできることがわかりました。
ネイティブライブラリを読み込んでおいたり集約例外ハンドラを設置したりと，それなりのアプリケーションを作る際にはこの辺でいろいろ介入が必要になってくると思います。ぜひ覚えておいてください。
B3で教職員になる話＋α

#### なんで書くの
~~いやカレンダー立っておいて自分も一記事くらいは~~
もし僕と同じようにEEICに迷い込んだひとがいたらきっと役に立つと信じてる

昨日はつれなさんの強い記事（まだ公開されてないのでわからないがたぶんつよい）で、あしたは実験でおせわになりましたTAさんの記事だね、何書くでしょ楽しみ！

読む前に
以下の内容はどっちらかというとB2くらいの研究まだしたことのないひと向けで、先輩方が読むときは
![](http://d2dcan0armyq93.cloudfront.net/photo/odai/400/7811d58779a365768ff22cccd1fd4723_400.jpg "zako")
と思っていただければ。

__生き残るためにお金が大事。__
EEICにGoogleとかMSインターン行ってる人もたくさんいれば、時給３０００円超えるバリバリエンジニアも普通にいる。  
でももしぼくみたいな
「えわたし__そんなすごいことできないけどお金はほしい、もっとアカデミアに近い勉強もしたい、publication出せればなおよし__」という人のための記事でもいえよう、あとは研究室選びにも役立つじゃないかと（と思うがぼくは選ぶ立場にいないのでなんとも言えんが
それと、ぼくのバイト歴のなかで、研究類似行為ではないものは４ヶ月のレストランのホールくらいなので、かなりバイアスが入ると思う。

では本題。
知ってる人は知ってると思いますが、~~ぼくいつも研究つらいツイートしてる~~僕は最近本学の教職員になった。
教職員って聞こえがいい（そんなことがない）かもしれないが研究補助なので、研究雑用レベルくらいしかしてない。
せっかくなので、いままでやってきた、研究バイトというものをまとめていきたいなとおもう。　アカデミアとプライベートリサーチ両方とも。
__以下の内容は研究バイトisなにというより、ぼくがこの２年くらい働いてに感じたことのまとめになる__

まずはアカデミアの方から
東大の先生方が大体すごい人であることはもう今さらということもないですが、東大の先生はまず__研究資金が潤沢__の方が多くいらっしゃる。例えばEEICの川原研のERATOは、5年で億単位でおりできます、ほかには染谷先生も同じ資金持っています(今は終わったぽい?）。そんな先生は大体研究補助をさがしている。たとえば、学科は違いますが、同じツイッタにいつもいるのでEEIC民はおそらくお馴染みの稲見先生ですが、今年のERATOで[バイト募集](https://star.rcast.u-tokyo.ac.jp/joinus.html)しています。とても楽しい内容ですので、ぜひ見てください（念のために、ぼくと稲見研は関係ないです）。なんか怖いかもしれないけど、EEIC民なら余裕とかのところもあるので、ぜひ応募してみてください。

実際やる内容はもちろん研究室によりますが、だいたい実装、実験とかやらせていただきます。  

メリットデメリットだけまとめると

メリット:
1. お金もらって研究できる
2. 研究機材使える
3. (学内の場合）通勤時間ほぼゼロ
4. 研究という概念もう少し理解できる（理解したとは言ってない
5. 論文出せる
6. 学会に出れる
7. 研究室の都合でやりたいことがだんだんできなくなることもある
8. 自分が研究に向いているかどうかがわかる
9. 最先端の先生の研究グールプにはいれて情報交換できる
10. 研究ダメ出される（大事
11. 研究資金申請できる  Nvidiaの Academic Grant とかいろいろ、興味ある人は連絡してください
12. 雇われやすい　その分野で有名な先生でも普通に学生が集まらなくて困ってる時が多いと聞いたので、とりあえず応募だそう


デメリット
1. 成果出ないと困る
2. 成果出ないと本当に困る
3. ~~成果出てなくて本当にとても困ってます~~
4. 見ての通り困りの果てにメンヘラに成り下がる人もいます
5. とあるお世話になった先生が「D進で大体ハゲ、デブ、鬱の少なくともひとつになる」と仰いました、ぼくも２年で11キロ増えた気がします…それはEEICのせいでもあると思いますが
6. 研究したい分野が自分の中で消滅することもある
7. そこまで興味ある分野じゃなくても読まされる（いいことでもあるが
8. D進がやたら勧め（あお）られます（当方B3
9. 場所によって出勤自由とかあればいちいち出勤ボタン押されるところもある
10. ブラックなところはブラック。

あとはメリットかわからないが、__いきたい研究室が変わってくる。__
自分のやりたい研究がすでに始まってるので、卒論でやりたい研究は一番興味ある分野より、__卒論でやらないとたぶんこれからの人生に関わることのない\できないだろう分野がやりたくなっている__。僕の場合はエネルギーや医療関係など、いままで触れたことのない分野を一年間楽しくいい先生の下に学びましょうという気持ちになる(総合点戦争色々むりという気持ちもあるけど

プライベートリサーチャーの方は
Wantedlyとかでもたまに見かけるけど、大きな会社なかなか出会えないと思いが、Hackthonとかでると、ためにスカウトされる。
メリットとデメリット大体アカデミアと一緒なので、違うところだけ書いておく。

メリット:
1. お給料が相対的によい
東大の学生非常勤は決まった金額になります（と聞きました）ので…控えめに言ってダメ。
2. 資源が相対的に豊か
GPUとかいいやつ使わせてもらえます。
3. 場所によってかなり自由な日程

デメリット
1. EEICのどS日程に合わない（合わせてくれる会社もありますが
2. 論文出せない会社もある
3. 分野によってそもそも学部生の枠がない
4. 大きな会社だと休日出勤がダメとかリモート勤務がダメとかいろいろある
5. コネやきっかけがないと探し辛い


あとはデメリットではないが、アカデミアの研究とバイトの研究実感してきて一つの大事なことがある。
アカデミアは今までないものを作ろうとしている（新規性をも求めている）が、ビジネスはそうでもない、今まで普及してなくてお金になりそうなものであれば何でもいいので、論文に出すようなものも作るけど、メインがドメインアダプテーションとかとりあえずお金になれそうなのやることが多いと実感した。（もちろん、研究分野や会社にもよる）。
どっちがいいとかではなくて、自分がどういう人生(研究)がほしいかによって選んでもらえればと。

ではでは、もしこれからバイトを探している人がいたら頑張ってください。
健闘を祈る。  
(もし質問や相談したいならツイッタよりリアル凸のほうが返事する確率が１標準偏差くらい上がるのでおすすめ

最後にもしB3の人がここまで読んでくれたら、mthsやykym研の見学いきませんか。
MAMP使ってると出くわすsocketエラー

wordmoveを使ってさくらレンタルサーバーにデプロイしようとしたところ、
`Can't connect to local MySQL server through socket '/tmp/mysql.sock'`
データベースのデプロイでこのエラー。

wordmoveが叩くlocalのmysqlのsocketファイルの参照先がMAMPと違うために起こる。

**MAMPで使うsocketファイルでシンボリックリンク貼ればOK。**

```bash:
$ln -s /Applications/MAMP/tmp/mysql/mysql.sock /tmp/mysql.sock
```

/Applications/MAMP/tmp/mysql/mysql.sock →　MAMPのsocketの場所
/tmp/mysql.sock →wordmoveを使うにあたり期待されているsocketの場所
deployerを実行した時にエラーになって進まないのを解決する話

## やりたいこと
とりあえずDeployerを普通に走らせたい。

##環境
- PHP 7.0
- CentOS 6.7
- Deployer 6.0.3

## 症状
本家に言われたとおり/user/local/binにpharを配置して、なんの変哲もないコードを書いて走らせたら、

```php:deploy.php
namespace Deployer;

require 'recipe/common.php';

// Tasks
task('test', function(){
　　writeln('test');
});
```
とりあえずなんか出来てはいるようだけど、よく分かんないエラーが出て怒られる。

```
$ dep test
➤ Executing task test
test
✔ Ok

 [Error] Call to undefined function Deployer\Utility\posix_setsid()

 #0 phar:///usr/local/bin/dep/src/Deployer.php(368): Deployer\Utility\Reporter::report(Array)
 #1 [internal function]: Deployer\Deployer->collectAnonymousStats(Object(Deployer\Console\CommandEvent))
 #2 phar:///usr/local/bin/dep/src/Console/Application.php(140): call_user_func(Array,
 Object(Deployer\Console\CommandEvent))
 #3 phar:///usr/local/bin/dep/vendor/symfony/console/Application.php(223):
 Deployer\Console\Application->doRunCommand(Object(Deployer\Console\TaskCommand),
 Object(Symfony\Component\Console\Input\ArgvInput), Object(Deployer\Console\Output\OutputWatcher))
 #4 phar:///usr/local/bin/dep/vendor/symfony/console/Application.php(130):
 Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput),
 Object(Symfony\Component\Console\Output\ConsoleOutput))
 #5 phar:///usr/local/bin/dep/src/Deployer.php(324):
 Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput),
 Object(Symfony\Component\Console\Output\ConsoleOutput))
 #6 phar:///usr/local/bin/dep/bin/dep(119): Deployer\Deployer::run('6.0.3', '/home/vagrant/d...')
 #7 /usr/local/bin/dep(4): require('phar:///usr/loc...')
 #8 {main}
```

これ……私のせいか……？！

調べたら、救世主登場。
[POSIX disabled on CentOS 7 : https://github.com/deployphp/deployer/issues/1201](https://github.com/deployphp/deployer/issues/1201)

## 原因：php-process が必要らしい
エクステンションが足りてないとか、そういう……。
あれ、私必要要件の欄読み飛ばしたのか…？と思いつつ、

```
sudo yum install --enablerepo=remi-php70 php-process
```
を叩いてphp-processを入れました。
無事に動くようになりました。

```
$ dep test
➤ Executing task test
test2
✔ Ok
```

未だに必要要件が書いてあるページを見つけられません。
どなたか知ってたら教えてください。

## 参考
- [POSIX disabled on CentOS 7](https://github.com/deployphp/deployer/issues/1201)
glsl constとdefineの違い

# はじめに
glslでは定数を定義するのにdefineを使う方法とconstを使う方法がありますが両者共明確に異なるので、それぞれの用途について解説します。

# define

defineはマクロ的に展開される。つまり文字列が置換されて展開される。

# const

constは定義時に実際に値が計算される。

# 具体例

両者の違いを具体的に見ていきましょう。
具体的には、defineでPIが設定してあった場合

```glsl
#define PI 3.141592653589793
#define PI2 PI * 2.
```

```glsl
float r = (atan(p.y, p.x) + PI) / PI2;
```

というのはマクロ的に展開されてしまって

```glsl
float r = (atan(p.y, p.x) + PI) / PI * 2.;
```

の場合意図した計算にならない。

```glsl
const float PI  = 3.141592653589793;
const float PI2 = PI * 2.;
```

の場合は、PI2の定数として参照される。

```glsl
float r = (atan(p.y, p.x) + PI) / PI2;
```

# それぞれの使い道

defineの場合単なる文字列置換であり、上記のような事故が起こるので、なるべくPIなどの定数はconstを使った方がいい。

defineの方は、glslの文法関係なく、自由に置換したい文字列を定義できるので、短い関数の定義などはとても便利

```glsl
#define saturate(a) clamp( a, 0.0, 1.0 )
```

これも、実際にはマクロ的に展開されているってことになります。
つまり、glsl的にはsaturate関数というユーザー定義関数は定義されていない。

saturateの場合はこっちの方が良さそうです。
「NVDIMM」のすゝめ

この記事はSFC-RG Advent Calendar 2017の14日目です。

突然ですが、メインメモリは電源を落とすと中のデータは消えます。
これはDRAMの特徴であり、如何ともしがたい部分ですね。
そして、2017年12月現在メモリの値段は爆発的に上昇しています。
どれくらい値上がりしているかというと、新しくサーバーを買うときに一番コストがかかる部品がメモリになるくらい値上がりしています。
もちろんメモリベンダも生産量を増やそうとはしていますが、しばらくはDRAMの値段は高いままという予測が主流です。

#NVDIMM #とは
そんな中で、「NVDIMM」というワードが最近ハードウェアベンダーの中で静かなブームとなっています。
NVDIMMは「Non-Volatile Dual In-line Memory Module」の略称で,日本語に無理やり直せば「不揮発性DIMM」となるでしょうか。
NVDIMMの定義としては、「メモリスロットに装着でき」、「RAMとして扱え」、そして「電源を落としてもデータを保持できる」ものです。
特徴としては
・容量単価がDRAMより安いNANDフラッシュや新興メモリ技術を用いることで容量単価が比較的安くなる
・CPUに直結されているDRAMバスに乗るため、通常のSSDと比較すると圧倒的に高速
・電源を落としてもデータが失われないSSDのような特性を持つ
というものが挙げられます。
#JEDEC公認のNVDIMMの3つの実装
NVDIMMと一口によっても、用いるメモリ技術と使用方法で大きく3つに分けることが出来ます。
##NVDIMM-N
![image.png](https://qiita-image-store.s3.amazonaws.com/0/217644/f14c15b9-6b3d-9121-5cf7-045e03027283.png)
DRAMと不揮発性メモリ(基本的にはNANDフラッシュ)を同じ容量搭載したモジュールです。
CPUからはDRAMにのみアクセスができ、適宜不揮発性メモリにバックアップがとられます。
もし電源が遮断された場合は、自分のモジュールに搭載されているor接続されているコンデンサやバッテリーによって電源が供給され、DRAMの内容を全てNANDフラッシュに書き出します。
###利点
・CPUからはDRAMにしか書き込まないので、DRAMと等速・等レイテンシ(=パフォーマンスの減少はない)
・DRAMに書き込むので、キャッシュラインサイズ(=CPUがアクセスできる最小単位)でアクセスが可能
・DRAMに書き込むので、OSの対応が不要
###欠点
・DRAMとNANDの容量が同じなので、通常のメモリモジュールより容量当たり価格は高くなる
・同様にNANDもDRAMも同容量積載するので、通常のメモリモジュールより1枚当たり容量が低下するor信頼性が低下する(予備DRAMチップが積めない)
###採用商品
HPE Persistent Memory(HPE)
AGIGARAM(AGIGA Tech)
NVDIMM(SMART Modular Tech.)
現在「不揮発性メインメモリ」として発売されているのはこのタイプが主流です。
##NVDIMM-F
![image.png](https://qiita-image-store.s3.amazonaws.com/0/217644/b46dcdf3-d8c6-2d30-2446-9a839eb5ac66.png)
DIMMモジュールに、(コントローラ用キャッシュを除き)フラッシュメモリのみ搭載したモジュールです。
イメージとしてはメモリバスに直接ぶら下がるSSDという認識で正しいです。
###利点
・SSDと同じくフラッシュメモリのみを搭載するため、容量当たり単価が廉価
・1枚のモジュールで大容量化が可能
・PCI-E接続のSSDと比較すると高速
###欠点
・基本的にはSSD同様4KBのブロックアクセスが主流になるため単独でシステムメモリとして利用するのはかなり難しい(コントローラによってはキャッシュラインアクセスにも対応)
・レイテンシはNANDのものが直接見えるためDRAMと比べるとレイテンシは大きい
・DRAMと比較するともちろん低速
・コントローラに依存するものの、基本的にはOS・BIOS・CPUの対応が必要
###採用商品
ULLtraDIMM(Sandisk)
なかなか商品として市場には出ていません。
##NVDIMM-P
![image.png](https://qiita-image-store.s3.amazonaws.com/0/217644/6d5a8c80-7a89-e349-4196-a50ce0af4e1a.png)
JEDECにて唯一詳細がいまだ策定中のものです。ReRAMという新興不揮発性メモリをストレージに利用し、DRAMをキャッシュとして搭載します。
バスはDDR5になるようなので、登場は2020年以降となるでしょう。

#なぜ、今NVDIMMなのか
もちろんこれには理由があります。
なぜなら、来年発売が噂されている次世代のIntelのサーバ用プロセッサ、「Cascade Lake」にて不揮発性メモリのサポートが予定されているからです。
搭載されるのはIntelとMicronが共同開発した3D XPointメモリで、詳しいことはまだ分かりませんが、メモリのキャッシュとしても、ストレージのようにも使えるモジュールのようです。
上記のNVDIMMとはまた違った実装が予定されていますが、ソフトウェア的には後述のpmem.ioが提供しているライブラリに対応し、ソフトウェア的にはNVDIMMと互換性を持つようです。
詳細はこの記事を。

【後藤弘茂のWeekly海外ニュース】Intelの新メモリ「3D XPoint」がDIMMで投入される背景
https://pc.watch.impress.co.jp/docs/column/kaigai/717746.html

そして、Intelがサポートするということは来年以降にリリースされる多くのサーバーでIntelのNVDIMMが利用できるようになります。
当然、サーバーサイドのコードを書く際も「不揮発性DIMMを利用して」という条件が増えるのは想像に難くありません。
そんな時、「NVDIMMって何だよ(哲学)」となる前に、最先端でナウでイケてるエンジニアは名前だけでも押さえておくべき技術でしょう。

#どうやって使うのか
http://pmem.io/nvml/
こんなライブラリーが既に公開されています。
これを使えば(簡単とは言いませんが)それなりの手間で不揮発性メモリに対応させることができます。
今すぐテストできる環境は無いのでアレですが、目を通してみるといいかもしれません。
今までのメモリとはだいぶ変わりますので面白いですよ。

#最後に
「君のパソコン、メモリ何GB?」
「え？1TBだけど？」
「それってストレージ容量でしょwwww」
「いや、メインメモリで」
という時代もそう遠くないのかもしれませんね。

#参考文献
https://pc.watch.impress.co.jp/docs/column/semicon/721621.html
各メーカーHP
Twitterカードで動画をインライン再生する方法


## はじめに
URL付きでツィートした際に
Twitterのプラットフォーム内でインラインの動画再生が可能です。

![スクリーンショット 2017-12-14 13.54.34.png](https://qiita-image-store.s3.amazonaws.com/0/58950/91e3a3b3-5a44-c717-730b-5bb14bb17c29.png)


## 設定方法

HTMLのメタタグにTwitterカードの内容を記述します。

``` html
	<meta name="twitter:card" content="player">
	<meta name="twitter:site" content="@username">
	<meta name="twitter:title" content="テストタイトル">
	<meta name="twitter:description" content="テストです。">
	<meta name="twitter:image" content="https://xxxx/ki.png">
	<meta name="twitter:player" content="https://www.youtube.com/embed/xxxx?rel=0&amp;controls=0&amp;showinfo=0">
	<meta name="twitter:player:width" content="640">
	<meta name="twitter:player:height" content="360">
	<meta name="twitter:player:stream" content="https://xxxx/ki.mp4">
	<meta name="twitter:player:stream:content_type" content="video/mp4;">
```

- twitter:card (必須) 
	- 動画のためplayerを指定します。
- twitter:site (必須)
	- @username
- twitter:title (必須)
	- サイトタイトル
- twitter:description
	- 説明書きなくてもOK
- twitter:image (必須)
	- 非対応ブラウザのサムネールで表示される画像です。
- twitter:player (必須)
	- HTTPSのiframeに入る動画のURL
- twitter:player:width (必須)
	- iframeに入る動画の横幅
- twitter:player:height (必須)
	-  iframeに入る動画の高さ
- twitter:player:stream
	- スマホで使用される動画
	-  Video: H.264, Baseline Profile (BP), Level 3.0, up to 640 x 480 at 30 fps. Audio: AAC, Low Complexity Profile (LC)
- twitter:player:stream:content_type (必須)
	- mp4	

参考
[Player Card — Twitter Developers](https://dev.twitter.com/web/sign-inhttps://dev.twitter.com/cards/types/player.html)

注意したいのがwitter:playerのURLのプロトコルがHTTPSである必要が
あるところです。
クライアントのURLがSSL対応してなかった！！なんて事もあります。

そんな場合は、youtubeの埋め込みURLを使用してもOKです。

`https://www.youtube.com/embed/xxxx?rel=0&amp;controls=0&amp;showinfo=0`

xxxxに固有のURLが入ります。

### 埋め込みURL
![1.png](https://qiita-image-store.s3.amazonaws.com/0/58950/9e8c154d-7ece-b290-dba4-8d40bd42be66.png)

![スクリーンショット 2017-12-14 14.19.41.png](https://qiita-image-store.s3.amazonaws.com/0/58950/ed09b00c-b875-2639-82ed-d341d6f7830e.png)

### player:stream
mp4の動画URLが用意できない場合は、モバイルでは、動画が再生され無くなります。その代わり、twitter:playerに指定しているURLへ遷移します。

## 注意 申請
準備ができたら、申請が必要となります。
これが後になって発覚すると恐ろしいので、事前にやっておくことを
お勧めします。

### Card validatorのURL
[Card validator](https://cards-dev.twitter.com/validator)

![スクリーンショット 2017-12-14 14.46.21.png](https://qiita-image-store.s3.amazonaws.com/0/58950/30612d64-f60b-db2d-f05e-6d4d7fb1a2cb.png)

Card URLにURLをプロトコル(https://〜)から入力します。
サイトURLis whitelisted for player card  
と緑の文字で表示されればOKなのですが

サイトURL is not whitelisted for summary card
と赤字で表示される場合は、申請が必要となります。

その場合は、
Request Approval
から申請をかけます。

空白のサイトで申請しても通ったくらいなので、
申請自体はそこまで厳しい印象ではなかったですが、
申請には1日かかりました。
長ければ、1週間程度かかる事もあるようです。

ドメインが許可されれば、同ドメインであれば対象URLでなくても
使用ができるようです。

![スクリーンショット 2017-12-14 15.04.37.png](https://qiita-image-store.s3.amazonaws.com/0/58950/effdd2a3-83e3-e19c-3ba7-d7a2be04cceb.png)


こんな感じのsuccessfullyのログが表示されれば、一安心です。
【FileMaker】FileMakerからGoogle Calendarに予定を追加しよう(1)

Advent Calendarやってて何が楽しいかというと、埋まっていない小窓を誰かが開けてくれることですね。
今年のFileMaker Advent Calendarも素晴らしく埋まっていない小窓を誰かが開けてくれていて、とても勉強になります！

今回は、FileMaker 16バージョンでGoogle Calendarを取得し、予定を追加してみようという企画です。
基本的には、curlとjsonで出来上がると思われます。
ので、他のバージョンでcurl,json関連のプラグインを入れている方もぜひお試しください。

ちょっと長くなりそうなので、サクッと読めるように以下の構成で分割してお伝えします。

(1) Google CalendarをFileMakerのレイアウトに取り込む
(2) Google CalendarにFileMakerから予定を追加し、FileMakerに取り込んだGoogle Calendarで確認する

今日は、「(1) Google CalendarをFileMakerのレイアウトに取り込む」になります。

# 下準備
Googleアカウントを持っていることを前提にして話を進めます。
Google Calendarにカレンダーを追加すると、設定画面でカレンダーIDなるものが用意されています。
このカレンダーIDを使って、該当のカレンダーへアクセスします。
以下のような「カレンダーの統合」という部分で、カレンダーIDを確認できます。

![1215_1.png](https://qiita-image-store.s3.amazonaws.com/0/60538/fb002ccb-b250-ffba-7fa2-75a921338f23.png)

このカレンダーIDの他、Google API Keyを取得します。
最近では、色々なブログなどでGoogle API Keyの取得方法を解説していますので、そちらへ任せます。
最新の情報として参考になるサイトとして、[GoogleカレンダーAPIキーの取得方法を解説](https://www.1-firststep.com/archives/3559)を紹介しておきます。


# レイアウトを作る
実際にレイアウトを作っていきます。
今回は、グローバルフィールドにGoogleカレンダーのhttpアドレスとカレンダーIDを保持していますが、テスト的に実行する場合は、直書きで十分かと思います。
<img width="994" alt="1215_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/140b8cb7-b918-f807-bf44-a3aaccdeee8f.png">

Google Calendarのアドレスは、
https://calendar.google.com/calendar/embed
です。
これにカレンダーIDとタイムゾーンをくっつけて送信します。

レイアウトモードからブラウズモードに戻ると、Google Calendarへアクセスしにいき、カレンダーが表示されます。
<img width="1029" alt="1215_3.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/8a61d3da-92c0-3b0f-5851-5600b95dccda.png">
上記画面では、「リフレッシュ」ボタンを作ってカレンダーの最新表示を行なっていますが、ボタンがなくても再表示は行えます。
（「リフレッシュ」ボタンは、単にレイアウトを２回切り替えて再表示しているのみです）


Macの場合はCtrl＋クリックで「再読み込み」が表示されますので、これをクリックします。
<img width="740" alt="1215_4.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/9019d8c3-2bfb-aa7a-a16c-5000fc05128e.png">

Windowsの場合は、右クリックでリストから「最新の情報に更新」をクリックします。
<img width="277" alt="1215_5.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/3d6512db-3bbe-3c22-374a-ee78ca45cd8b.png">

# 動作の確認
表示されるイベントをクリックすると、バルーンが出て「詳細」「マイカレンダーにコピー」など、そのままできそうに見えます。
<img width="533" alt="1215_6.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/67a61a48-bc25-2c23-fb0d-9a22d623797f.png">
が、実際にはウェブサイトのGoogle Calendarへ飛ばされてしまいます。

こういうことをせずに、FileMakerで予定を追加し、FileMakerでGoogle Calendarを確認しよう、という動きが次回になります。

ただ、お仕事などでGoogle Calendarに予約が入るなどの場合は、わざわざサイトを立ち上げなくても予約が確認できますので、ここまでの実装でもかなり役に立ちそうです。

# 注意点
Google Calendarを読み込む、ということは、単にGoogleのカレンダーにアクセスしているだけですので、実際にFileMaker上にイベント情報を保存している訳ではありません。
業務上は、ここから先、ご自身の仕事として登録した内容を使って諸々の運用がなされることと思います。
Google Calendarから取得した情報をFileMakerのテーブルなどへ取り込むなどの処理は、別途記事が書ければ、と思っています。（ただ、そういう同期は意識しないとめんどくさーで終わってしまう可能性が。。。餅は餅屋という部分もありますので、全てをFileMakerでカバーしなくてもいい場合もあります）

# 追記(2017/12/25)
[p388cell](https://qiita.com/p388cell)さんから情報をいただき、webビューアの再表示を修正しました。

まずは、webビューアに名前をつけ、
<img width="485" alt="1215_7.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/7908c5e5-bf4b-61c5-23fa-4d8cac42b81f.png">

スクリプトで、「webビューアの設定」を選択し、先ほどつけたwebビューアの名前で再表示します。
<img width="839" alt="1215_8.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/aecc07f0-e31d-035f-ac0f-6f1c36442d45.png">

ありがとうございました！


では！
AngularJS creating multiple $resource endpoints in a service

For example, here’s a service called User which maps to the URL “/api/users/…”:

````
angular.module('myApp')
  .factory('User', function($resource) {
    return $resource('/api/users/:id/:controller', {
      id: '@_id'
    }, {
      changePassword: {
        method: 'PUT',
        params: {
          controller: 'password'
        }
      },
      get: {
        method: 'GET',
        params: {
          id: 'me'
        }
      }
    });
  });
````

individual elements inside the object that each map to a different $resource. So, for example:

````
'use strict';
 
angular.module('myApp')
  .factory('User', function ($resource) {
    return {
      WithId: $resource(
        '/api/users/:id/:controller',
        {
          id: '@_id'
        },
        {
          changePassword: {
            method: 'PUT',
            params: {
              controller: 'password'
            }
          },
        }
      ),
      Misc: $resource(
        '/api/users/misc/:controller',
        null,
        {
          generateResetPasswordToken: {
            method: 'POST',
            params: {
              controller: 'generateResetPasswordToken'
            }
          },
        }
      ),
    };
  });


$scope.user=new User.WithId();
Or whatever the sub-resource is called.

````
シンプルなデータ永続化ライブラリ"saves"のご紹介

# saves


みなさんはデータの永続化はどうされてますか？
sqlite3? realm? gcp?

大げさな下準備をせずにデータを永続化したい時ってありますよね。
そんな時は"saves"。

*カレントディレクトリにデータベース(sqlite3)が作成されます。


2020/6/4
データベース名に任意の名称を付与する機能を追加しました。

新たに作成するデータベースの名称を指定する

```
Saves.current_dbname = 'hoge'
s = saves.Saves()
```
現在使用中のデータベースの名称を変更する

```
s = saves.Saves()
s.set_db_name('fuga')
```

## usage

install

``` 
pip install saves
```

save

``` 
num = 99
s = saves.Saves()
s.save('number',num)
```

load

``` 
s = saves.Saves()
num = s.load('number')
print(num)
# 99
```

delete

``` 
s = saves.Saves()
s.delete('number')
```

delete all

``` 
s = saves.Saves()
s.clean()
```

get keys

``` 
s = saves.Saves()
keys = s.keys()
print(keys)
# ['hoge','fuga']
```

---

尚、現バージョンではint,str,list,dict,tupleの扱いのみ対応しています。

[Github/saves](https://github.com/Akirakong/saves "Github")
[AWS SDK for Go] S3の署名付きURLを取得する

##プライベートなS3コンテンツにアクセスしたい！
###→署名付きURLを発行する！
http://docs.aws.amazon.com/ja_jp/sdk-for-go/v1/developer-guide/s3-example-presigned-urls.html

```go
svc := s3.New(session.New(), aws.NewConfig().WithRegion("ap-northeast-1"))

req, _ := svc.GetObjectRequest(&s3.GetObjectInput{
	Bucket: aws.String("bucket_name"),
	Key:    aws.String("file_path"),
})
url, err := req.Presign(time.Hour * 2) // 有効期限を指定して署名付きURLを取得
if err != nil {
	fmt.Println("Failed to sign request", err)
}

fmt.Println(url)
```

コマンドでも取得できるので、確認用に
`$ aws s3 presign s3://bucket_name/file_path --expires-in 30`


## こう使ってます
1. DynamoDBにバケット名とファイルパスを保存しておく
1. バケット名とファイルパスを指定して、S3から署名付きURLを取得
1. ファイルが見れる！
MySQL レプリカ遅延を意図的に行う方法

## はじめに
開発で検証する際に意図的にレプリカ側の同期のタイミングを遅らせたいことがありますよね。
1年前ほど前に`percona-toolkit` を使って遅らせる方法で検証を行ったので、せっかくなので共有します。

## 環境情報

- Dockerを使ってリードレプリカ構成する方法は下記を参考にさせていただきました

[Dockerで手元にmysqlレプリケーション環境を構築](http://tkyshm.hatenablog.com/entry/2016/08/31/154727)

## リードレプリカ前提知識

**レプリケーションの利点**

- 参照性能の向上
    - DBサーバーの負荷を分散できる
- 高可用性構成
    - マスターの障害時にスレーブをマスタに昇格することで高可用性を実現
- 地理的冗長性
- バックアップとして利用

**レプリケーションの仕組み**

- スレーブがマスタにレプリケーション開始をリクエスト
- マスタ側が変更をバイナリで記録
   - 更新系のSQLのみ記録している
   - クエリ実行時間などのメタデータも記録
   - トランザクションのコミット時に同期的に記録
- マスタがレプリケーションにデータをスレーブに転送
- リレーログ(マスタから受信した変更点を記録したファイル)の内容をスレーブに適用
- `log-slave-updates` を設定している場合、スレーブでもバイナリログを出力（多段構成のレプリケーション時必須）


**準同期型レプリケーションと非同期型レプリケーション**

- 準同期型 => 高可用性目的  
  - マスタに障害が発生したら発生直前の更新内容も伝搬されている（データ欠損のリスク低い）  
  - マスタの更新パフォーマンスが悪くなる
- 非同期型 => 負荷分散向き  
  - マスタの更新パフォーマンスが良い
  - 障害発生直前のデータが伝搬されていない可能性がある
 
## percona-toolkitのインストール

brew経由でインストールします

```
$brew install percona-toolkit
```

## 遅延を発生させる方法

仕組みとしてはスレーブの開始と停止を繰り返すことで遅延を発生させているらしい

```
 // pt-slave-delay [OPTION...] SLAVE-HOST [MASTER-HOST]
$pt-slave-delay --delay 30s --interval 10s -u root 127.0.0.1 --port 13316
2016-09-21T16:49:22 slave running 0 seconds behind
2016-09-21T16:49:22 STOP SLAVE until 2016-09-21T16:49:52 at master position mysql-bin.000005/126000
2016-09-21T16:49:32 slave stopped at master position mysql-bin.000005/126000
2016-09-21T16:49:42 slave stopped at master position mysql-bin.000005/126000

```

より詳細のオプションについては下記を参考してください
[pt-slave-delay ― Percona Toolkit Documentation](http://www.percona.com/doc/percona-toolkit/2.1/pt-slave-delay.html)
warning: Insecure world writable dir /usr/local/bin in PATH, mode 040757


完全に個人的メモです
とある理由でruby gemをアップデートしないといけなかったので

```
sudo gem update —system
```

とコマンドを叩くと

```
/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/universal-darwin17/rbconfig.rb:214: warning: Insecure world writable dir /usr/local/bin in PATH, mode 040757
Latest version already installed. Done.
```

アップデート自体はできたようなのですがWarningが出たので確認して見ると

どうやら`/usr/local/bin`が書き込み可能になってるのが良くなかったようで
なんで757になってたのかも覚えてないのですがとりあえず下記のコマンドで権限を755にしたらWarningは消えました

```
chmod 755 /usr/local/bin
```
Square Connect Node SDKのChargeオブジェクトの使い方

SquareのAPIで何がしたいかと言えば、決済ではないでしょうか。そのためのAPIが[Charge API](https://github.com/square/connect-javascript-sdk/blob/master/docs/TransactionsApi.md#charge)になります。

```
POST /v2/locations/{location_id}/transactions
```

この時にNode SDKで送信するオブジェクトが ChargeRequest なのですが、使い方が分かりづらいかも知れません。

## 基本はユニークなIDと金額

ChargeRequest はそのまま生成することもできます。

```javascript
const body = new SquareConnect.ChargeRequest();
```

また、引数としてユニークなIDと金額を渡すこともできます。ユニークなIDについては[kelektiv/node-uuid](https://github.com/kelektiv/node-uuid)を使うと楽だと思います。

```sh
$ npm install uuid --save
```

```javascript
const uuidv1 = require('uuid/v1');
const uuid = uuidv1();
const body = new SquareConnect.ChargeRequest(
  uuid, {
    amount: 1000,   // 金額
    currency: 'JPY' // 通貨単位
  }
);
```

## この他使える情報

ChargeRequestにはこの他、下記の情報が適用できます。すべてオプションですが、card_nonce と customer_id/customer_card_id のいずれかは必須です。

|キー|意味|
|----|----|
|card_nonce|一時的に使えるカードトークン|
|customer_card_id|顧客化したカードID|
|delay_capture|trueにすると確定せず、オーソリのみ|
|reference_id|自社システム用のID|
|note|取引に関するメモ|
|customer_id|顧客ID。customer_card_idと一緒に使用|
|billing_address|請求先住所|
|shipping_address|配送先住所|
|buyer_email_address|購入者のメールアドレス|
|order_id|別途作成できる注文データのID|
|additional_recipients|追加の注文者|

これらは JSON に対するキーとして指定します。

```javascript
body.card_nonce = 'aaavvvv';
```

## 普通のJSONでもOKです

なお、 `SquareConnect.ChargeRequest.constructFromObject` を使うと単なるオブジェクトからChargeRequestに使える形式に変換してくれます。例えば数値から文字列にするなど、エラーが発生しないように変換ができます。

```javascript
const body = SquareConnect.ChargeRequest.constructFromObject({
  idempotency_key: 100,
  amount_money: {
    amount: 100,
    currency: 'JPY'
  }
});
```

この場合、本来 idempotency_key は文字列でないといけないので、自動で変換されます。入力チェックの目的で使っても良さそうです。

```json
{
  "idempotency_key": "100",
  "amount_money": {
    "amount": 100,
    "currency": "JPY"
  }
}
```

constructFromObject はすべてのWeb APIモデルに対して用意されています。

----

Square Connect Node SDKはまだできたばかりで、これから機能追加が行われていきます。ぜひ使ってみて、分からないところがあれば[Squareのエラー・バグ・問題の解決方法｜teratail](https://teratail.com/tags/Square)へお寄せください！
10.2 Release 2 で製品登録の画面がシンプルになった

[RAD Studio / Delphi / C++Builder 10.2 Tokyo Release 2 が公開](https://community.embarcadero.com/blogs/entry/rad-studio-10-2-2-released-today)されましたね。
インストーラが改良され、ライセンスの製品登録の画面がシンプルになっています。

![inst001.png](https://qiita-image-store.s3.amazonaws.com/0/164551/e74cfa52-868e-e2ec-20c5-aed61829f99d.png)

が...これは誤解を受けるぞ (多分翻訳ミス) という箇所があるので補足
「名前と電子メール」の箇所、ここに入力するものは
<font color=red>EDN (Embarcadero Developer Network) のログイン名、または電子メールアドレス</font>
です。(ログイン名または電子メールが正しいと思うな）

パスワードには、EDNのアカウントの登録時に設定したパスワードを入力します。

ご注意くださいませ（特に初めてインストールする方）

## 10.2.3 で修正されました

<img width="401" alt="esdInst04.png" src="https://qiita-image-store.s3.amazonaws.com/0/164551/5fa2244c-66b6-d527-3096-c136b6ed2da4.png">
サーバーとは？(種類と説明)


サーバーがよく分からないので、
勉強した内容をまとめようとおもう。(わすれちゃうから・・)

サーバーとは、<font color="Chocolate">クライアント(顧客?)と呼ばれるPCやスマホなどの端末からのリクエスト(要求)に対応して、自身が所持している情報を提供するコンピューター</font>のことを指す。

まずサーバーはインターネットに自作webサイトを公開するときに借りたりするもので、
いろんな種類がある。
・レンタルサーバー
　ー共用サーバーともいい、サーバーを貸し出ししてくれる。以下がサーバーの種類である。

・共有サーバー
　ー1台のサーバーを複数人のユーザーで共有して利用するサービス。比較的安価であるが、ユーザーが任意で設定を変更できなかったり、負荷の高い処理をしているユーザーがいたら、同じサーバーを利用している人にも影響がでる。

・専用サーバー
　ー特定のユーザーが1台のサーバーを占有して使用できるサービス。共有サーバーと比べスペックが高く、サーバーのOS、サーバーの設定、インストールソフトなどを自由に変更できることが大きなメリットとなる。しかしそれ故に専門知識も必要となり、値段も共有サーバーにくらべて高い。

・VPSサーバー
　ー仮想専用サーバーともいい、共有サーバと専用サーバの組み合わせみたいなサーバーである、１台のサーバーの中でユーザーごとに領域を区切りあたかも専用サーバーのように提供される。

・クラウドサーバー
　ーVPSみたいなサーバーだが状況に応じて柔軟に利用するスペックを変更できるので、VPSよりも有能?(比較的新しいみたい)


なんかおもっていたより、種類があってびっくりした。


今後(自分が)使いそうなサーバーをのせておく。
さくらインターネット : 
https://www.sakura.ne.jp
AWS : 
https://aws.amazon.com/jp/pricing/
引用
https://www.kagoya.jp/howto/rentalserver/basic-01/
matplotlibで複数のfigureを一つのpdfに保存する

# 内容
タイトル通りですが、複数のfigureをまとめて一つのpdfに保存するやり方です。

# やり方
```py3
from matplotlib.backends.backend_pdf import PdfPages

# ファイルを開く
pdf = PdfPages('test.pdf')

# 保存 (current figure)
pdf.savefig()

#　閉じる
pdf.close()
```
# サンプル1 : 個別に保存
```py3
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages

x  = np.linspace(0, 2 * np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)

pdf = PdfPages('test.pdf')

plt.figure()
plt.plot(x, y1)
pdf.savefig()

plt.figure()
plt.plot(x, y2)
pdf.savefig()

pdf.close()

```
# サンプル2 : 開いているfigureを一括保存
```python3
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages

x  = np.linspace(0, 2 * np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)

plt.figure()
plt.plot(x, y1)

plt.figure()
plt.plot(x, y2)

pdf = PdfPages('test2.pdf')

fignums = plt.get_fignums()
for fignum in fignums:
    plt.figure(fignum)
    pdf.savefig()
    
pdf.close()
```
【UITableView】ページング処理のため残りの cell の数を取得する

`UITableView` である程度スクロールしてある程度下端に近づいたら、追加でコンテンツを取得したい、という場合があるとおもいます。いわゆるページング処理です。
そんなときにこんな extension があると簡単にイベントを捕まえることができます。

```swift:UITableView+.swift
extension UITableView {
    // 与えられたindexPathの下部のセルの数を返す
    func belowCellsCount(cellIndexPath: IndexPath) -> Int {
        // 全てのセルの数
        let allCellsCount = Array(0 ..< self.numberOfSections).reduce(0) { (sum, sectionIndex) -> Int in
            return sum + numberOfRows(inSection: sectionIndex)
        }
        // `cellIndexPath`の上部のセクションのすべてのセルの数
        let cellsInAboveSectionCount = Array(0 ..< cellIndexPath.section).reduce(0) { (sum, sectionIndex) -> Int in
            return sum + self.numberOfRows(inSection: sectionIndex)
        }
        return allCellsCount - cellsInAboveSectionCount - cellIndexPath.row
    }
}
```

こんな感じで使えます。

```swift:ListViewController.swift
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if tableView.belowCellsCount(cellIndexPath: indexPath) < 6 {
        // 残りのセル数が6を下回った
        // 追加のコンテンツ取得処理
        self.viewModel.fetchList()
    }
}
```

`contentOffset` を取得して `contentSize` を比べることでも似たようなことができますが、デバイスごとにセルのサイズが変わったりする場合に使い勝手が変わってきます。セルの数でページングする方が確実だと思います。
同じ extension を `UICollectionView` にも実装すると、`UICollectionView` でも同じことが可能です。
VARとVARP、STDEVとSTDEVPの違い

逆に理解していたので、備忘録（Excelだけでなく、スプレッドシートも同様）。

![スクリーンショット 2017-12-14 14.15.51.png](https://qiita-image-store.s3.amazonaws.com/0/75329/0167fc26-b52d-df90-edda-040fc692a310.png)


# VAR（VAR.S） と VARP（VAR.P）

VAR（VAR.S）は、対象にしたデータが標本のときの分散（**不偏分散**）。
VARP（VAR.P）は、対象にしたデータが母集団のときの分散。

:warning: Pつく方が不偏分散ではない。（n-1 するのは VAR 及び VAR.S）

# STDEV（STDEV.S） と STDEVP（STDEV.P）

STDEV（STDEV.S）は、対象にしたデータが標本のときの標準偏差（**標本標準偏差**）。
STDEVP（STDEV.P）は、対象にしたデータが母集団のときの標準偏差。

:warning: Pがつくほうが標本標準偏差ではない（n-1する不偏分散の平方根は、STDEV 及び STDEV.S）
MeCabを使って、テキスト中に含まれる品詞をカウントしてみよう！

## 概要
このエントリは、自然言語処理の基礎を学ぶためのものです。
画像処理では画像を扱い、音声処理では音を扱いますが、自然言語処理ではテキストが対象となります。
テキストをコンピュータで処理していきたいのですが、その前段階としてテキストを部分ごとに区切らなければいけません。
テキストを部分ごとに区切る作業を形態素解析といい、それをするためにはMeCabという形態素解析エンジンを使います。
今回はMeCabを触ってみたいと思います。

## インストール
Mecab のインストールには[こちら](https://qiita.com/grachro/items/4fbc9bf8174c5abb7bdd)をご参考ください

## MeCabで遊んでみる
parseToNode()というメソッドで、最初のnodeを取得します。
node.nextをすることによって次のnodeに移ることができます。
nodeのsurfaceには語が、featureには特徴が入っています。
例えば、バナナという単語であれば以下のようになります。
```node.surface = "バナナ"```
```node.feature = "名詞,一般,*,*,*,*,バナナ,バナナ,バナナ"```


```mecab_test.py
import MeCab

text = "私はバナナが好きです。"

mecabTagger = MeCab.Tagger("-Ochasen")
node = mecabTagger.parseToNode(text)
while node:
    word = node.surface
    hinshi = node.feature.split(",")[0]
    print(word+": "+hinshi)
    node = node.next
```

```
私: 名詞
は: 助詞
バナナ: 名詞
が: 助詞
好き: 名詞
です: 助動詞
。: 記号
```

## MeCabで品詞をカウントする
node.feature中の１番左の部分に品詞の情報が格納されています。
辞書型のデータ構造をうまく使い、品詞をカウントしていきましょう。

```mecab_hinshi_test.py
# coding: utf-8
import MeCab

text = "私の好きな果物はバナナです。"

mecabTagger = MeCab.Tagger("-Ochasen")
node = mecabTagger.parseToNode(text)
hcount = {}
while node:
    hinshi = node.feature.split(",")[0]
    if hinshi in hcount.keys():
        freq = hcount[hinshi]
        hcount[hinshi] = freq + 1
    else:
        hcount[hinshi] = 1
    node = node.next
for key,value in hcount.items():
    print(key+":"+str(value))
```

```
名詞:4
助詞:2
記号:1
助動詞:2
```
aws-cliにて、複数の認証情報を使い分けたい場合の設定方法

# aws-cliのprofile機能

## 複数アカウントを利用する際は危険

__複数案件__をこなしていると、`aws-cli`にて__複数のアカウント情報__を取り扱うことが出てくると思います。

その際に、__各認証情報__を__正確に区別__する必要があり、間違って別の認証情報を使ってAWSサービスを操作してしまうと__<font color="red">大問題</font>__になってしまします。

## cliでの基本的な認証処理

`aws-cli`を使う場合、ホーム直下の`.aws`ディレクトリにある認証情報は`.config`ファイルと`.creadincails`ファイルに記載します。

```shell:directory
~
└── .aws
    ├── .config
    └── .credentials
```

上記ファイルは、`aws configure` コマンドで作成するも良いですし、__物理的__にファイルを作成してもどちらでも問題ありません。

__実行ユーザー__の`~/.aws/`内の上記ファイルを利用して認証処理を行います。

__記載内容__は以下が基本です。

```ini:.config
[default]
output = json
region = {リージョン}
```

```ini:.credentials
[default]
aws_access_key_id = {アクセスキー}
aws_secret_access_key = {シークレットキー}
```

## 認証情報の複数管理方法

`aws-cli`にはこのようなケースを考えて、__profile機能__があります。

### profile機能を知らなかった僕

以下のように__各ファイル__を管理し、

```shell:directory
~
└── .aws
    ├── .config.hoge
    ├── .credentials.hoge
    ├── .config.fuga
    └── .credentials.fuga
```

__cpコマンド__で都度コピーし

```shell:command
cp ~/.aws/.config.hoge ~/.aws/.config
cp ~/.aws/.credentials.hoge ~/.aws/.credentials
```

作業が終わったら__rmコマンド__で消していました。。。。(お恥ずかしい・・・__orz__)

```shell:command
rm  ~/.aws/.config
rm  ~/.aws/.credentials
```

### profile機能を知った僕

ディレクトリとしては、各ファイル(config/credentials)を__それぞれ一つずつ__管理します。

```shell:directory
~
└── .aws
    ├── .config
    └── .credentials
```

その上で、以下のようにセクションを__各認証情報毎__に分けて、各情報を記述します。

```ini:.config
[profile hoge]
output = json
region = {リージョン}

[profile fuga]
output = json
region = {リージョン}

[default]
output = json
region = {リージョン}

```

```ini:.credentials
[hoge]
aws_access_key_id = {アクセスキー}
aws_secret_access_key = {シークレットキー}

[fuga]
aws_access_key_id = {アクセスキー}
aws_secret_access_key = {シークレットキー}

[default]
aws_access_key_id = {アクセスキー}
aws_secret_access_key = {シークレットキー}
```

上記のように__.config__では`[profile {profile}]`、__.credentials__では`[{profile}]`のように__セクション(profile)__指定します。

その上で、__コマンド実行時__に

```shell:command
aws ~~~ --profile ${profile}
```

と`--profile`オプションで__セクション(profile)__を指定することで、各ファイルに指定した__セクション(profile)__毎の設定を利用して操作をしてくれます。

しゅごい。

ちなみに、`--profile`オプションをつけ忘れると、__[default]セクション(profile)__の設定が利用されるので、複数の認証情報を扱い場合は__defaultセクション__は__<font color="red">指定せず</font>__、__必ず--profileで意図的に指定する__運用にした方が良いかと思われます！
aws ec2で、pythonスクリプトを定期自動実行するまで

#はじめに
pythonで書いたスクリプトを、定期実行したかったのでサーバ上に動くようにしました。スクリプトの内容はスクレイピングとブログに自動投稿です。毎日一回だけなので、最初は手動でやっていましたが、勉強も兼ねてaws ec2を借りて動かしてみました。初めてのクラウド体験。

#EC2インスタンスを起動まで
EC2インスタンスを作成するには[この記事](http://tech.lexues.co.jp/archives/1668)を参照すると良いと思います。無料枠で作成する場合は、設定なども参考になると思います。AWS側も丁寧に誘導してくれるので、そこに乗っかればいけました。

#ec2インスタンスを作成した後
インスタンス上でpythonスクリプトを動かすのに行うことは、以下のことです。

1. サーバにSSHでログイン
2. サーバ上にpythonをインストール、仮想環境（venv）を作成
3. ローカル開発環境にあるファイルやライブラリをサーバ上に同期
4. スクリプトを定期実行するために、サーバ上のcronの設定

以上の作業でローカルにあるpythonスクリプトを、ec2インスタンス上で自動実行することができました。
それぞれ方法を見ていきましょう。

## サーバにSSHでログイン

```
~/.ssh/config内
Host ec2:
 HostName <インスタンスのIPアドレス>
 User ubuntu
 IdentiFile <ダウンロードしたキーペア名.pemへのパス>

```
と`~/.ssh/config`内に記述して、以下のコマンドでログインできます。

```
ssh ec2
```


## サーバ上にpythonをインストール、仮想環境（venv）を作成
サーバ上にpythonとvenvをインストール/作成しましょう。

```
sudo apt-get install -y python3 python3.4-venv
python3 -V
python3 -m venv sample  仮想環境作成
. sample/bin/active 仮想環境に入る
```

## ローカル開発環境にあるファイルやライブラリをサーバ上に同期
ローカルのファイルをサーバ上に同期するにはいくつか方法があると思いますが、今回は`rsync`を使用します。

```
rsync -av <ファイル>　ec2:パス
```
後は同期するファイルをこのコマンドで叩けば良いだけです。

同期するのは、ライブラリ集である`pip freeze`と`実行するスクリプト`です。前者は以下のようにテキストファイル化すると良いと思います。

```
pip freeze > requirements.txt 
```

## スクリプトを定期実行するために、サーバ上のcronの設定
サーバ上で自動実行を行うためにはcronを設定します。そのためには`/etc/crontab`を編集しましょう。殆どがコメントになっていると思いますが、自動実行する時刻とコマンドをここに書くことで実装できます。

設定するには、左から分、時、日、月、曜日、ユーザ、コマンド内容の順番で記載していきます。以下の例は、毎日22時42分にコマンドを実行する例です。
また、実行するコマンドは分かりやすくシェルスクリプトにまとめてますが、まとめなくても大丈夫かもしれません。

```
# m h dom mon dow user  command
42 22   * * *   ubuntu  /home/ubuntu/run_script.sh > /tmp/run_script.log 2>&1
```

これでサーバ上で定期自動実行できました。

#終わりに
awsの無料枠というのはec2起動時間が月に750時間までらしいです。なので一つのインスタンスを月にずっと起動してたら730時間なので、それだけで埋まってしまいます。
日に一度のみの定期実行したいだけならば、他の方法があると思うので調べてます。
`aws lambda`がそれっぽい。
Kotlin入門 クラス

KotlinはJVM言語なので、Javaと同じようにクラスを使えます。
Javaよりもかなり綺麗に書けるので見ていきましょう。

# そもそもクラスとは
クラスとはデータの組み立て設計書見たいなものです。
例えば「人」の設計書を書くとき、中に
 * 年齢
 * 身長
 * 体重
 * 性別
などの変数や
 * 歩く
 * 寝る
 * 食べる
などの動きがあると思います。

KotlinやほかのJVM言語ではこのまとまりを**クラス**と呼びます。
クラスには変数やメソッドと呼ばれる動きを実装できます。

# Kotlinでクラス
クラスの基本形はこんな感じです。

```
class クラス名(コンストラクタ){
  fun メソッド名(引数) {
    ...
  }
}
```

実際に「**Person**」という上の例で書いたようなクラスを書いてみます。
**Person**には
変数に
 * 年齢(age)
 * 身長(height)
メソッドに
 * 歩く(walk)
 * 寝る(sleep)

```kotlin
class Person(var age: Int, var height: Double){
  var walk_distance: Int = 0
  fun walk(){
    walk_distance += 10
    println(walk_distance + "m歩いた")
  }
}
```

実際にこのクラスを使ってみると

```kotlin
val hoge = Person(24, 170.0)

println(hoge.age) // ”24”と出力される
println(hoge.height) // "170.0"と出力される

hoge.age += 1 // "age"に1を足す
println(hoge.age) // "25"と出力される

hoge.walk() // "10m歩いたと出力される"
hoge.walk() // "20m歩いたと出力される"
```

このようなことが出きるようになります。

# 参考
[JavaDrive](https://www.javadrive.jp/start/about/index1.html)
Google HomeとジャルジャルのM-1のネタ再現してみた

# はじめに
この記事は クソアプリ Advent Calendar 2017 14日目の記事です。

普段は営業職をしていてAdvent CalendarはたまにTwitterで流れてくる記事を眺めるくらいだったのですが、今回作ったものを見せたところ[kon_yu](https://qiita.com/kon_yu)さんにぜひ投稿すべきと言われたので初参戦です。

# 作ったもの
Google Home上で遊べるジャルジャルのピンポンパンゲーム
実際に遊んでいる様子（画像クリックでデモ動画に飛びます)

[![こちら](https://qiita-image-store.s3.amazonaws.com/0/42911/cdba8fc9-fdbc-17ff-ff8b-6808f70680fb.png "Google Home上で遊べるジャルジャルのピンポンパンゲーム")](https://youtu.be/5vSHJp0BY4I)

# なぜ作ったの
今年のM-1グランプリの決勝戦で[ジャルジャルの変な校内放送のネタ](https://youtu.be/FccPXLYNlyA)をみて、その斬新な構成に驚きました。

しばらくは周りの人とピンポンパンゲームを真似して楽しんでいたのですが、それからしばらくしてActions on Google(のDialogflow)というものを使えばGoogle Homeで簡単にいろいろなことを言わせることができるという記事がTwitterで流れてきましました。

参考:[Actions on Googleでapi.aiを使ってGoogle Homeに何か言わせてみる](https://qiita.com/syarihu/items/53ea1a65f481f8121109)

これを見て自分の中でブームが来ていたジャルジャルのネタとActions on Googleを組み合わせれば、Google Homeとネタができるやん！と思った次第です。

# すごいところ/ちょっと手こずったところ
ジャルジャルのネタの途中で「ファミレス行ってピンポン押して店員さん呼んでハンバーグ定食頼んでパンかライスか聞かれてるやん！」という長台詞があるのですが、Googleの音声認識ではほぼ完璧に認識できていました。

<img src="https://qiita-image-store.s3.amazonaws.com/0/42911/e593eaab-f573-ecef-47ad-36373271a484.jpeg" width=50%>

一方でピンポンパーンといった擬音、特に今回のネタのように作られた擬音は、音声認識されてもひらがなで認識されてしまって、カタカナで設定したInputがうまくトリガーされないといったことが起こりました。これに関してはひらがなでInputのトリガーを設定してしまうという力技で解決しました。

# 製作時間
4時間(ネタの分析 + 開発)

# まとめ
今回は思いついたアイデアをすぐに形にできて、営業やってるような自分でも作れてしまうのはDialogflowすごいなと感じました。

こういう下らないものをゆる〜く一緒に作る趣味仲間も募集していますので、なんか作ろうぜ！って方はぜひTwitterかなにかでご連絡いただけると嬉しいです。
GoogleOptimizeを使って無料で楽々ABテスト

# GoogleOptimizeとは

Google Optimizeとは、Google Analytics 360 suiteの製品シリーズの内の一つの無償版で、2017年3月30日から正式版に移行し、誰でも無料で利用が出来るようになっています。


# 設定手順
設定手順はざっくりとこんな感じです。

1. アカウントとユーザーの管理
2. テストの作成
3. Googleアナリティクスへのリンク
4. オプティマイズプラグインのインストール
5. テスト開始

## 1. アカウントとユーザーの管理

[GoogleOptimize公式サイト](https://optimize.google.com/optimize/home/#/accounts/1931987521/containers/7756485)にアクセスして、利用を開始します。
<img width="750" alt="アカウント_-_オプティマイズ.png" src="https://qiita-image-store.s3.amazonaws.com/0/2781/1aab90e1-54ce-b51a-23ba-e73f95b6ddb7.png">

## 2. テストの作成
テストの作成ボタンをクリックして、テストの名前・エディタページのURL・テストのタイプを選択します。

<img width="616" alt="コンテナ___ウェブテスト_-_オプティマイズ.png" src="https://qiita-image-store.s3.amazonaws.com/0/2781/cd751866-0fe2-5f55-e3ce-2afe1b8b295c.png">

### 2-1 パターンの作成
テストのパターンを作成しましょう

<img width="944" alt="sampleテスト___詳細_-_オプティマイズ.png" src="https://qiita-image-store.s3.amazonaws.com/0/2781/2a7e0015-6b4d-433f-63da-3d08927da5ad.png">

ビューを切り替えられ、それぞれにCSS等を設定できます。
<img width="1287" alt="人間万事塞翁が馬___まちづくりとか技術とか子育てとか.png" src="https://qiita-image-store.s3.amazonaws.com/0/2781/2caaad0c-8d66-502c-c07c-6b019e415106.png">

### 2-2. 目標の設定
テスト目標を設定します。ここは、GoogleAnalyticsと紐付けられるので、イベントトラッキングなどを設定すると良いです。
<img width="565" alt="sampleテスト___詳細_-_オプティマイズ.png" src="https://qiita-image-store.s3.amazonaws.com/0/2781/f6c1cc7b-d8f4-0c47-bd41-06474e0b0c54.png">

### 2-3. ターゲットの設定
各パターンの割合や評価のタイミングや条件を細かく設定していきます。
<img width="896" alt="sampleテスト___詳細_-_オプティマイズ.png" src="https://qiita-image-store.s3.amazonaws.com/0/2781/ff1cb7ff-9286-1c82-5143-1972fe39f2a2.png">

## 3. Googleアナリティクスへのリンク
Googleアナリティクスへとリンクする必要があるので対応するプロパティを選択します。

<img width="615" alt="コンテナ___ウェブテスト_-_オプティマイズ.png" src="https://qiita-image-store.s3.amazonaws.com/0/2781/9fb12350-cfa0-7bca-a959-502936dbf31a.png">

## 4. オプティマイズプラグインのインストール
説明に沿って、以下のようなタグをAnalyticsのタグの近くに入れます。

```javascript
 ga('require', 'GTM-XXXXXX');
```

## 5. テスト開始
ここまで設定できればテスト開始して結果を見守るだけです。
一度テストを開始してしまうと内容は変更できないので、しっかり確認してから開始しましょう。
無料版では1度に３テストまでできます。

## レポート
しばらくするとこんな感じでレポートが見れるようになります。
<img width="889" alt="ショップ関連フッターメニューテスト___レポート_-_オプティマイズ.png" src="https://qiita-image-store.s3.amazonaws.com/0/2781/db8cb702-1112-bd0e-645e-febd24da7411.png">


## まとめ
こんなに簡単に無料でABテストができるなんて、、いい時代になりましたね。。
Pythonで画像ファイルをパワポに貼る

# 内容
タイトル通りディレクトリにある複数の画像をパワポに自動で貼るプログラムです。

# プログラム
```py3
from pptx import Presentation
from glob import glob

# Presentationインスタンスの作成
ppt = Presentation()
# 幅
width = ppt.slide_width
# 高さ
height = ppt.slide_height

# レイアウト, 6番は白紙
blank_slide_layout = ppt.slide_layouts[6]

# 画像ファイルの読み込み
fnms = glob('./figure/*.png')

# ファイル毎にループ
for fnm in fnms:
    # 白紙のスライドの追加
    slide = ppt.slides.add_slide(blank_slide_layout)
    
    # 画像の挿入
    pic = slide.shapes.add_picture(fnm, 0, 0)

    # 中心に移動
    pic.left = int( ( width  - pic.width  ) / 2 )
    pic.top  = int( ( height - pic.height ) / 2 )

# 名前をつけて保存
ppt.save('figure.pptx')
```
# おまけ
上のやり方だと連番のファイル名の順番がバラバラになるので、数字順にソートするやり方です。もっといいやり方があると思うので教えてほしいです...。

```py3
import re

# 文字列から数値だけを取り出す
def str2int(str):
    i = int( re.search('\d+',str).group() )
    return i

# ファイルの読み込み
fnms = glob('./figure/*.png')
# ソート
fnms.sort(key=str2int)
```
rebar3 uncaught errorについて

# 問題
rebar3でコマンドを実行する時に

```
===> Uncaught error in rebar_core. Run with DEBUG=1 to see stacktrace or consult rebar3.crashdump
```
が出ました。　解決してみました。

## 細かいバックグラウンド
0. Macを使ってます
1. チームメンバーのgitレポをクローンしてrebar3を使ってました、特に問題なかった（xref, dialyzerなど）
2. ```./rebar3 pkgs```でパッケージングしてみたところ、バグった
3. エラーを見て環境変数関連のエラーメッセージがあった```error:/User/先輩/のファイル/が欲しい```
4. 推測：rebar3をビルドする環境（依存するファイルなど）が変わったので、怒られたのでは
5. 対策：自分でビルドしてpkgさせます
6. 現在ここ：オフィシャルのgitレポから最新のレポ3.4.7をクローンして、ビルドして、```./rebar3 clean```を実行しようとするところ、上記なエラーが出ました

# TL;DR
- ローカルでビルドしたrebar3のバージョンが```3.4.7+build.3966.refbXXXXXXX```です
- オフィシャルサイトのバイナリーのバージョンが```3.4.7```です
- 依存するappの中にバージョンが```X.X.X```という文字なしのvsnを想定するappがあります
- オフィシャルサイトのバイナリーを使えばエラーを解消できます

# 詳しいデバッグ手順
まず

```
DEBUG=1 ./rebar3 clean
```
でスタックトレースを拝見します

``` erlang
===> Evaluating config script "/WORKINGDIR/_build/default/lib/hackney/rebar.config.script"
===> Uncaught error in rebar_core. Run with DEBUG=1 to see stacktrace or consult rebar3.crashdump
===> Uncaught error: {badmatch,
                             {error,
                              {40,file,
                               {error,
                                {badmatch,
                                 ["3","4","7+build","3966","refbXXXXXXX"]},
                                [{erl_eval,expr,3,[]}]}}}}
```
全く原因がわからないのでグーグル先生に聞いたところ、この[イシュー](https://github.com/erlang/rebar3/issues/1253)を見つけました。中に依存するappのrebar.config.scriptに問題がありと説明し、ワークアラウンドも載っています。
今回エラーが出たのはhackneyのrebar.config.scriptです。

```erlang
IsRebar3 = case application:get_key(rebar, vsn) of
               {ok, VSN} ->
                   [VSN1 | _] = string:tokens(VSN, "-"),
                   [Maj, Min, Patch] = string:tokens(VSN1, "."),
                   (list_to_integer(Maj) >= 3);
               undefined ->
                   false
           end
...
```
ここで```string:tokens/2```で<font color="LightSalmon">三つ</font>のtermをMaj、Min、Patchを通して取り出そうとしています。
しかしローカルでビルドしたrebar3のバージョンが、、、、
まずrebar3のバージョンを確認しましょう

```
./rebar3 report
Rebar3 report
 version 3.4.7+build.3966.refbXXXXXXX
 generated at 2017-12-14T04:35:25+00:00
...
```
このvsnに```string:tokens```を適用すると```["3","4","7+build","3966","refb7c021b3"]```、<font color="LightSalmon">五つ</font>のtermを含むリストが帰ってきます。なので```badmatch```になります。
イシューではrebar.config.scriptを修正することでワークアラウンドするようと提案しましたが、一々問題のあるscriptを修正するのがキリがないなあと感じ、大人しくオフィシャルサイトのバイナリーを使うことにしました。

オフィシャルサイトのバイナリーで```./rebar3 report```を実行してみると

```
./rebar3 report
Rebar3 report
 version 3.4.7
 generated at 2017-12-14T03:07:34+00:00
```
バッチリです、rebar3のコマンドも無事実行できました。```/rebar3 pkg```も実行できるようになりました。
cvsのプロジェクトをgitに変換する


Ubuntuで実施しました。公式のドキュメントがWarningだらけなので、色々心配なのですが、古いプロジェクトを救出する一手段としては有効かと思います。変更履歴が重要でなければ `cvs export` の方がベターかもしれません。

```
sudo apt install git-cvs
cvsps --version # 2.0系が入ってることを確認
mkdir project && cd project
git cvsimport -v -d /path/to/repos/ project
```

`/path/to/repos/` が、CVSROOTがあるディレクトリで、 `project` はその直下のサブディレクトリを指定します。実行すると、カレントディレクトリにリポジトリを生成する点に注意してください。今回はファイルの取り出しはできたものの、コミットログが文字化けして読めませんでした（結局、.gitを消して最新の状態だけ保存することにしたのでこれ以上の調査はせず）。

https://git-scm.com/docs/git-cvsimport