OmniAICreator/Qiita-1.07M huggingface dataset:
JPEGファイルのプログレッシブ判定

#まえがき
プログレッシブJPEGが読めない端末(ガラケー時代の端末です)に対応するため、Gitの全ファイルをスキャンすることにした…のはいいんですが、既存の方法だと自動化に不向き or 判定上はセーフだけど読めない謎JPEGがある 等の理由でこれだっ！って物がなかったので自作することに

#しくみ
さらりと調べた結果、SOFヘッダ部に画像のスキャンモードが格納されていることがわかりました
(参考：http://www.setsuki.com/hsp/ext/jpg.htm)
なので楽観的にプログレッシブフレームが存在するかどうか、つまりJPEGファイル中に0xFFC2が存在するかどうかで判定をすることにしました
本来はちゃんと検出位置がSOFヘッダなのかどうか考慮しなければいけないハズですが、今のところ誤検出がないので改修してません
また、ベースラインとプログレッシブ以外にもシーケンシャル、ロスレスとありますが今回はこの二つはそもそも使わないだろうという事で対象外としています

#Source
https://github.com/fumitti/JpegProgressiveChecker

```csharp
        private const int Bufsize = 4096;//?
        static async Task<bool> IsJpegProgressive(string filePath)
        {
            using (var stream = File.OpenRead(filePath))
            {
                var sofFlag = false;
                byte[] buf = new byte[Bufsize];
                while (true)
                {
                    var read = await stream.ReadAsync(buf, 0, Bufsize);
                    foreach (var b in buf)
                    {
                        if (sofFlag)
                        {
                            if (b == 0xC2)
                                return true;
                            sofFlag = false;
                        }
                        if (b == 0xFF)
                            sofFlag = true;
                    }
                    if (read <= 0)
                        break;
                };
            }
            return false;
        }
```
C#初心者な頃にゴリ押しで書いたので汚いです(言い訳)

あとはこれをGithub連携させたJenkinsでキックさせ、もし引っかかったらSlackに通知する運用をしています
ホントは変換までしてもよかったんですが~~めんどくさい~~技量不足故断念
Angular RouterアプリケーションをAzure Web Appsにデプロイして動かす

# 背景
## Angular Routerとは
Angular2からリリースされた機能で、アプリケーションの状態を宣言的に特定することができ、コンポーネントとURLがリンクされる。Single Page Applicationでありながら通常のWebページと同様に特定のWebページに直接アクセスすることもできる。

## やりたいこと
ng serveやnpm startでローカル開発したものAzure App ServiceのWeb Appsにデプロイして公開したい。

# 問題
ローカルの開発環境では問題なくルーティングできているのに、Web Appsにデプロイすると以下のような挙動になってしまう。

- F5でリロードした時に"The resource you are looking for has been removed, had its name changed, or is temporarily unavailable."という404的なメッセージが表示される。
- 特定のコンポーネント（にリンクされたページURL）を直接表示しようとすると、やはり上記の404的なメッセージが表示される。

# 対応
## web.configに設定追加
アプリケーションroot直下のweb.configファイルに以下設定を追加することでローカルと同様の挙動となることを確認できた。

```
<configuration>
    <system.webServer>
        <rewrite>
          <rules>
            ...省略...

            <rule name="Index Rule" stopProcessing="true">
                <match url=".*" />
                <conditions logicalGrouping="MatchAll">
                    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                </conditions>
                <action type="Rewrite" url="/index.html" />
            </rule>

            ...省略...
            </rules>
        </rewrite>
    </system.webServer>
    ...省略...
</configuration>
```

Azureに限らず普通にIISにデプロイする場合や、他のPaaSにデプロイする場合でも同様のことが起こるかもしれないが、試していない。
どなたか分かる方がいれば教えてください。
App Maker 2017年の個人的な総括

App Maker を仕事でもそれなりに関わっていて@howdy39が何をしたのかとか、App Makerについて思うこととか雑に書いていきます。

そもそも App Maker ってなに？という人は、以下の記事を参照してください。
[Google App Maker とは？ 短期間で Web アプリケーション構築を可能にした理由](https://www.topgate.co.jp/what-is-google-app-maker)


# いつから始めたのか
2017年7月ぐらい。
なんか新しいことやるか、どうせやるなら誰もやってないのがいいな。
と思って存在は知っていたけど触ってなかった App Maker に決めた。

会社の Slack に App Maker チャンネルが既にあったのでそこにjoin。
完全に寂れてて数ヶ月投稿がない感じだったけど今は筆者がそれなりに投稿してる感じ。


# 勉強
日本語の情報はまったくないので[公式のドキュメント・リファレンス](https://developers.google.com/appmaker/)と[公式のサンプル](https://developers.google.com/appmaker/samples/)を読んだり。

たまに Stack Overflow に助けられた。
[Recently Active 'appmaker' Questions - Stack Overflow](https://stackoverflow.com/questions/tagged/appmaker)


# 社内で導入
いくつかアプリを作って実際に運用している。
このあたりの話は会社のブログに書こうかなと思っている。


# トレーニング
会社で GCP のトレーニングをやっているが、それとは別で App Maker のトレーニングもやろうという話が持ち上がり、結構なボリュームの資料作りをした。
すでに数社様でやっていて実績があったりする。（評判はとても良い感じでうれしい）


# 登壇/LT
[G Suite ユーザー会](http://gsuiteusers.jp/)という G Suite を利用している企業が情報交換したりするコミュニティがあるんだけど、
9月のユーザー会では Google 本社で App Maker について LT をした。

12月に App Maker 分科会があってそこでも何かする予定。
分科会は速攻で枠が埋まったみたいで需要は結構あるみたい。



# Qiita
[GoogleAppMaker](https://qiita.com/tags/GoogleAppMaker/likes) のタグを作っていくつか投稿した。
※タグを AppMaker にしなかったのは [mozilla-appmaker/appmaker](https://github.com/mozilla-appmaker/appmaker) というのがすでにあったのと、これから同じ名前でなにか出てきたら面倒になりそうだからという理由で`Google`を頭につけた。

最近あげてないのは飽きたのではなく別件に追われているから。これからもあげていく予定。


# 感想とか
## GAS はどうなる？
GAS はなくならないしこれからも使われ続ける！

App Maker は GAS にマテリアルデザインの画面をつけたものであるけど、 GAS を置き換えるものではないし上位互換でもない。
Web 画面からしか操作ができないので（GAS の Execution API や Webアプリケーションとして導入 がない） GAS より使い勝手悪い、というところもある。

また、GAS は個人の Gmail でもつかえるけど、 App Maker は G Suite Business 以上という制限がある。
これは個人的な推測だけど、制約が緩くなることはないと思う。

## App Maker を勉強する価値はある？
GAS より使える範囲が狭い（主に、G Suite Business 以上という制限と同一ドメインのユーザーでしか使えない点）が、Web 画面が簡単に用意できてちょっとした DB もついているので利用価値はそれなりにある。
社内で使うちょっとしたツールとかそういうレベルで活躍するものだと思う。

作ろうとしているものを `システム` と呼んだならそれは App Maker でやることじゃない可能性が高い。
`ツール` や `アプリ` と呼んだなら App Maker の出番かも。という感じ。

## EAP はいつ外れる？
2017年Q4予定らしいけどずれて来年になる気がする。
これからリリースしたら年末ゆっくり越せなくなるかもだし（Googleの人が）


# 来年やりたいこと
技術書典で本書こうかなーと思っているのだけどニッチ過ぎて需要があるのかが謎。
アマゾン・パブリッシングのが良いかもしれない・・・？
Nimble-SnapshotsでiOSアプリのViewをテストする

この記事は [Classi Advent Calendar 2017](https://qiita.com/advent-calendar/2017/classi) の2日目の記事です。

ClassiでiOSエンジニアをしている [@enomotok_](https://qiita.com/enomotok_) です。
Nimble-Snapshotsを使ってiOSアプリのViewのリグレッションテストを行う方法を紹介します。

# モチベーション
## アプリのリライト
Classiにはいくつかのアプリがあります。そのなかには、過去の経緯によりアプリの内部実装が好ましくなく、リライトを行なっているものがあります。見通しの悪いコードを少しずつ改善していくわけですが、ユニットテストが整備されておらず、そのまま手を入れるとデグレが発生する可能性があります。そこでViewのレイアウトが壊れていないことを確認するために、Nimble-Snapshotsを使ってOutside-Inのテストケースを用意することにしました。

# Nimble-Snapshots
[Nimble-Snapshots](https://github.com/ashfurrow/Nimble-Snapshots) は、 [Quick](https://github.com/Quick/Quick) のテストケースで使用するマッチャーで、Viewのスナップショットを取得したり、見た目が変化していないことをアサートすることができます。これはXCTest用に開発されたFacebook製の [FBSnapshotTestCase](https://github.com/facebookarchive/ios-snapshot-test-case) のラッパーです。

## なぜXCTestではなくQuickを使うのか
XCTestは非同期処理のテストを行うのが得意ではありません。 `UIViewController` のライフサイクルメソッドをコールし、非同期でWeb APIから取得した結果をViewに反映したのちに画面の見た目を検証する、といったユースケースにはQuickが適しています。Quickのマッチャーである [Nimble](https://github.com/Quick/Nimble) に用意された `toEventually()` メソッドを使うことで、タイムアウトが発生するか、成功するまで、アサーションをコード内で繰り返し実行することができます。

# 使用方法

導入は簡単です。CocoaPodsでQuick, Nimble, Nimble-Snapshotsをテストターゲットに追加します。

```Podfile
target 'SnapshotTestingSandbox' do
  use_frameworks!
  target 'SnapshotTestingSandboxTests' do
    inherit! :search_paths
    pod 'Quick'
    pod 'Nimble'
    pod 'Nimble-Snapshots'
  end
end
```

スナップショットはデフォルトの設定で `$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages` に保存されます。もし変更したければ、環境変数 `FB_REFERENCE_IMAGE_DIR` にパスを指定することで任意のディレクトリに取得したスナップショットを保存することができます。

# テストコードの書き方

テストコードを書きます。
最低限のサンプルは以下の通りです。

```ViewControllerTests.swift
final class ViewControllerSpec: QuickSpec {
    override func spec() {
        var sut: ViewController!
        describe("ViewController") {
            let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
            sut = storyboard.instantiateInitialViewController() as! ViewController

            it("view exists") {
                expect(sut).notTo(beNil())
                // スナップショットを取得
                //📷(sut)
                // 非同期でスナップショットがあることを確認
                expect(sut).toEventually(haveValidSnapshot())
            }
        }
    }
}
```

`📷(sut)`

スナップショットを取得するメソッドです。実行すると必ずテストは失敗します。

`expect(sut).toEventually(haveValidSnapshot())`

取得済みのスナップショットと、以前取得したスナップショットが等しいことを確認するアサーションです。一度テストを走らせ、 `📷 ()` メソッドを使ってスナップショットを取得してから、このメソッドに差し替えると良いでしょう。

# テストダブルについて
ViewControllerは起動時に他のオブジェクトを伴ったり、Web APIにアクセスした結果を表示するものがほとんどでしょう。ViewControllerのインスタンス化に必要なオブジェクトを一から生成するのは骨が折れる作業かもしれません。それらを別のもので肩代わりさせたい場合、テストダブルを用意したり、 [OHHTTPStubs](https://github.com/AliSoftware/OHHTTPStubs) を利用したりします。今回の記事では割愛します。

# サンプルコード

サンプルコードを下記のリポジトリで公開しています。
https://github.com/k-enomoto/SnapshotTestingSandbox

Objective-CでもSpecta, Expecta+Snapshotsの組み合わせで同様のテストを書くことができます。
https://github.com/k-enomoto/SnapshotTestingSandboxObjC

# 所感

インターネットを見回しても、iOSでOutside-Inのテストを書く知見は意外と共有されていない気がします。もし日常的にそのようなやり方で開発をしているよ、という方がいたら、是非とも色々教えていただきたいです。この記事に対する指摘も歓迎します。

# 最後に

Classiでは一緒に働くエンジニアを募集しています。
https://www.wantedly.com/companies/classi

明日は @cl-sawada さんです。
EC2 Spot InstanceでImmutable Infrastructureなdeploy手順

＃別blogから引っ越した2014/2/17の記事です。

話題の（？）Immutable Infrastructure にインフラ1年生がEC2 Spot Instance で挑んでみました。

いざTryしてみて社内に共有する資料を作ったのですが、せっかくなので公開しました。

http://www.slideshare.net/slideshow/embed_code/31283937

当社提供中のソーシャルゲーム「タワーオブドラゴン」はAWSで稼働しています。

ソーシャルゲームはその特性上、こんなケースが頻繁に発生します。

サービスを停止させること無くアプリケーションを更新する
突然のトラフィック増大に対応するためサーバを急きょ追加しスケールアウトする
大規模なアップデートを施すため一律更新済のサーバを展開する
EC2も常にオンデマンドで使っているとコストが嵩んでしまいます。

トラフィックが落ち着いている時は Reverse Proxy / Application Server の台数を絞ってコストを削減していますが、Load Balancer 配下の Reverse Proxy が余りにも少ない状態だと、ELBからの切り離し・切り戻しで残されたActive系に瞬間的な高負荷がかかるのか、HTTP500が返ってしまうことがあるようでした。

このため、deployする時だけELB配下のノードを増やすという間抜けな運用をしており、1deploy $1.2 みたいな貧乏性にはむず痒い状態になっていました。

 

このままではdeploy回数を減らすという、ある意味で正しい((オンラインのままでdeployすると、どうしても少数のエラーが起きてしまっているため))けど、守りに入った間違った状態に向かってしまう。

何かいい方法はないか考え、そういえば Spot Instance という手があると思いつきました。

これまで Spot Instance は存在や概要は知っていれど、入札だ強制停止だなんだと取っ付きにくく、使ったことがありませんでした。

 実際にやってみたらあっさり簡単でコストも圧縮できました。

ただし、いつ急激に価格が跳ね上がるかは予測できないため、

安全圏な入札価格に設定する
ELB配下に1台はオンデマンドなり非Spotなノードを置く 
など配慮は要りそうです。
SQL Server + .NET で Timeout expired. というエラーが出る

＃別blogから引っ越した2013/12/12の記事です。

いきなり技術記事ですが、この事象で日本語の記事がなかなか見つからなかったため、同じような問題に困っている方に向けて書き残しておこうと思います。

 

当社のインフラはAWSに Windows Server 2012 + .Net + SQL Serverを構築して動いていますが、一定の割合で下記のような例外が発生していました。

 

System.Data.SqlClient.SqlException (0x80131904): A transport-level error has occurred when receiving results from the server. (provider: TCP Provider, error: 0 - The semaphore timeout period has expired.) ---> System.ComponentModel.Win32Exception (0x80004005): The semaphore timeout period has expired

 

System.Data.SqlClient.SqlException (0x80131904): Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)

 

原因がわからず、Google先生にすがりついたところ、以下のAWSフォーラム投稿を発見しました。

 

[RDS + .Net]Semaphore timeout error when cnnecting to a db instance

https://forums.aws.amazon.com/message.jspa?messageID=470985

 

これによると、答えは以下の部分でした。

```some settings on the NIC
IPv4 checksum offload - disable
large receive offload - disable
large send offlaod - disable
tcp checksum offload - disable ```

英語に疎いものでなぜこうなのかをきちんと理解しきれていませんが、試してみたところ見事に掲題のエラーは収束することができました。

 

設定するにはコントロールパネルなどからネットワーク設定へ進み、イーサネットアダプタの詳細設定を開きます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/48982/be29f345-2b77-7638-62e9-ea7b7078778d.png)


この中から記事の通りにNICプロパティ4つをDisabledに変更します。

 

　・IPv4 Checksum Offload

　・Large Receive Offload（IPv4）

　・Large Send Offload Version（IPv4）

　・TCP Checksum Offload（IPv4）

 

 

さすがにNICの変更のためRDPは瞬断しましたが、数秒で再接続されました。

OSの再起動は発生しません。

 

設定後は .Netの例外は収束し、サーバも安定しているようです。
嘘つきString


こんな数学の問題見たことないでしょうか？


「この紙の上には、 
１という数字が■個、２という数字が■個、 
３という数字が■個、１から３まで以外の数字の 
数が■個書いてある。 」

1枚の不思議な紙が落ちてました。
この紙には、この紙自身のことが書いてあります。
ところが、■に書いてあった４つの数字が消えていて読めません。
■に数字を入れて、この文が正しくなるようにしてください。


この答えは順番に４、１、３、１となります。実際に数字をあてはめて確かめて見てください
これは高校数学レベルの組み合わせの問題です。


このように自分から自分へ自己言及すると妙なことが起こります。

プログラム内で無限ループするかどうか判定するプログラムは存在しうるか？

という問題に通じることがあります。そのようなプログラムは存在し得ないわけです。
では次の問題はどうでしょう。

「この文章には１という数字が（　）個含まれている」

（　）に1を当てはめてみましょう。すると

「この文章には１という数字が（1）個含まれている」

となります。
文章中には合計で１が2回登場するので文章の意味と矛盾します。
（　）にはいる数字は１ではないわけです

では９以下の１以外の整数を当てはめて見ましょう。

すると文章中には１は1回しか登場しないわけですが（　）は1以外だったはずなので矛盾。つまり9以下の1以外の整数でもないわけです。

では10以上なのでしょうか？まさか。あり得ないでしょう。

つまり（　）にはいる整数は存在しません。

数学的にあり得ないことが証明できました。はい、おしまい

答えは本当に存在しないのでしょうか？
いいえ存在します。それも無限に。

模範解答はこちら

```math
\frac{1}{2}+\frac{3}{2}
```
上式には１が1つしか含まれていません。
したがって、文章中には合計で１が2回登場します。
また、上式を計算すると結果は2になります。

このように、実数同士の演算を行った結果が、式に登場する１の数と一致すれば良いわけです。

以下、イグザンプルです。

```math
\lceil \sqrt{2} \rceil ,(6-5)
,\cos^2 49^ \circ +\sin^2 49^\circ, etc \cdots
```

確かに、なるほどといった感じです。
でも僕はあまり好きではありません
それはあくまで式であって数字ではないだろう、と思うからです。

日常生活で「りんごが$1/2+3/2$つあるね」
なんて言わないわけです。
式を数字として扱うのは計算機だけで十分です。

そこで思いついたのが整数の二進表記でした。
例えば0010bを文章中の（　）に当てはめましょう。
文章中には合計で１が2回登場します。
また、10進表記で0010bは2を表すので矛盾なく文章を組み上げることができました。

二進表記では0と1だけで数を表すのでこの方法なら意味的に矛盾しない数を列挙することができるのでは？

そして、その整数列をオンライン整数辞典に載せたら人気出るかも…。

早速プログラムをかいてみました。3分くらいでかける簡単なプログラムです。

余談ですがJavaのInteger.bitCountの内部実装が面白いのでご紹介

public static int bitCount(int i) {
  i = i - ((i >>> 1) & 0x55555555);
  i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
  i = (i + (i >>> 4)) & 0x0f0f0f0f;
  i = i + (i >>> 8);
  i = i + (i >>> 16);
  return i & 0x3f;
}

これだけでint の1のビットの数を数えることができてるんです。
ループや条件分岐などの制御構文を使わずにシフトと論理演算だけで
実装できるなんて…
ループを使わないので計算量は$O(1)$です。すごい
これはウェーブレット木という文字列探索アルゴリズムが元になっています。


さて、本題に戻ります。
プログラムを実行します。ウキウキと
./test.out 2000
なんて叩きます。
すると実行結果は

2
3


あれ？これだけ？
数字を増やしても結果は変わりません。
内部でもちゃんと動いてるようです。

そうです。
よく考えれば、整数の1のビットの数の増加率は少なくとも
$\log_2 n$以下に抑えられるから線形に増加する$n$に敵うわけないんです。

そんな当たり前のことに気づかなかった自分が恥ずかしいです

以下その証明


ある0以上の整数$n$について
$2^{i-1} \le n \le 2^i$ 
を満たすようなiが存在する。
この時$i$は、$n$を二進数表記する際に必要なビット数を表している

関数$B(n)$を次のように定義する

$B(n)$:={$n$を二進表記した時の1のビットの個数}

すなわち、
$B(n)+1=n$
を示せば良い
左辺は文章中に１が登場する合計を表している

定義から$B(n)$は
$0 \le B(n) \le i$
を満たす。
これから
$i-1 \le \log_2 n$
したがって

$0 \le B(n)=n-1 \le i \le 1+\log_2 n$
$0 \le n \le 2+\log_2 n$

等式が成立するのは$n=4$

これより、$0 \le n \le 4$が示せた。

よって等式を満たす整数は2,3のみ。


なんだか当たり前でしたね。

夜も眠れなくなるくらい面白いと思った問題でしたが実際は
驚きも何もない当たり前の結果。

なんだが凹んじゃいます。

教訓：寝る前に思いついたアイデアは大抵落とし穴がある。

以上。
Vmware Toolsを手動でインストールする

#環境
-windows7
-VMware Workstation 14
-CentOS 6.9

#目的
仮想環境を作った際に、ホストOSとのファイル共有したいので自分用に一つにまとめるため。

#Vmware Toolsのインストール
Player(P)→管理(M)→VMware Toolsのインストールを押してもインストールが始まらなかったので手動でやることに。。

ここまで進むと下の方に手順のダイアログが表示されますが、インストールは行われていないです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/217135/4531ad90-1955-91f1-6159-e5cba498563e.png)

ということで、以下よりインストールの手順を記します。
まず、`# mount`でisoファイルがマウントされているか確認をします。
もし、マウントされている場合は
`# /dev/cdrom on /mnt/cdrom type isoXXXX`
と表示されるそうです。

次にマウントを行うディレクトリを作成します。僕はルートディレクトリに作成しました。

マウントするためのディレクトリの作成
`# mkdir /mnt/cdrom`

マウントの実行
`# mount /dev/cdrom /mnt/cdrom`

/mnt/cdrom ディレクトリへ移動すると以下のようなファイルが作成されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/217135/4f4592a5-a78a-d78c-b70e-20631a04c8b8.png)

続いて作業ディレクトリへ移動しましょう。(/tmpとか)

このディレクトリ内のtarファイルを展開します。
`# tar zxpf /mnt/cdrom/VMwareTools-XXXX.tar.gz`

マウントの解除
`# umount /dev/cdrom`

自動マウントが行われるLinuxディストリビューションの場合は特にする必要はないそうです。

展開が完了したらVmwareToolsのインストーラのディレクトリへ移動します。
`# cd vmware-tools-distrib`

最後にインストーラーの実行
できないならsudoで実行してください。
`# ./vmware-install.pl`

共有フォルダの有効設定を忘れないように
![image.png](https://qiita-image-store.s3.amazonaws.com/0/217135/311ab7b2-96a6-c012-9100-1c99c32639a9.png)

これで/mnt/ghfsディレクトリの中に指定したホストOSのディレクトリが表示されて、ファイル共有ができていることがわかると思います。

僕が既に使用している仮想環境にはインストール済みなので、確認をしていないのですがこれを参考にしてインストールしている際に問題がありそうな場合はコメント頂けるとありがたいです^^

参考。というかそのままだけど
[仮想マシンへのVMware Toolsの手動インストール](https://docs.vmware.com/jp/VMware-Workstation-Player-for-Windows/14.0/com.vmware.player.win.using.doc/GUID-08BB9465-D40A-4E16-9E15-8C016CC8166F.html)
Amazon Connect で顧客の電話にこちらから自動で発信するフォームを作る方法

[![Screenshot from Gyazo](https://gyazo.com/fb239ff8a039b920668a3b45c24af62d/raw)](https://gyazo.com/fb239ff8a039b920668a3b45c24af62d)
よく見かけるこのフォーム　Amazon Connect であれば、直ぐにできるのだろう！
とおもうのが普通ですが、これは出来ません。

現在、どこかに発信させるというAPIが存在しないために出来ないのです。
https://qiita.com/koyakeiaaaaa/items/90f523721a42f50d05be
ここにも書いたとおり、インスタンス全体を操作できるAPIがなく、そのうち提供されるはずという、中の人噂を信じる以外にない状況です。

https://github.com/aws/amazon-connect-streams/blob/master/Documentation.md
このjs ライブラリで　電話オペレーターとしてログインしていれば、自動的に電話をかけることができるのですが、御客さんに電話オペレータとしてのログイン情報を渡せないので、今のところは無理です。
いつしか、電話オペレータ（エージェント）ではない、カスタマーとしてのログイン情報いらずのAPIができればいいと思っています（もちろん、いたずら電話を掛ける人間に対してIPなどで、止めるように自動でなっている前提で。）

アップデートがあり次第ここに書きます。
Redis

[Redis](https://redis.io/) とは、key-value store。ある文字列に割り当てられたデータを検索する仕組み。データはメモリに保存される。永続化も出来る。

## インストール

公式サイトのおすすめは自分で make する事らしい。

    $ wget http://download.redis.io/redis-stable.tar.gz
    $ tar xvzf redis-stable.tar.gz
    $ cd redis-stable
    $ make
    $ sudo make install

`make test` はしないほうが良い。パスワードを聞かれてうざい。

サーバーを起動。ポート 6379 で起動する。

    redis-server

別のターミナルからクライアントを起動してインタラクティブに試す。SET と GET でキーに値を入れたり読んでみる。キーは慣習で my:key のようにコロンで区切る事が多いが、内部的にコロンは特別扱いされない。

    $ redis-cli
    127.0.0.1:6379> SET my:key somevalue
    OK
    127.0.0.1:6379> GET my:key
    "somevalue"

コマンドライン引数に直接 redis コマンドを入れる事も出来る。

    redis-cli SET my:key somevalue

`redis-server` を終了してみる。カレントディレクトリの dump.rdb にデータが保存される。

     ^C26341:signal-handler (1512099345) Received SIGINT scheduling shutdown...
     26341:M 01 Dec 12:35:45.346 * Saving the final RDB snapshot before exiting.
     26341:M 01 Dec 12:35:45.347 * DB saved on disk
     26341:M 01 Dec 12:35:45.347 # Redis is now ready to exit, bye bye...
     $ ls
     dump.rdb
    
面白い事に、`redis-server` を終了しても `redis-cli` はすぐにはエラーにならない。なので `redis-server` を一旦停止して別の `redis-sever` を立ち上げても `redis-cli` は何食わぬ顔して処理を続ける。

続きは [interactive tutorial](http://try.redis.io/) で勉強出来る。これも面白い。

## 色々な機能

存在確認。

    127.0.0.1:6379> EXISTS my:key
    (integer) 1

INCR で数字を増やす。SET を省略すると 0 が入ってる物とみなす。

    127.0.0.1:6379> SET mynumber 10
    OK
    127.0.0.1:6379> INCR mynumber
    (integer) 11
    127.0.0.1:6379> INCRBY mynumber 10
    (integer) 21


EXPIRE で有効期限の秒数を設定する。TTL で残りの有効期限を調べる。TTL = -1 は有効期限未設定、TTL = -2 は時期限切れを現す。

    127.0.0.1:6379> SET timer hello
    OK
    127.0.0.1:6379> EXPIRE timer 60
    (integer) 1
    127.0.0.1:6379> TTL timer
    (integer) 55

RPUSH でリストの後ろに追加する。Redis では、キーを予め SET しておかなくても要素を追加出来るし、要素がなくなると勝手にキーが消える。LRANGE で範囲内の要素を読む。LRANGE の範囲指定のマイナスは後ろからの位置を現す。

    127.0.0.1:6379> RPUSH friends Alice
    (integer) 1
    127.0.0.1:6379> RPUSH friends Bob Charlie Dave
    (integer) 4
    127.0.0.1:6379> LRANGE friends 0 1
    1) "Alice"
    2) "Bob"
    127.0.0.1:6379> LRANGE friends 0 2
    1) "Alice"
    2) "Bob"
    3) "Charlie"
    127.0.0.1:6379> LRANGE friends 0 -1
    1) "Alice"
    2) "Bob"
    3) "Charlie"
    4) "Dave"

HSET でハッシュを作成して HGET で取り出す。

    127.0.0.1:6379> HSET secrets Alice alicesecret
    (integer) 1
    127.0.0.1:6379> HSET secrets Bob bobsecret
    (integer) 1
    127.0.0.1:6379> HGET secrets Alice
    "alicesecret"

## REDIS で使えるデータ

* ADD: 文字列
* RADD LADD: リスト
* SADD: セット
* ZADD: 順序付きセット
* HSET: ハッシュ
* GEOADD: 緯度経度で検索出来る情報

## 色々な技

データべースのすべてのキーを表示

    redis-cli --scan --pattern '*'

全部削除

    edis-cli flushall

## GUI

Medis: https://github.com/luin/medis というのを使うと GUI で中身を見る事が出来て便利。

## 参考

* [Redis Quick Start](https://redis.io/topics/quickstart)
MySQLのテーブル定義書を自動更新する環境を作った

# 概要

今使っているテーブル定義書は最新ですか？  
こんな状況に身に覚えがないですか？

- 更新を忘れて仕様書が信用できない。
- 見ていた仕様書が古くて、ハマったことがある。
- 毎回`SHOW CREATE TABLE;`コマンドで確認している。


何番煎じのネタかわかりませんが、今回 `mysqldump` + `xsltproc` + `cron`を使ってテーブル定義書を自動で最新に更新する環境を作ってみました。

# 環境

データベース = MySQL
仕様書ビルド環境 = Linux
仕様書の閲覧 = ブラウザ

# DB作成

```MySQL
CREATE DATABASE `SampleDB`;
```

```MySQL
CREATE TABLE `SampleDB`.`Users` (
  `user_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ユーザーID',
  `name`    varchar(64) NOT NULL DEFAULT "" COMMENT 'なまえ',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='ユーザーテーブル';
```

```MySQL
CREATE TABLE `SampleDB`.`Favorites` (
  `favorite_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'お気に入りID',
  `user_id`     int(11) unsigned NOT NULL DEFAULT 0 COMMENT 'ユーザーID',
  `content`     varchar(64) NOT NULL DEFAULT '' COMMENT '好きなこと',
PRIMARY KEY (`favorite_id`),
FOREIGN KEY `foreign_user` (`user_id`) REFERENCES `Users` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='お気に入りテーブル';
```

# やること

1. `mysqldump`を使って、DDLをxml形式で出力。  
  `mysqldump --no-data --xml SampleDB > mysqldump.xml`
2. `xsltproc`を使い、`xmlファイル` + `xsltファイル` => `htmlファイル`に変換します。(`xsltファイル`についてはあとで触れます。)  
  `xsltproc -o index.html style.xslt mysqldump.xml`
3. 出来上がったHTMLを、Webサーバーのに公開ディレクトリに配置すればブラウザから確認できます。  
  ※ 公開するのはローカルネットワーク上だけにしましょう。  
  ※ セキュリティ上問題ないかはよく検討した上で行ってください。  

この３ステップをシェル化すれば、１コマンドで仕様書の更新ができます。

```sh
#!/bin/sh

RUN_SHELL_DIR=`dirname $0`

# Work space
WORK_DIR="${RUN_SHELL_DIR}/MySQLSchemaDoc"
TEMPLATE_XSLT=${WORK_DIR}"/src/style.xslt"
MYSQLDUMP_XML=${WORK_DIR}"/mysqldump.xml"
OUTPUT_HTML=${WORK_DIR}"/dist/index.html"

# MySQL ※環境に合わせて書き換えてください
MYSQL_HOST="127.0.0.1"
MYSQL_USER="username"
MYSQL_PASS="password"
MYSQL_SCHEME="SampleDB"

# Web Server ※環境に合わせて書き換えてください
PUBLIC_DIR="/var/www/html/mysqldoc/"

mysqldump --no-data --xml -u ${MYSQL_USER} -p${MYSQL_PASS} -h ${MYSQL_HOST} ${MYSQL_SCHEME} > ${MYSQLDUMP_XML}
xsltproc -o ${OUTPUT_HTML} ${TEMPLATE_XSLT} ${MYSQLDUMP_XML}

cp  ${WORK_DIR}/dist/* ${PUBLIC_DIR}
```

このシェルを`cron`で１日１回くらい定時実行するよう設定すれば、（ほぼ）最新の状態に保たれるようになります！

# 利用する`xsltファイル`

いくら最新の情報でも"見づらい/使いづらい" だとそもそも誰も見ない。ってことになるので、ある程度使えそうなXSLTスタイルシートを用意しました。
https://github.com/RyutaKojima/MySQLSchemaDoc 
利用・複製・改変は自由なので、必要に応じてカスタマイズしてください。 
（プルリクも待っています！！）

ほかのサイトでもXSLTスタイルシートを公開してあるので、気に入ったものをベースにカスタマイズすればよいかと思います。
[MySQL テーブル仕様書メーカー的な何か](http://mysql-doc.mariyudu.net/)

# 最後に

仕様書作成で消耗したくないですね！
ubuntu:文字化けした時の対応


ubuntu上にpython環境を作って動作確認した時に何故か日本語の部分でエラーが出たのでその時に行ったことメモ


```動作環境
macOS High Sierra 10.13
#ubuntu on docker
cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.3 LTS"
```

とりあえずpythonをインストールしてみて動作確認したらエラー発生。。どうも日本語が読めないっぽい。。

```hoge.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

aaa = "あいうえお"
print(aaa)
```
```
python hoge.py 
Traceback (most recent call last):
  File "aa2.py", line 7, in <module>
    print ('\u3053\u308c\u3067\u65e5\u672c\u8a9e\u3082\u6253\u3066\u307e\u3059')
  File "/root/.pyenv/versions/3.6.3/lib/python3.6/codecs.py", line 377, in write
    self.stream.write(data)
TypeError: write() argument must be str, not bytes 
```

色々調べていると日本語環境がどうも入っていないような気がしたので日本語環境を構築してみた。

```
echo $LANG

```

何も表示されなかったので、多分これが原因と思い日本語環境にしてみた。

```
apt-get install language-pack-ja-base language-pack-ja
locale-gen ja_JP.UTF-8
echo export LANG=ja_JP.UTF-8 >> ~/.profile
source ~/.profile
```

```
echo $LANG
ja_JP.UTF-8

```

```
python hoge.py 
あいうえお
```

オッケー。ちゃんと表示されました。

これに行き着くまでに色々やったことがあるので合わせてメモしておきます。

最初はソースの文字コードが違うと思っていたのでその辺りから調べていた。調べるためにnkfをインストール。

```apt-get install nkf```

```文字コードの調べ方
cat hoge.py | nkf --guess
```

```文字コード変換方法
#utf-8に変換
nkf -w --overwrite hoge.py
```

文字コードとかホント嫌い。


Ubuntuに日本語localeを設定する
http://www.dreamedge.net/archives/111
nkfで文字コード変換
https://qiita.com/kentakozuka/items/d874a572ddf6cc34213f
Digコマンドを打つためのシェルスクリプト

自分のネットワークに障害があったとき、大体一番か二番目くらいにDNSが正常かどうかを確認しますよね。

Digって戻り値でエラーが掴みづらいので、
AnserSectionが０だったらエラーとするようにしました。


```
#!/bin/bash
#set -x

HOME_DIR="${PWD}"

# ssh check関数

dig_check () {
    anschk=$( dig $1 @$2 | grep ANSWER | cut -d"," -f2 | cut -d":" -f2; )
    if [ $anschk = 0 ]; then
      res=`echo ${res} | sed "s/^M/ /g" `
      echo "NG : dig $1 @$2 にてANSWERがありません"
    else
      res=$( dig $1 @$2 | grep Query | cut -d":" -f2; )
      status_code=$?
      #dig ameba.jp @$1 +short

      if [ $status_code = 0 ]; then
        res=`echo ${res} | sed "s/^M/ /g" `
        echo -n "OK : dig($2) : $1 : ${res}"
      else
        echo "NG : dig command : $2"
      fi
    fi

}

echo "----DNS決め打ちでDigします----"
#dnsサーバのIPアドレスをここに記載
dns_list=(
    192.168.1.254
    8.8.8.8
)
echo '```'
for cache_sv in ${dns_list[@]}; do
echo "`dig_check "yahoo.co.jp" "${cache_sv}" `"
echo "`dig_check "google.com" "${cache_sv}" `"
done

echo '```'
exit
```

### 出力ログ

----DNS決め打ちでDigします----

```
OK : dig(192.168.1.254) : yahoo.co.jp : 3 msec
OK : dig(192.168.1.254) : google.com : 0 msec
OK : dig(8.8.8.8) : yahoo.co.jp : 0 msec
OK : dig(8.8.8.8) : google.com : 0 msec

```
Mbed OS 5について

[mbed Advent Calendar 2017](https://qiita.com/advent-calendar/2017/mbed) 1日目の記事です。

最近、[Wio LTEの本](http://amzn.to/2zDAesb)を出版して浮気気味ですが、ちゃんとMbed OS 5をいじくってます！(主に仕事で,だけど・・。)

とうことで同じく出版、出版予定のmbed OS 5について書いた本を紹介します。

## はじめてのMbed OS 5【前編】: Mbed OS 5で始めるIoTプロトタイピング
おかげさまで[はじめてのMbed OS 5【前編】: Mbed OS 5で始めるIoTプロトタイピング](http://amzn.to/2zQ3q3b)は出版開始から1ヶ月が過ぎ、ぼちぼちな売れ行きです。
以降、Mbed OS 5もバージョンアップされているので、合わせて内容を更新予定です。
[![Top_logo.jpg](https://qiita-image-store.s3.amazonaws.com/0/109992/8a9a9741-cb91-f5a5-714f-10ecbd3cf781.jpeg)](http://amzn.to/2hiVpMh)

## はじめてのMbed OS 5【後編】: Mbed OS 5で始めるIoTプロトタイピング
【後編】は遅れ気味ですが以下の目次で、近々出版予定です。
![Top_logo.jpg](https://qiita-image-store.s3.amazonaws.com/0/109992/008fc013-3765-698f-9020-1c23253d9a7e.jpeg)
**IoTエッジデバイスプロトタイピング**
　**アップロードしたデータの取り扱い方法**
　　**enebularの紹介**
　　**Infomorsionの紹介**
　**センサー追加**
　**製品化への対応方法**
　**異常処理の追加**
　**デバック環境を整える**
　**MDK ARMに移行**
**Mbed OS 5の詳細**
　**フォルダ構成**
　**ブートストラップシーケンス**
**Mbed OS 5 APIリファレンス**
**Mbed コミュニティの紹介**

## 今後の予定
次はMbed Cloudについて本を書く予定です。
私が所属するウフルはMbed Cloudのパートナーということもある、Mbed Cloudはいち早くいじらせてもらっています。
（世界でもっともいじってるのはうちの会社らしい？ ほんと？）
それなので、いち早く詳細な情報をお届けできると思いますので、こうご期待ください！
ちなみにMbed Cloudについてのドキュメントは、最近公開状態となったので誰でも見られるようになっています。

[Mbed cloudのトップページ](https://cloud.mbed.com/)
[Mbed cloudのドキュメントページ](https://cloud.mbed.com/docs/v1.2)

主な機能を紹介すると・・。

- Mbed Cloud Connect　Mbed Cloudとはセキュアな通信で繋がります。Mbed Cloud経由でデバイスとデータのやり取りができます。ポータルサイトではMbedデバイスが接続されているステータス、デバイス―Mbed Cloud間のデータの内容の確認、書き込みができます。
- Mbed Cloud Update　Mbed Cloudからファームウェアのアップデートができます。複数のデバイスへいっぺんにアップデートすることもできます。

こんな感じです。

お楽しみに！

初日から内容が少なくてすみません～。
次は[toyowata](https://qiita.com/toyowata)さんです。
DOTweenのコールバックをいくつか紹介

謎のAdventCalendar　解散カレンダー二日目です。

Unityのゲーム開発者さんおなじみのDOTweenを使ったお話です。

DOTweenはアニメーション終了時や切り替え時などにコールバック関数が設定できるので何個かコールバックを紹介しときます。

・OnComplete
　アニメーションが終了したら実行されるコールバック。お手軽便利すごいやつ
　

	void Start () {
        this.transform.DOMoveX(2, 2).OnComplete(() =>
            {
                Debug.Log("ほげ!");
            });
		
	}

こんな感じで使います。

![1.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/159111/f57966fc-6da4-9f7e-6a09-1c926495c197.gif)



・AppendCallback　（sequence専用)
sequenceでアニメーションの後ろにコールバックを追加できます。これも地味に便利。


	void Start () {
        Sequence seq = DOTween.Sequence();
        //右に行く
        seq.Append(this.transform.DOMoveX(2, 2))
        //コールバック
        .AppendCallback(() =>
        {
            Debug.Log("左行くやで〜〜〜");
        })
        //左に行く
        .Append(this.transform.DOMoveX(0, 2))
        //コールバック
        .AppendCallback(()=>
        {
            Debug.Log("FOOOO~~~~!!");
        });
		
	}
![２.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/159111/e369d5f2-fca8-4d18-6c47-4a0baaa3d17f.gif)



・OnWaypointChange(DOPath限定）
あんまり使ってる人がいない機能なんですがDOPathでのみ使えるコールバックです。
DOPathは配列の中に座標データを入れるとその通りに移動してくれるやつです。
このコールバックでは配列のウェイポイントに到達した度にコールバックが呼ばれます。
ちょっと特殊でint型変数がコールバックの引数として入ってきます。

	void Start () {
       
        Vector3[] array = new Vector3[3];
        array[0] = new Vector3(0, 1, 0);
        array[1] = new Vector3(1, 1, 0);
        array[2] = new Vector3(1, 0, 1);

        transform.DOPath(array, 4).OnWaypointChange(waypoint =>
            {
                Debug.Log("waypointの中身"+waypoint);
            });
	}

![３.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/159111/6bdf4533-dfc1-baa0-ffdc-613a56a51eb6.gif)



まだ書こうと思ったけど眠いので今日はこの辺で。気が向いたら書き足します。
API Gateway で URL クエリパラメータの扱いで混乱した


gumi TS&D という部署のクラウドエンジニア担当です.
(12/1 当日に Calendar 作って, 当日夕方書きました)

ご存知の通り簡単な API であれば API Gateway は最適です.
構築も AWS マネージメントコンソールからドキュメント見ながらぽちぽちしていくだけなのでとても楽かと思います.

しかし, ぽちぽち構築は自動化の妨げになるので, クラウドエンジニアとしてはコード化しないといけません.

今回簡単な API を API Gateway で作る機会があり, クエリパラメータの扱いで混乱したので紹介します.

## (ちなみに作成した API)

![Untitled.png](https://qiita-image-store.s3.amazonaws.com/0/46714/5cc35934-40d8-d4a7-8028-fadce46f9c1b.png "Untitled.png")

今回作った API は, POST したファイルを S3 の指定したパスに保存するものです.



## 混乱箇所


CloudFormation の Template(抜粋) は以下のようになります.

```
ApiGateway:
	Type: "AWS::ApiGateway::Method"
    Properties:
    	RequestParameters:"method.request.querystring.objectPath": true
    	Integration:
    		RequestParameters:
          		"integration.request.path.objectPath": 	"method.request.querystring.objectPath"
        Uri: !Sub "arn:aws:apigateway:ap-northeast-1:s3:path/sample_bucket/{objectPath}"
        ...
```


- 「RequestParameters」に受け付ける URL クエリパラメータの設定
- 「Integration.RequestParameters」で変数にマッピング

**この二つの設定が必要.**


私は「RequestParameters」で混乱した.

Properties 直下の「RequestParameters」は「メソッドリクエスト」の URL パスパラメータの設定.
マネージメントコンソールだと下の SS の通り.

![スクリーンショット 2017-12-01 15.09.56.png](https://qiita-image-store.s3.amazonaws.com/0/46714/ed3f890a-0df9-c292-5284-8463761ba4b5.png "スクリーンショット 2017-12-01 15.09.56.png")

「Integration.RequestParameters」は「統合リクエスト」の URL パスパラメータの設定.
マネージメントコンソールだと下の SS の通り.

![スクリーンショット 2017-12-01 15.54.19.png](https://qiita-image-store.s3.amazonaws.com/0/46714/6c5bc48b-ef90-f456-a493-df37a89d4f9c.png "スクリーンショット 2017-12-01 15.54.19.png")

---

さらに「Integration.RequestParameters」に関しては, マネージメントコンソールと同じようにパラメータ名だけの指定ではダメで以下のように指定しなければならない.

```
integration.request.<location>.<name>
```
<script>要素のdefer属性、async属性による外部JavaScriptの非同期読み込み

ディップ [Advent Calendar 2017](https://qiita.com/advent-calendar/2017/dip-dev) の5日目です。

JavaScriptはその処理内容自体もパフォーマンスチューニングの対象になりますが、HTML側での`<script>`タグの書き方も大事です。

# レンダリング前のプロセス
![image.png](https://qiita-image-store.s3.amazonaws.com/0/71171/caa434d0-ca42-ba2e-8716-11fc102591a6.png)

## ブラウザが描画の前にやっていること
ブラウザはHTMLをサーバーからダウンロードすると、その内容をパース（解析）してDOMツリー（文書構造の内部表現）を構築する。

## &lt;script&gt;タグによるパースの中断
```html
<script src="foo.js"></script>
```
HTMLパーサーは、パースの途中で`<script>`タグがあるとそのスクリプトを実行し終わるまで一時的にパースを中断する。
**src属性**がある場合（外部JavaScript）はサーバーにリクエストし、ダウンロードして実行するので、その分中断時間が長くなる。
`<script>`タグを`</body>`の前に記述するのがセオリーなのはこのため。

## なぜパースが中断されるのか
JavaScriptの`document.write()`メソッドは、その場にHTMLを書き出す機能を持つ。
そのためこのメソッドが実行されると、パースの結果生成されるDOMツリーの構造に影響を与えてしまう。
スクリプト内に`document.write()`メソッドが使われているかどうかはスクリプトの内容を見なければ分からないため、`<script>`タグの位置でパースを一時的に中断して、スクリプトの内容を取得・解析する。

## &lt;script&gt;要素のdefer属性・async属性
```html
<script src="foo.js" defer></script>
<script src="bar.js" async></script>
```
src属性を持つ`<script>`要素に**defer属性**または**async属性**を付与することにより、**パースが中断されなくなる**。
その代わり、そのスクリプト内に記述された`document.write()`メソッドは無視されるようになる。
そのスクリプト内で`document.write()`メソッドが実行されない事が保証されることで、HTMLパーサーはパースを続行できる。

# defer属性とasync属性の使い分け

## defer属性
スクリプトが`<script>`要素の順に実行されることが保証される。
HTMLのパースは中断されないが、実行されるのはDOMツリー構築後であることに注意。
外部のJSライブラリ（jQueryとか）の機能を使ったJSファイルやプラグイン等、スクリプト間に依存関係がある場合にはこちらを指定する。

**DOMツリー構築完了後、常にscript1 → script2の順に実行される**

```html
<script src="script1.js" defer></script>
<script src="script2.js" defer></script>
```

## async属性
スクリプトが`<script>`要素の順に実行されることが保証されない。
スクリプトのダウンロードが終わると直ちにコンパイル＆実行されるため、スクリプト間の依存関係が無い場合はこちらの方が高速。

**ダウンロードが完了した順に実行される**

```html
<script src="script1.js" async></script>
<script src="script2.js" async></script>
```

---

それでは、残り僅かになった酉年を大切にお過ごしください！
Eclipseを使っていて便利だったショートカットの忘備録

---
## 思いつく限りで書いていく。
### 単位毎の選択
Shift + Alt + ← or →
コピペ前など、とにかく良く使う。
Ctrl + Shift + ←or→
上のショートカットとはまた違う。
マウスで対象をダブルクリックすることもある

### 補完
Ctrl + Space
便利な補完機能。たまに重くなるのが残念な所
### 補完2
Alt + /
こちらは編集対象内で補完候補を見つけて来てくれる
Ctrl + Spaceとは全然違うので使い分ける
### コメント
Ctrl + Shift + c または Ctrl + /
選択した行の先頭に//を追加してコメントアウトしてくれる
//がある行に対して使うとコメントアウトが解除される
### 移動関係
Ctrl + ←or→
単語単位で移動。左右のキーを連打したくない時に。
Home
行の先頭へ移動
End
行の最後へ移動
Ctrl + Home
先頭行に移動
Ctrl + End
最終行に移動
Ctrl + Shift + ↑or↓
前(次)のメソッドに移動
### インポート
Ctrl + Shift + O
### フォーマッター
Ctrl + Shift + F
### 改行
Ctrl + Shift + Enter
カーソル行の上方向に改行。行の最後尾にカーソルを持っていかなくてもOK
Shift + Enter
カーソル行の下方向に改行
### 保存
Ctrl + s
おなじみのコマンド
### コピペ
Ctrl + c
Ctrl + x
Ctrl + v
念のため
### アンドゥーリドゥー
Ctrl + z
Ctrl + y
### タブ移動
Ctrl + PageUp or PageDown
### 呼び出し階層を開く
Ctrl + Alt + H
これってどこで使われてるんだろうって時に
### 宣言を開く
F3
中身なんだっけ？
### ブレイクポイントの設定
Ctrl + Shift + B
カーソル行で切り替え

### 大文字と小文字の切り替え
Ctrl + Shift + x
Ctrl + Shift + y
 
### つづく...
Project Euler Q32 【パンデジタル積】

Project Eulerをワンライナーで解いてみる。
間違っていたらコメントください。


## 問題
すべての桁に $1$ から $n$ が一度だけ使われている数を$n$桁の数がパンデジタル (pandigital) であるということにしよう: 例えば$5$桁の数 $15234$ は$1$から$5$のパンデジタルである.

$7254$ は面白い性質を持っている. $39 × 186 = 7254$ と書け, 掛けられる数, 掛ける数, 積が$1$から$9$のパンデジタルとなる.

掛けられる数/掛ける数/積が$1$から$9$のパンデジタルとなるような積の総和を求めよ.

HINT: いくつかの積は, 1通り以上の掛けられる数/掛ける数/積の組み合わせを持つが$1$回だけ数え上げよ.

## 解答

```bash
seq 9876 |
awk -v FS= '{s=1;for(i=1;i<=NF;i++){s*=gsub($i,$i)};if(s==1){print}}' |
factor |
awk 'NF!=2{print $1*1}' |
awk '{for(i=1;i<=$1;i++){if($1%i==0){print i"@"$1/i,$1}}}' |
grep -v "0" |
awk -v FS= 'length==11{s=1;for(i=1;i<=NF;i++){s*=gsub($i,$i)};if(s==1){print}}' |
uniq -f1 |
awk '{s+=$2}END{print s}'
45228
```

`factor`みたいに約数を出力するコマンドないかなあ。

スタートの`seq`を$98765$から$9876$に変更したところ、実行時間が$11$分から$12$秒へと劇的に改善した！

## 答え合わせ
こちらのサイト様と一致していればOKとした。
http://kingyojima.net/pje/032.html
猫写真のサイズがポストカードに使えるかどうか判別する AppleScript を書いた


## 概要
弊社猫社員のポストカードを販売するにあたって、サーバに溜め込まれた猫写真の中から、ポストカードに使えるサイズの画像を抽出するようにオーダーされたので、AppleScript で書いてみました。

## 環境
* MacOS 10.12.x
* Adobe Photoshop CC 2017

## ポストカードのサイズ
* 幅　：100mm
* 高さ：148mm

## 仕様
* ドロップレット形式
* ドラッグ＆ドロップされたファイル群を一つずつ開く
* 幅・高さがポストカードのサイズで定義されたものより大きければ、ファイルにタグをつける（サンプルではレッドのタグ）
* ファイルは保存せず閉じる

## ソースコード
```applescript:ソースコード
on open fileList
	repeat with i in fileList
		tell application id "com.adobe.photoshop"
			--ルーラーの設定を退避後、mmに変更（サイズをmmで判定するため）
			set oldUnits to ruler units of settings
			set ruler units of settings to mm units
			open i
			tell current document
				activate
				set filePath to POSIX path of (file path as alias)
				--再サンプルのチェックを外した状態で解像度を350に変更（350は一般的な印刷時の解像度）
				resize image resolution 350 resample method none
				--画像が100x148より大きいか判別
				if (width > 100 and height > 148) then
					my addTagOnFile(filePath)
				else if (width > 148 and height > 100) then
					my addTagOnFile(filePath)
				end if
				--保存しないで閉じる
				close saving no
			end tell
			--ルーラーの設定を元に戻す
			set ruler units of settings to oldUnits
		end tell
	end repeat
end open

to addTagOnFile(filePath)
	--タグをShell Scriptでつける
	do shell script "xattr -w com.apple.metadata:_kMDItemUserTags '(\"レッド\\n6\")' " & filePath
end addTagOnFile
```

## ポストカードに興味がある方は
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">【お知らせ】東京板橋区の保護猫カフェCAT&#39;S INN TOKYO <a href="https://twitter.com/CATS_INN_TOKYO?ref_src=twsrc%5Etfw">@CATS_INN_TOKYO</a> さんにてみるくトートバッグとポストカードセットの委託販売がスタートしました！委託販売収益はすべて保護猫活動へのチャリティーにあてさせていただきます(ΦωΦ)<a href="https://twitter.com/hashtag/qnote_cat?src=hash&amp;ref_src=twsrc%5Etfw">#qnote_cat</a> <a href="https://t.co/h8rDZLKHGy">pic.twitter.com/h8rDZLKHGy</a></p>&mdash; 株式会社 qnote (@qnote_inc) <a href="https://twitter.com/qnote_inc/status/889428922760257536?ref_src=twsrc%5Etfw">2017年7月24日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ポストカードはもちろん、みるく部長のトートバッグもとってもかわいいので、ぜひ！

## まとめ
* AppleScript はドラッグ＆ドロップで実行する形式がとても使いやすくて良い
* 猫写真の整理は幸せな気持ちになれるのでおすすめ
指定した期間から指定した期間を除外して空いた期間を見つける。

# 目的

元々は、12月のスケジュールから空白期間を見つけるために必要になった。
検索してみたところ似たようなものがなかなか見つからなかったので自作。

## 例
12月のスケジュールが

- 12月01日 0:00:00～12月20日 23:59:59
- 12月22日 0:00:00～12月31日 23:59:59

である場合、空いている期間は、

- 12月21日 0:00:00～12月21日 23:59:59
になる。

# 使い方
調べたい期間を設定

```php
$objDateSplit = new DateSplit(new DateTime('2017-12-01 00:00:00'), new DateTime('2017-12-31 23:59:59'));
```

期間から除外するスケジュールを指定

```php
$objDateSplit->splitPeriod(new DateTime('2017-12-01 00:00:00'), new DateTime('2017-12-20 23:59:59'));
$objDateSplit->splitPeriod(new DateTime('2017-12-22 00:00:00'), new DateTime('2017-12-31 23:59:59'));
```

出力

```php
foreach ($objDateSplit as $aryBlankRow) {
	printf("%s ~ %s\n", $aryBlankRow[0]->format('Y-m-d H:i:s'), $aryBlankRow[1]->format('Y-m-d H:i:s'));
}

#[結果] 2017-12-21 00:00:00 ~ 2017-12-21 23:59:59
```


# クラス

```php
class DateSplit implements IteratorAggregate
{
	/**
	 * 期間一覧
	 *
	 * @var array int
	 */
	protected $aryPeriod = [];


	/**
	 * コンストラクタ
	 *
	 * @param \DateTime 全体期間開始日
	 * @param \DateTime 全体期間終了日
	 */
	public function __construct(\DateTime $objDateFrom, \DateTime $objDateTo) {
		$this->aryPeriod[] = [$objDateFrom->getTimestamp(), $objDateTo->getTimestamp()];
	}



	public function getIterator() {
		$aryResult = [];

		foreach ($this->aryPeriod as $aryPeriodRow) {
			$aryResult[] = [
				new \DateTime(date('Y-m-d H:i:s', $aryPeriodRow[0])),
				new \DateTime(date('Y-m-d H:i:s', $aryPeriodRow[1])),
			];
		}

		return new ArrayIterator($aryResult);
	}



	/**
	 * 期間を分割する
	 *
	 * @param \DateTime 分割開始期間
	 * @param \DateTime 分割終了期間
	 */
	public function splitPeriod(\DateTime $objDatePeriodFrom, \DateTime $objDatePeriodTo) {
		$aryResult = [];

		$numPeriodFrom = $objDatePeriodFrom->getTimestamp();
		$numPeriodTo   = $objDatePeriodTo->getTimestamp();

		foreach ($this->aryPeriod as $aryBasePeriod) {
			$aryResultTmp = [];

			$numBaseFrom   = $aryBasePeriod[0];
			$numBaseTo     = $aryBasePeriod[1];

			if ($numBaseFrom < $numPeriodFrom && $numBaseTo > $numPeriodFrom) {
				$aryResultTmp[] = [$numBaseFrom, $numPeriodFrom - 1];
			}

			if ($numBaseFrom < $numPeriodTo && $numBaseTo > $numPeriodTo) {
				$aryResultTmp[] = [$numPeriodTo + 1, $numBaseTo];
			}

			if (count($aryResultTmp) === 0 && !($numBaseFrom === $numPeriodFrom && $numBaseTo === $numPeriodTo)) {
				$aryResultTmp[] = [$numBaseFrom, $numBaseTo];
			}

			$aryResult = array_merge($aryResult, $aryResultTmp);
		}

		$this->aryPeriod = $aryResult;
	}
}
```
SIerが提供するスマートスピーカーAISonar

# TISAdventCalendar6日目

TISというSIerが業務用に提供する新しい価値であるスマートスピーカーのお話です!!
その中でもスマートスピーカーという製品を支えるための技術群や他の製品との違いについて書きます。

# AISonarとは

公式の発表では以下のように記載されています。
>「AISonar」は、エーアイとTISで共同開発した音声認識技術・意図解釈技術>（AI）・機械翻訳技術・音声合成技術を組み合わせた、スピーカー型のコミュニケーションツールです。
>>https://www.tis.co.jp/news/2017/tis_news/20170925_1.html

なかなかピンとこないですね…というわけでもう少し詳細についてまとめてみます。

# AISonarを支える技術

AISonarの基盤を支える重要な技術が3つあります。

1. 音声認識
2. 対話制御
3. 音声合成

このいずれが欠けてもスマートスピーカーとしては動作できません。
これらの要素について一つ一つみていってみます。

## 音声認識
音声認識はフェアリーデバイセズ社の[mimi](http://www.fairydevices.jp/mimi.html)を利用しています。
また音声認識とセットで同社の[fairy I/O Tumbler](http://www.fairydevices.jp/fairy_io.html)をハードウェアとして利用することで他のコンシューマ向けスマートスピーカーで提供されるような機能だけではなく、他のスマートスピーカーでは活用できないような情報を利用可能になっています。

例えば、以下のような情報が利用可能です。

| 機能                |詳細|
|--------------------:|-------------------|
| 話者の識別      |識別事前学習済のデータから**話者を識別**する |
| 3D音声定位      |スマートスピーカーに対して**どの向きから声をかけたか**識別する|
| 適応ビームフォーミング|**特定の方向**からの音声だけを認識する |
| 多言語対応|音声認識で**多言語の認識**が可能 |
| 複数話者の同時認識|複数の方向からの音源を別々に認識することが可能|

## 対話制御
スマートスピーカーで業務を実現するためには業務自体を対話シナリオとして用意する必要があります。
一問一答のような対話シナリオだけでなくユーザの回答によって条件が分岐していくような複雑な対話シナリオを定義することで実際の業務を実現することが可能になるためです。

AISonarではこの機能を[TIS](http://www.tis.co.jp)のチャットボットプラットフォーム[DialogPlay](https://www.dialogplay.jp/)で実現しています。
DialogPlayは対話シナリオを定義の自由度が高く、またWebブラウザ上からわかりやすく定義できる
という点で強みがあります。:thumbsup:

## 音声合成
最後にユーザへのフィードバックとして、[株式会社エーアイ](https://www.ai-j.jp/)の音声合成を利用しています。
実績のある音声合成ソリューションで、音声合成の色々なパラメータ（ピッチ、感情、声の大小、etc...）について自在に調整可能です。

多国語での音声合成が可能で、さらに事前に音声合成用の日本語合成辞書を作って置くことで自由なキャラや人間の声でスマートスピーカーがお話ししてくれます。:relaxed:

# コンシューマ向けスピーカーとの違い（差別化ポイント）
## カスタム自由
AISonarは自由にカスタムすることができます。

- ハードウェア
 - ディスプレイとの接続
 - センサー（温度、気圧、カメラなど）の接続と連携
- ソフトウェア
 - 社内システムとの連携
 - Storeによるチェックなどの制限のない独自アプリケーションの導入
- ネットワーク
 - 社内のイントラ/システムとの接続
 - クラウドを利用しない形態へのカスタム
 - 有線LANでの接続

等が考えられるでしょうか？
企業利用で考えられるあらゆる制約を逃れられるでしょう :smile: 

## 基本的な動作

シーケンス図で書くと基本的な機能だとこんな感じです。
![シーケンス図](https://qiita-image-store.s3.amazonaws.com/0/19483/840b3a35-0926-cce8-a424-c1c85655371c.png)

この基本的な流れにたとえば発話内容の翻訳などの別の機能が入ると少し変わるという形になります。


## ターゲットの違い
AISonarはB2Bをターゲットにした業務用スマートスピーカーです。
いくつかの観点で他の製品では実現不能なことが実現可能です。

### 利用環境の違い

コンシューマ向けスマートスピーカーは家庭内が主な利用シーンになりますが、AISonarは窓口、工場、倉庫などのような多彩な利用シーンを想定しています。
例えば、少々騒々しいような環境などでも安定して動作させることができるよう開発が進んでいます。

### 独自辞書の組み込み

一般的な言葉ではないような独自の言葉を音声認識してほしいというケースがあるでしょう。
例えば、業務や会社独自の規則名や製品名、略語等は音声をテキスト化する際に期待通りに結果が得られないという問題につながります。
AISonarでは認識時にシステムごとに固有の辞書を組み込むような対応も可能となっていきます。

### 音声データの取り扱いの違い

コンシューマ製品の音声データはどうしても製品の改善のために音声データを利用されてしまいます。
利用されるとはいっても、恐らく音声認識の学習用途に利用する、以上のことはしないでしょうが、情報漏えいを警戒したり、情報の統制を重要視したりするような環境下ではコンシューマ製品は選択肢に挙げられないでしょう。
AISonarであれば、必要であればイントラ内で完結させる音声認識システムの構築や、あるいは契約という所で守ることも実現ができるでしょう。

### マーケットの審査を受けない

コンシューマ向け製品ではアプリケーションを配布のために審査が存在します。（スマートフォンにおけるGooglePlayやAppStoreの審査をイメージするとわかりやすいと思います。）
しかし、AISonarにはそういったものは存在しておらず、限られた人が限られた目的でスマートスピーカーを活用したシステムを構築する事ができるようになります。

# おわりに
TISの提供するスマートスピーカーの話を軸に、スマートスピーカー全般を支える技術とコンシューマのスマートスピーカーとの違いをまとめました。

システムをコンシューマ製品で実現する場合、なんらかの制約で実現が困難な場合などの検討にご活用ください。


# 公式の情報はこちら

https://www.tis.co.jp/news/2017/tis_news/20170925_1.html
UnityでKinectを動かす

今回はUnity2017.1.2で開発してみました！

#もくじ
1.Kinect for Windows SDK 2.0をダウンロード
2.Unity Pro packagesをダウンロード＆インポート

#1.Kinect for Windows SDK 2.0をダウンロード
↓ここからSDKをダウンロード↓
https://developer.microsoft.com/en-us/windows/kinect/tools

以下の手順でダウンロードできます
![2.PNG](https://qiita-image-store.s3.amazonaws.com/0/191497/7177d793-e15a-de91-eb66-577081379152.png)

![3.PNG](https://qiita-image-store.s3.amazonaws.com/0/191497/87aade15-a1d1-4dc1-d27f-8940d76a7091.png)

![4.PNG](https://qiita-image-store.s3.amazonaws.com/0/191497/6d4b2be3-2dce-308a-5e9f-3ca09b4bb75e.png)

#2.Unity Pro packagesをダウンロード＆インポート
Unity Proと書いてありますが、5から無償提供されるようになったそうです！
![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/191497/520999b6-e0e4-c520-5058-cbe93112024b.png)

Asset>Import　Package>Custom Packageをクリック
![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/191497/663fa448-984b-27f3-d858-56f15248164f.png)

Kinect.2.0.1410.19000を開きます
![2.PNG](https://qiita-image-store.s3.amazonaws.com/0/191497/0fe8002a-0b48-66ef-a105-bb45283deb36.png)

Import！
![3.PNG](https://qiita-image-store.s3.amazonaws.com/0/191497/cd9a9219-57e4-4d4c-a544-7b7e369ec59d.png)

KinectViewをAssetフォルダにドラッグ＆ドロップしてください
![4.PNG](https://qiita-image-store.s3.amazonaws.com/0/191497/d5e934c0-6567-63f0-d956-e1b98dabb417.png)

APIの変更を自動変更するので、「I Made a Backup. Go Ahead!」をクリックしてください
![5.PNG](https://qiita-image-store.s3.amazonaws.com/0/191497/860a8808-4afe-fa90-4648-a74d5c62dba6.png)

Unityに入れたKinectViewのフォルダの中に「Main Scene」が入っているので開きます
![6.PNG](https://qiita-image-store.s3.amazonaws.com/0/191497/25d800be-8270-1f91-ec1e-f252fb29c9eb.png)

Kinectをつないで再生を押すと動きます！
![キャプチャ7.PNG](https://qiita-image-store.s3.amazonaws.com/0/191497/a33375d8-0d40-5460-4b04-ffb025186099.png)

今日はここまで！
IM-FormaDesigner 標準アプリ 過去バージョンを任意で使用する

##やりたいこと
新バージョン稼働後に旧バージョンアプリで新規登録を行いたい場合、どうしたら良いか

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/22172/ba7e4bb7-5796-e508-cc2c-afca39a262ad.png)

##前提
新バージョンを作ると新バージョンが強制的に使われ、新旧バージョンを並行して使うことが出来ないように見える
またim-workflowのように申請基準日によって旧バージョンを使うような仕組みが存在しない模様

https://www.intra-mart.jp/document/library/forma/public/forma_specification/texts/spec/forma_app_version_spec.html


##やりかた
Formaアプリにリクエストパラメータ**imfr_application_no**を指定するだけで良い
指定する値は**アプリケーション履歴番号**

http://localhost:8080/imart/forma/normal/view/regist_application_view/version_test?imfr_application_no=1
![2017-12-01_17h41_53.png](https://qiita-image-store.s3.amazonaws.com/0/22172/51544c23-2449-5ff0-778a-7a3dee4bcfd6.png)

例はGETだがPOSTでも大丈夫

ちなみに、何も指定しないともちろん新バージョンが表示される
http://localhost:8080/imart/forma/normal/view/regist_application_view/version_test?
![2017-12-01_17h41_58.png](https://qiita-image-store.s3.amazonaws.com/0/22172/1b10f319-e937-a6df-b1c1-00fd0131ecc6.png)


##注意事項
旧バージョンの有効日付がシステム日付内でないとエラーになる
並行運用期間は有効にしておく必要がある
Drawpile を用いた多人数同時描画作業方法


#古くなったのでちょっと書き換えたよ
Qiitaにあんまりプ関係無い記事置くのもアレかなぁと思ったのではてなブログ
https://ulufu.hatenadiary.com/entry/2020/05/06/031410
#ダウンロードリンク
英語が怖くても安心して
ソフトウェアは至極安全な日本語です
https://drawpile.net/download/
所持 OS のリンクを選んでダウンロードしてください
セットアップを起動すると日本語になるのでインストール方法は省略

##Drawpile の簡易的説明
超高機能お絵かきチャット

* 多人数同時描画作業可能
* ラスタ描画とベクタ描画の共存
* レイヤをユーザ毎に振り分け可能
* アニメーション機能
* 絵チャログの保存・再生が容易
* etc...etc...etc...

##絵チャのセッションを開始する

メニューバーの「セッション」から「ホスト...」を選択
![hostmenu.png](https://qiita-image-store.s3.amazonaws.com/0/212121/acd34bcb-79c6-fa76-7179-1979cec1009d.png)

セッション（絵チャ）を始める設定画面
![hostdialog-guide.png](https://qiita-image-store.s3.amazonaws.com/0/212121/336c08d6-2319-d600-5692-4b0ce6bccd85.png)
（画像は公式サイトからの引用）

タイトル：任意の名称（日本語可）
ユーザー名：任意の名称（日本語可）
パスワード（有無は任意）
ID alias：任意の文字列でセッションへのリンクを作成出来る

##Listing について 
Drawpile 公式のセッションリストへ公開するかどうかを選択
public：リスト一覧に公開される
private：ルームコードでのみ入室が可能

##サーバーについて
ビルトイン：自身のパソコンにサーバーを建て、セッションを開く
リモート：外部のサーバーを用いて、セッションを開く
Drawpile がパブリックサーバーを公開しているので、リモートのテキストボックスに drawpile.net と入力すれば利用できる

あとはホストボタンを押せばセッションが開始される

#募集方法
ウィンドウ右下あたりにある、IPアドレスを右クリック
IPアドレス、またはセッション用URLをコピーする
Listing においてチェックを入れた場合、ルームコードでの募集が可能
![dsadawdddww.PNG](https://qiita-image-store.s3.amazonaws.com/0/212121/bdc42cb3-e1ed-929f-fd4c-e5e53027b236.png)

##参加方法
ダウンロードを忘れずに
https://drawpile.net/download/
メニューバー「セッション」から「参加」を選択
![joindialog.png](https://qiita-image-store.s3.amazonaws.com/0/212121/28bc30e6-8d1f-5da1-7f3a-fd2628243c96.png)
Server にIPアドレス、またはルームコードを入力
ユーザー名は日本語可
参加ボタンを押して、セッションに参加完了


![raya.PNG](https://qiita-image-store.s3.amazonaws.com/0/212121/bf48272c-4442-ca3b-0970-8c1623ce80c0.png)
サイゴに……絵チャでかいたの
Twitter https://twitter.com/ulufu_ug
ReactNativeのデバッグ時の黄色の警告を隠したい

# Situation
`react-native run-ios`
もしくは
`react-native run-android`
でのデバッグ時

# Problem
<img width="377" alt="スクリーンショット 2017-12-01 17.17.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/151736/e3259727-37da-4843-e03a-c3fcf959eda5.png">

邪魔なこいつの正体はYellowBox.jsというらしいです

# Solution
エントリーファイルのindex.js || index.ios.js || index.android.jsに
`console.disableYellowBox = true;`
の1行を追加して解決ヽ(･∀･)ﾉ
アドレス変更したらWordPressの対応

EC2再起動したら、wordpressにアクセスできなかった。

原因：WordPressではサイトURLをDBに保存し、このURLが変更になってしまった場合、このDBの値を変更しないことです。

案1：DBの値修正(非推奨)
原因：wp_posts テーブル中にも 旧IPアドレスが含まれたリンクが残っている。

select * from wp_options where option_name = 'siteurl';
select * from wp_options where option_name = 'home';

UPDATE wp_options SET option_value='http://xxx.xxx.xxx.xxx/wordpress' where option_name = 'siteurl';
UPDATE wp_options SET option_value='http://xxx.xxx.xxx.xxx/wordpress' where option_name = 'home';

![1.jpg](https://qiita-image-store.s3.amazonaws.com/0/213567/4b6fd651-84b3-fd4d-5e7c-d45851b9880b.jpeg)

案2：wp-cli利用して、すべての旧urlも書き換えます。

参照文章：
https://www.agilegroup.co.jp/technote/wordpress-site-change.html
msSaveBlobが関数ポインタで参照実行できない（できました！）

# msSaveBlobが関数ポインタで参照実行できない
表題の言い方あってるかわかりませんが、以下が実行できませんでした。

```javascript
const downloadFile = ダウンロードして来たファイル;
const fileName = ダウンロードして来たファイルにつけるファイル名;
const msSaveBlob = document.defaultView.navigator.msSaveBlob;

msSaveBlob(downloadFile, fileName); //　エラー

document.defaultView.navigator.msSaveBlob(downloadFile, fileName); // 実行可能
```

**なんでこんなことしてるのかなどのバックボーンは一旦、置いといてもらえると助かります。 **

エラー内容は以下になります。

```
オブジェクトの呼び出しが無効です
```

`msSaveBlob`を`open`に変えてやって見たらできたので、記述方法は間違ってないと思いますが・・・
なんで実行できないんだろう・・・


**追記**
コメント頂きまして、こちら無事対応完了しました。
@jkr_2255 さんありがとうございます。

正しいコードは以下です。

```javascript
const downloadFile = ダウンロードして来たファイル;
const fileName = ダウンロードして来たファイルにつけるファイル名;
const msSaveBlob = document.defaultView.navigator.msSaveBlob.bind(document.defaultView.navigator);

msSaveBlob(downloadFile, fileName);
```
Twitter エタフォBotをGo言語で作ってみた

エタフォ、速攻いいねする奴です

anacondaってライブラリ使います

```go get github.com/ChimerCoder/anaconda```しておいてください

api制限とやらがあるらしいのでsleep入れてますtime.Sleep()の中の秒数はお好みでどうぞ

汚いソースですが↓

```go:エタフォ.go
package main

import (
	"github.com/ChimeraCoder/anaconda"
	"net/url"
	"fmt"
    "os"
	"time"
)



const (
	ck  = "コンシューマーキー"
	cs  = "コンシューマーシークレット"
	at  = "アクセストークン"
	ats = "アクセストークンシークレット"
)

func favo(){
	anaconda.SetConsumerKey(ck)
	anaconda.SetConsumerSecret(cs)
	cl := anaconda.NewTwitterApi(at,ats)
	v := url.Values{}
	v.Set("screen_name",os.Args[1])
	v.Set("count","5")
	v.Set("include_rts", "0")
	tls,_ := cl.GetUserTimeline(v)
	for _,tl := range tls{
		cl.Favorite(tl.Id)
		cl.ReTweet(tl.Id)
		fmt.Println(tl.Id)
	}

}


func main(){
	for{
		favo()
		time.Sleep(10 *time.Second)
	}
}
```

使い方
```go build エタフォ.go
エタフォ @スクリーンネーム```