OmniAICreator/Qiita-1.07M huggingface dataset:
オリジナルNEM切手の作り方と考察 

こちらの記事は２０２０年１２月１５日に作成したものです。


オリジナルNEM切手の作り方


〇作成目的
NIS１のウォレットアドレスを利用し、
日本の法律と紐付けることで複製することを禁じられた切手に内包できる。
発行期日を証明する。
発行した人、渡した人を明確にする。
という事が出来るのでないだろうかと考え作成しました。


〇作成方法
１．デザインを作成する
２．NEM-Walletを使用し、専用のウォレットアドレスを作成する。
３．日本郵便株式会社のオリジナル切手作成サービスを使用する。


以上２点で完結します。


デザインの作成は日本郵便株式会社のホームページにある内容に準じます。
郵便オリジナル切手窓口
https://www.post.japanpost.jp/kitte_hagaki/picture_stamp/index.html

ポイント
・JPG.PNGのみ画像対応
・著作、肖像権がある場合、著作者の書面が必要になる場合がある。

また、XEMの（Symbolじゃない）ロゴはCC0であるので許可、書面等は必要ありませんでした。
Symbolのロゴは商用以外自由（２０２０年１２月現在）という事ですので、NEM日本の窓口
で確認するのが良いと思います。



初期デザイン案
![1593906916id.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546181/fd896e92-c59b-15fb-decb-66906303f3b9.png)




![1593907033id.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546181/09f5c808-9ddf-8437-838c-8e9a10529e51.jpeg)




最終デザイン

![1594440181id.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546181/e06ae597-f9e6-089c-ccbd-2a706f614969.png)


![1594441110id.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546181/2b883f7f-cd24-4e67-e5cf-b3e47b46411f.png)


成果物

![1595642159imagetools0.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546181/dda765dc-6e5a-d1cc-21b5-dd592261cc9d.jpeg)




考察

【郵便局について】
日本郵便局オリジナル切手部門はNEMに関して調べたうえで連絡いただいたので
版権関係は電話での口頭でOKが出た。また、デザインも私自身が作ったので問題はなかった。
QRコードの切手は読めない可能性を考えて最大の大きさにしたが、この場合郵送物が持ち込みだったため、
消印は手押しだったため絵が見えるように局員が端っこに押して貰えた。
実験の為、私自身の住所にも送り、QQRコード切手がスマホで読めるかどうか試したが
正常に読むことができた。

【時間の証明】
０XEM送信されたメッセージを含むトランザクションは、トランザクション日時とメッセージ内容日時と紐付けられる。
郵便局から送られた切手に押される消印により、送付日時が証明できる。
消印、トランザクション日時、メッセージ内容日時それぞれが相互に時間証明となる。
万が一複製する者がいたとして、３つの日時をリンクさせることは不可能であると考える。
※ネームスペース（NIS１）を利用しない理由
ネームスペースは毎年レンタル更新があり、今後NEMの価格が大幅に上昇してしまった場合、純粋に更新を忘れた場合、
発行者が寿命により不在になった後の場合等、長期的に保有する「モノの証明」の場合、疑念が残る。

 

【モノの流通の明確化】
ウォレットアドレス、関連付けるモノを1対にし、それ以外に使わないことに関して以下のような活用が考えられる
今回最大３０個の景品セットを送付するが、送付対象者がNEMウォレットアドレスを持っている場合、もしくは作成した場合を
前提として、
①景品セットのウォレットアドレスから、各対象者NEMウォレットアドレスに０XEM送信
⇒送付対象者に対して、日時、送付内容物の履歴が半永久的に残る（NEMが無くならない限り）
⇒景品セットウォレットアドレスからいつどのアドレスに送ったか、いくつのアドレスに送っているかが明確になる
　シリアル番号の代価として扱えるのではないか
⇒また、各所有者は他所有者のウォレットアドレスが解るので、共通したモノを所有しているコミュニティーを作ることができる
　（※個人情報を調べることなくその気になればできやすい）


【まとめ】

NEM切手用QRコード切手

下記が実際のウォレットアドレス（アセットタグ）です。

NC4XC32BZGAPC7E6I7P2V6FYOMR723JPHJNPBRK4

XEMBOOK等で、内容を閲覧することができます。
http://xembook.net/xemmessage.html?address=NC4XC32BZGAPC7E6I7P2V6FYOMR723JPHJNPBRK4
テストと書いてしまったのですが、ここに今回送付したユーザーさん（本名じゃない）の
名前を刻ませていただいています。

刻んだその名前は過去のものとなり、改ざんされることなく半永久的にブロックチェーンNEMに残ります。
そして、手元に届いたQRコード切手によりいつでも第三者でもQRコードから辿れば、刻まれた情報を閲覧することが可能です。
QRコードを切手にし、モノに貼り付けることで　法に守られた、ネットとリアル（今回はNEM切手とその箱）を接続する
証明書となりえるのではないでしょうか。
現行機器の仕様を取り込み切れなかった話

# はじめに
「[本番環境でやらかしちゃった人 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/yarakashi-production)」に掲載する候補の1つだったけど、別にユーザ影響は与えてないからやらかしちゃってないなぁ～と思ってボツにした記事。

せっかく載せる記事の候補をリストアップしたので、公開してみようと思います。

# システムの概要
とあるシステムの全面更改案件があり、その時はネットワークチームのリーダとして案件に関わっていました。

元々のシステムの構築は別ベンダが担当しており、システム更改でベンダ変更を行うという案件になります。

ネットワーク構成としては、フロントエンドでWeb系通信を受け、バックエンドで各システムと連携するといったごく一般的な構成になります。

但し、Web系通信はインターネット通信網が2つあり、それぞれ別のページを表示させるような構成となっておりました。

# インフラ試験では出なかったのに
各フェーズすべて波乱万丈でしたが、、、試験フェーズまで辿り着き、何とかインフラ試験を終わらせて、アプリを入れた総合試験を実施時に問題が発生。

httpでアクセスしたとき、httpsにリダイレクトさせる総合試験で、一部端末だけhttpsにリダイレクトされないという問題が発生。

Webサービスのリダイレクト設定が間違ってるのかな？と当たりをつけて見てみるものの、設定上はうまくリダイレクトできそう。

# パケットキャプチャによるシーケンス調査
問題を追えないなら、パケットを追えばいい！

ということでパケットキャプチャを取ってサクッと調べてみると、Webサーバから想定通りのレスポンスは返している模様。

Webサーバの前にいる負荷分散装置は・・・正常にレスポンスを返しているようだけど、、、ん？

**送信パケットと応答パケットを受け取っているインタフェースが違う！**

今更ルーティングが抜けていたのか？と不安に感じながら現行のルーティング定義と見比べても、足りないルーティングは無く、差分は無いように思える。

# 問題の原因
結論としては現行環境で使っていた`BIG-IP`と今回導入した負荷分散装置の仕様の違いでした。

現行の`BIG-IP`では`Auto Last Hop`という**機器仕様**でうまいことレスポンスパケットを返していたのですが、今回導入した機器には機能が無かったので、試験フェーズまで発覚しなかったということでした。

`Auto Last Hop`の詳細は以前書いた以下をご覧ください。
※今回の件のことを書いてます。

- [BIG-IPのAuto Last Hop機能には気をつけろ！！](https://qiita.com/sakai00kou/items/da50f5aade1cdc930b3c)

# 解決案の検討
仕様の違いはどうしようもないとして、今回の機器には`Auto Last Hop`と同じような機能は無く、別の方法を考えなければ・・・

ここまで来て、`BIG-IP`に買い替える事なんてできない！！

## その１ 仮想ルーティング案
`Cisco`機器で言うところの、`VRF`(Virtual Routing and Forwarding)のような機能でルーティングテーブルを複数持てれば回避できるのでは！と思い調べてみたけど機能なし。

## その２　ポリシールーティング案
負荷分散装置からネットワーク網にレスポンスパケットを返す際、ポリシールーティングで制御すれば回避できるのでは！と思い調べてみたけど以下略。

・・・ネットワーク機器ならポリシールーティングくらいできても良いと思うんだ（愚痴

## その３　NAT案
アドレス変換すれば何とかできるのでは！と思い調べてみたけど、1対1で変換できるような数ではなく、1対多で変換したとしても、追跡が難しくなり、監査要件が満たせなくなるのでボツ。

あといくつか案を考えた気がしますが、どれもうまくいかずボツ。

# 最終的に
どうしようもないので、負荷分散装置とネットワーク網のルータ間に1本リダイレクト用ケーブルを敷設させて頂き、「[BIG-IPのAuto Last Hop機能には気をつけろ！！](https://qiita.com/sakai00kou/items/da50f5aade1cdc930b3c)」でも書いた通り、ルータでポリシールーティングをゴリゴリ書くことで回避しました。

# おわりに
機器固有の機能など使っていたり、特殊な方法で問題を回避していたような場合、移行時に思いがけない問題が発生することがあります。

今回はオンプレ機器で自システム内の機器設定を工夫することでどうにかできたからよかったですが、もし**クラウドへの移行等でこのようなネットワークの問題が発生した場合**はクラウド側で対応しきれず、影響が大きくなるのではないかと思います。

クラウド移行だけの話ではないですが、移行時には、機器の仕様やトリッキーな設定に注意しましょう。
ALAsset の thumbnail メソッドでの画像取得は止めたほうがいい

# はじめに
この記事は iOS Advent Calendar 2020 の 14 日目の記事です。 

私が開発してるアプリは iOS 7 をサポートしていた時期もあり、 ALAsset が使われている画面もあります。この ALAsset は端末内の写真やビデオを扱うためのクラスで、現在は PHAsset に置き換わっているため Deprecated になっています。 このクラスが iOS 14 からいよいよサポートされなくなってるなと感じるバグが発生し修正作業に追われたため、この記事を残します。

# 発生した現象
この問題が発生したのは写真一覧画面でした。 この画面では写真ライブラリにアクセスするため、 iOS 13 以前ではアクセス時に写真ライブラリの使用を許可するか聞かれるダイアログが表示されており、

- OK
- 許可しない

の選択肢がありました。 iOS 14 ではこのアクセスレベルが変更されており、

 - 選択した写真のみ
 - すべての写真
 - なし

の選択肢が表示されます。この選択肢の「すべての写真」を選ぶと写真ライブラリに保存されている全ての写真を表示することができ、「なし」を選ぶと1枚も写真が表示されないことは確認しました。が、「選択した写真のみ」を選んだにも関わらず、この画面では選んだ写真を表示することができませんでした（写真のパスを取得することはできる）。

ちなみに、この問題は Xcode 12 でビルドしていなくても、 iOS 14 端末で動かすと必ず発生します。ですので知らない間に影響を受けてる可能性があるので、 ALAsset を使っている方は一度確かめてみるのが良いと思います（「すべての写真」を選んでれば影響を受けないので、クリティカルな問題では無いと思いますが）。 

# 原因
コードを追っていくと、

```objective-c:CollectionViewCell.m
    CGImage *cgImage = [asset thumbnail];
    self.imageView.image = [UIImage imageWithCGImage:cgImage];
```
上記のコードの cgImage が nil になっていることがわかりました。「すべての写真」を選んでいると thumbnail メソッドで画像を取得することができていましたが、「選択した写真のみ」を選んでいると取得できなくなっていました。

この thumbnail メソッドについて [Apple のドキュメント](https://developer.apple.com/documentation/assetslibrary/alasset/1615879-thumbnail)を呼んでみると、`「 This method returns NULL for assets from a shared photo stream that are not yet available locally. （このメソッドは、まだローカルで利用できない共有フォトストリームからのアセットに対してNULLを返します。）」`と書かれていました。ここの判定がそれぞれの選択肢を選んだときで変わったみたいですね。

# 解決方法
PHAsset に置き換えましょう！！！
一応、

```objective-c:CollectionViewCell.m
    CGImage *cgImage = [[asset defaultRepresentation] fullResolutionImage];
    self.imageView.image = [UIImage imageWithCGImage:cgImage];
```
とすることで画像を取得できることは確認しましたが、わかりにくいやり方ですし Deprecated を無理矢理しのぐのは今後またバグになる可能性が高いです。幸い私は別 ViewController で PHAsset を使っている画面があったので、その画面に置き換えることで対応しました。

# まとめ
ということで、 iOS 14 になったことで知らない間に ALAsset を使っていた画面で写真が表示できなくなっていた、という記事を書きました。今時 ALAsset を使っている方がどのくらいいるのかわかりませんが、同じような境遇の方の助けになっていましたら幸いです。
以上で、 14 日目の記事は終了します。ありがとうございました！!
AWS Lambda で大量データをBatch処理した話と注意点

本記事は「[AWS LambdaとServerless Advent Calendar 2020](https://qiita.com/advent-calendar/2020/lambda)」の17日目の記事です。




# やりたいこと

- Amazon Redshiftにある10億レコードを越えるデータを1レコードずつ、特定の列を判定したりという、シンプルな処理だが全レコードを見ていく必要のある処理をしたい

# 従来やってた方法
- RedshiftからSQLでELTしてUNLOAD
- UNLOAD結果をEC2へS3からダウンロード
- JavaやPythonなどのプログラムでバッチ処理実行
- 結果をS3に格納

この方法でも良かったのですが、大規模データをEC2で高速に並行で処理する、、、前に少し考えてみると、あれLambdaが相性良いのでは？と思い試してみました。

# 具体的な方法
- MAXFILESIZEを指定してUNLOAD
- UNLOAD先をLambdaのイベントトリガで発火

## Lambdaのおおよそのコード
```
def lambda_handler(event, context):
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
    outputdata = "";
    try:
        dlfilename ='/tmp/'+key.replace("/","")
        s3client.download_file(bucket, key, dlfilename)
        gzipfile = gzip.open(dlfilename, 'rt') 
        csvreader = csv.reader(gzipfile, delimiter=SEP, lineterminator=L_SEP, quoting=csv.QUOTE_NONE)
        for line in csvreader:

        #略

        uploadbinary = gzip.compress(bytes(outputdata , 'utf-8'))
        obj = s3resource.Object(processedbucket,processedkey)
        obj.put( Body=uploadbinary ) 
    except Exception as e:
        print(e)
        os.remove(dlfilename)
    os.remove(dlfilename)
```

流れとしては、gz圧縮でUNLOADされたファイルをダウンロードし、処理したものをgzip圧縮し、再びS3に格納しています。

## Redhisftのクエリ

```
（割愛）
PARALLEL ON gzip MAXFILESIZE 50MB allowoverwrite;
```
この時のUNLOAD先を、先のLambda関数のトリガに設定します。


# 注意点
## タイムアウト
Lambdaは最大実行時間が15分のため、それ以内で収まるファイルサイズでのUNLOADが必要です。もちろん15分ギリギリは狙わず、余裕を持たせて終わるサイズでチューニングするのが良いと思います。

## メモリ不足
アウトプット用のファイルデータをつくっていくうちに設定したメモリを越えるとOutOfMemoryErrorとなります。
ちょくちょく以下のようなものでデバッグしました。

```
    print("memory size at outputdata:"+str(sys.getsizeof(outputdata)))
```

対策としては、メモリが上がると処理性能も上がるようなのと、多少のお金を掛けてエラーが減るならありと考え、今回の処理においてはギリギリをチューニングする意味は無いと考え、最大値の3008MBで全振りしてました。
（って書いてたら12月のアップデートで10,240MBまで上限がアップしておりました...）

今回の場合、データセットの特殊性も相まって事前のファイルサイズから処理後のデータ量が読み辛く「想定の倍」くらいにしています。それが丁度3GBくらいだったので、当時の3008MB全振りが丁度よかった感じです。


## ディスクサイズ不足
Lambdaの/tmp ディレクトリのサイズは512MBです。
当然ですが、MAXFILESIZEを指定せず＝分割せずにUNLOADして処理結果がこれを越えるとダウンロード時点でエラーとなります。

また、開発時にハマった点としては「予期せぬエラーで終了した時にファイルが消えてない状態」になり、その後コンテナが再利用されると、イベント自体は別のものでも過去に処理したファイルが残っている、という点です。
1コンテナで複数のイベントは処理されないことは保証されているのですが、イベントが終わった時に例えば/tmp/領域が綺麗になる訳では無い、ということですね。


なのでディスクサイズにおける対策は
・適切に小さいファイルサイズで処理する
・/tmp/を都度消す処理を入れる
と2点になるかと思います。開発時点ではEFSでハンドリングしやすくするのもありなのかもなぁ、と思わなくもないです。

適切なMAXFILESIZEのMB数があるかとは思うのですが、処理するデータの中身次第で処理の重さが変わることがあった点に加え、大きめのメモリで速攻で1イベントを終わらせる分にはコストが跳ね上がることもないため「メモリ多め」「ファイルサイズ少な目」というざっくりとしたチューニング方針を採りました。


# 感想
無事安定稼働しています。サーバーレスということで、気を遣わなければいけない点はあるものの、並列部分を任せられるのはやはり大きいですし、1並列あたりの処理も512MBという十分なファイル容量と潤沢なメモリは魅力的ですね。文中に書いてある2020/12のアップデートによる10,240MBのユースケースが気になります...
Twitterでバズってるやつは本当に仕事ができるのか？

あなたの社内に、Twitterで有名な人はいませんか？

先日、デザイナーの@makiyo-miyataさんと雑談をしていた中でこんな話が出ました。
**「Twitterでバズってるやつ本当に仕事できるのか？」**
というか身の回りに「この人の仕事っぷりはすごい…尊敬…」と思う方、軒並み誰もTwitterやってない。もしくは全然呟いてない。このギャップはなんだろうという疑問から出た説です。

ちなみに弊社POLにはTwitterのインフルエンサーはいません。多分。いたらごめんなさい。

でもTwitterで有名な人、仕事できそ〜かっこい〜って思いますよね？私は多少思います。
呟くのってアウトプットの機会でもあるので、良質なアウトプットを出すために良質なインプットをTwitterでやっているのかな？Twitterをやらないと見えない景色があるのかな…と思うようになりました。

というわけで、まずは自分がペルソナになるところから。Twitterを始めました。
(アカウントはバレたくないので伏せます。特定したとしても知らせないでください！)

**1日目 初ツイート**
![スクリーンショット 2020-12-13 22.07.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309411/fb4bd2ce-861d-6cd0-7825-0e31254a8603.png)
バズらせ目的で呟くことは人生でなかったので緊張…
1ツイート目にしては悪くないかなという感じですが、バズってるとは言えないですね。

**3日目 ウケる法則が見えてくる**
いくつか呟いて、大体パターンがわかってきました。
>・RTした時、その投稿内容が自分の意見だと思ってもらって構わないものは拡散されやすい。
・時期性に沿うのはいい。
・投稿の時間帯は出勤時間/退勤時間あたりは初速がいい。
・やっぱりフォロワーが多い方にRTしてもらうのが手っ取り早い

マーケティング部署にいた頃に得た知見をすべてTwitterに活かしていきます。マーケ部もこんなことに知見使われるとは思ってないだろうな。反応率、いいね率、RT先のご意見などを見て、定性/定量調査も行います。デザイナーの得意領域ですね。


**4日目 Twitterに支配され始める**
このあたりから完全にフックモデルのサイクルにハマります。私がTwitterを動かしていたはずなのに、Twitterが私を動かしているような…
このまま続けると習慣になってしまう…嫌だ…こんなの嫌なのに…
![picture_pc_d64f3e492b45feae844e789d896a3b68.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309411/481e1c29-16af-5877-b3d0-a2ca4ccabd55.jpeg)

**5日目 コツを掴み始めるが…？**
![スクリーンショット 2020-12-13 22.07.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309411/703f4262-de48-2f41-1645-83e25ac02385.png)
コツを掴み始みます。他の呟きも100〜3000いいねを行き来して、フォロワーも数百人に増えてきました。それと反比例するかように仕事のパフォーマンスが悪くなってきました。

**6日目 マジで悩みのタネになり始める**
そしてとうとう社内SlackでTwitterとの付き合い方をお悩み相談とかする始末。中学生か？
![スクリーンショット 2020-12-13 19.24.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309411/56ef8464-8518-390c-a576-26ea92159568.png)


**7日目 自己肯定感が低くなってくる**
ここらへんでTwitterで時間を取られるのが、というより仕事で思ったようなパフォーマンスを出せなくなるのが本当に嫌になっていきます。自己嫌悪が強くなっていき「Twitter　頻度減らす　方法」でググるなどするように。アプリやブラウザをすべてログアウトし、朝起きた時と夜寝る前だけと決めました。仕事のパフォーマンスが戻ります。一安心か…？

**9日目 再発**
全然だめ。Twitter開いちゃう。しかも「バズる」が目的なので目標を達成するにはどうすればいいのかを常に考えるように。嫌だ　こんなの私じゃない　やめろ　離せ

**10日目 解放**
![スクリーンショット 2020-12-13 22.06.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309411/0b71c5c3-6827-ceff-e554-968bb42f50da.png)
1万件のいいね！ これはバズったと言ってもいいのでは。というかこれで許してほしい。フォロワーも2000人超えで着地。良かった〜〜終わった〜〜〜〜



##【結論】Twitterでバズってるやつ、多分仕事してない

これ呟く以外のリソースがすっげ〜〜〜〜〜取られる。
調査という名のエゴサの時間、分析の時間、アウトプットを考える時間…心と脳のキャパを思ったよりずっと多く取られてしまいます。
当然ですがフォロワーの数=ビジネスマンとしての出来は必ずしもイコールではないです。こんなのずっと続けて仕事になるもんか。
あとスマホ見すぎて肩こりが悪化しました。

一緒に仕事をしていて尊敬できる方は、Twitterをやらない時間でインプットしたり、仕事のことを考えているからなんだと思います。尊敬の念は強まるばかり。ここで冒頭の「弊社POLにはTwitterのインフルエンサーはいません」に繋がるわけですね。オタクなので伏線回収が大好きです。

とはいえ、己を律せる人/仕事が評価されて有名な人/Twitterが仕事みたいな人ももちろんいるので、一概に仕事してないとは言えないですね。採用や広報として機能させている方は理性が強い すごい

Twitterをやったら見える景色、身を持って体験できたので、アカウントは消そうと思います。
社内メンバーへ私は中バズ主だぞという証拠も残せてよかったです。私は中バズ主だぞ！
Twitterやってる時間で本とか読んだほうが良いです。当たり前体操。それでは。



次回は@takahashik0422さんお願いします！
Athenaの実行結果を通知をLambdaから実行するときにやって良かった通知機構

# 概要
EventBridgeでAthenaの結果を受けとり、StateがFAILEDだった場合にSlackに確認できるコマンドの通知を行っています。


[こちらの記事](https://qiita.com/yuji_saito/items/d8303d2d8669e9a35ab8)で書いたものと一緒に運用したのですが、以下のようなSlack通知をすると便利ですよ、という話です。


# コード
だいたいこんな感じのメソッドです。

```
（略）

if currentState == 'FAILED' and previousState =='RUNNING' :
    post_slack("query_execution_id:"+query_execution_id+" is got FAILED. Please check with the following command [ aws athena get-query-execution --query-execution-id "+query_execution_id+" ]")


def post_slack(msg):
    message = msg
    # 弊チームでは :squirrel: が人気です。
    send_data = {
        "username": "EventBridgeから来たエラー",
        "icon_emoji": ":squirrel:",
        "text": message,
    }
    send_text = "payload=" + json.dumps(send_data)
    request = urllib.request.Request(
        "https://hooks.slack.com/services/XXXXXXXXXXXXXX", 
        data=send_text.encode("utf-8"), 
        method="POST"
    )
    with urllib.request.urlopen(request) as response:
        response_body = response.read().decode("utf-8")

```

# 特徴
FAILEDになるとSlackの専用チャンネルに
```
aws athena get-query-execution --query-execution-id xxxxxxxx
```
が来ます。

特にどういったクエリが実行されるか分からない中で `Query exhausted resources at this scale factor` を把握していけるのは、クエリ改善において大きいです。


# 余談
EventBridgeで受け取れる情報だけで実現しているため上記のようになっていますが、ここで更にGetQueryExecutionを使って、直接エラー内容をSlackに貼りつつ、RDSなどに成功、失敗ともに結果を格納していく、みたいなこともやりたいなと思っています。
EventBridgeでAthenaの実行結果を受けとると完了待ちのポーリングが不要となる話

本記事は「[AWS その2 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/aws2)」の17日目の記事です。

# 内容

今年2020年の3月より、[Athenaのクエリの状態移行がEvengBridgeに対応](https://aws.amazon.com/jp/about-aws/whats-new/2020/03/amazon-athena-now-publishes-cloudwatch-events-for-athena-query-state-transitions/)しました。

つまり、これを使えば従来のように「forループでGetQueryExecutionを実行してAthenaの実行完了を待つ...！！」というポーリングが不要となります。革命ですね。
また、もしLambda経由でAthenaのクエリを実行などをする場合は、Lambdaの起動時間が圧倒的に節約されます。

# 設定方法

## とりあえずLambda関数を用意する
EvengBridgeでルールを作成するときに、Lambda関数を選択する項目があるため、先に関数を用意しておきましょう

おおよその最低限の処理

```
def lambda_handler(event, context):

        currentState=event_dict['detail']['currentState']
        previousState=event_dict['detail']['previousState']
        query_execution_id=event_dict['detail']['queryExecutionId']

        if currentState == 'FAILED' and previousState =='RUNNING' :
           # 失敗した旨をSlackなどで通知する
           （割愛）

        if currentState == 'SUCCEEDED' and previousState =='RUNNING' :
           # query_execution_id を元に後続処理をする
           （割愛）
```

一応 previousState も見ていますが、SUCCEEDED or FAILEDだけ見ても良いのかもしれません。

いずれにせよ

```
print(json.dumps(event))
```
みたいな感じでeventの中身を一度見ると掴みやすいです。公式ドキュメントは[こちら](https://docs.aws.amazon.com/athena/latest/ug/athena-cloudwatch-events.html)です。

後続処理に紐づけ得る情報が揃っているかを確認します。言い換えると、当然ながら EventBridgeで通知されるイベント内容を元に、全体設計をする必要があります。


## EvengBridgeへ移動
ちなみにかつてAmazon CloudWatch Eventsと呼ばれていたものが、いまはAmazon EventBridgeと名前を変えています。

### イベントパターン
イベントパターンを選択し、AWS→Athena→すべてのイベント、を選択します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68734/38a13586-9d1d-bc55-8684-ece1bd7697c3.png)


### ターゲット
ターゲットとして「Lambda 関数」を選択し、機能という欄にLambda関数が一覧で表示されるのでここで選択します。

この後、ルールを作成すると**自動的にLambda側にもトリガが設定されます**。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68734/9f8bb74c-f69a-26af-3b7d-29bf1089fe6f.png)

# 注意点
## 何をもって処理対象とするかの判定の話
この機構を使うのであれば、Lambda経由の実行のためのワークグループなど、専用のワークグループを作成しておく必要があると考えます。
手動で流したものから何から拾ってしまうため、組織内などで利用する場合は特に注意が必要となります。

例えば1つしかワークグループが無い中で無条件で queryExecutionId を元に後続処理をしてしまうと、手動で流したクエリもその処理に乗ってしまいます。


簡易な設定としては「カスタムパターン」を選択して、以下のような形にすることでワークグループで絞られます(またはAWS→Athenaを選択したあとに「編集」をすると自動的にカスタムパターンとなります)。

```
{
  "source": [
    "aws.athena"
  ],
  "detail-type": [
    "Athena Query State Change"
  ],
  "detail": {
    "workgroupName": [
      "xxxxxxxxxx"
    ]
  }
}
```

# 運用してみて
注意点は一定あるかと思いますが、Lambda経由でAthenaを実行をしたいケースではLambda上でポーリング処理を持つと、Lambda自体のタイムアウトなどを含めどうしても綺麗にならない点がある点が、EventBridgeによりだいぶスッキリしました！
Amazon Athenaで遭遇した、FAILEDにおけるエラーメッセージ集

# 概要
Athenaを使っていると様々なエラーに一定確率で遭遇します。
使っていて見かけた、State:FAILEDになったときの、StateChangeReason、要はエラーメッセージを一覧化してみました。

# 基本方針
あくまで私が使っているデータセットでは、ですが

- 再実行して返ってきたら「調子が悪かったんだな」と思ってスルー
- 再現性があれば調査、問合せ

という形を取っています。

実際にはファイル破損などにより発生することがあるようなのですが、それと同様のエラーメッセージでも2回目以降は成功したりするためです。
※実際そのようなもので必ず2回目以降も再現するエラーは今のところ発生しておらず、ある種、安定、安心しています。

というわけで以下の通りとなります。

# 一覧

## Query exhausted resources at this scale factor

厄介なやつです。本エラーが出るケースを2通り観測しており

1. EngineExecutionTimeが比較的短い場合で発生
→再実行で成功することが多い＝Athenaの調子がたまたま悪かった

2. EngineExecutionTimeが長い場合
→再実行でも失敗することが多い＝クエリ改善が必要

となります。後者の場合は再現性がある場合が多く、クエリ改善の戦いが始まります。

## Query timeout
Query改善をしましょう...

## SYNTAX_ERROR
SYNTAX_ERRORはものによってはクエリ開始時にエラーとなるものもありますが、Column 'xxx' cannot be resolvedなどは実行され、SYNTAX_ERRORとしてエラーが流れてきます。


## Amazon Athena experienced an internal error while executing this query. Please try submitting the query again and if the issue reoccurs, contact AWS support for further assistance. We apologize for the inconvenience.

これは記載の通りですね。


## [ErrorCode: INTERNAL_ERROR_QUERY_ENGINE] Amazon Athena an experienced an internal error while executing this query. Please contact AWS support for further assistance. You will not be charged for this query. We apologize for the inconvenience.

問いあわせよと言われましたが、再実行で上手くいきました。

## GENERIC_INTERNAL_ERROR: Unable to （直接裏のプログラムの例外が書きだされるケースのため略...ver1/略）
とてもドキドキしますが、再実行で大丈夫でした(1)


## GENERIC_INTERNAL_ERROR: Unable to （直接裏のプログラムの例外が書きだされるケースのため略...ver2/略）

とてもドキドキしますが、再実行で大丈夫でした(2)。


## GENERIC_INTERNAL_ERROR: Could not decompress page
これも一瞬ｳｯとなりますが、うちのデータセットでは再実行で大丈夫なケースが全てでした。


# 感想
うちのデータセットでは結構複雑なJOINを連発していたりするので、それが起因しているものが多いのかなぁ、とは思っているのですが、頻度が高い訳でもないのと、前述の通り再実行でOKな場合がほとんどなので、安定しているな～という感想を持っています。
Python学習 基礎編　~型変換とは？~

こちらはPython学習の備忘録です。
プログラミング初心者や他の言語にも興味、関心をお持ちの方の参考になれば幸いです。
* * *
###型変換とは？
まず型変換を説明する前にデータ型の説明が必要でしょう。
データ型とは、プログラミングで扱うデータの型のこと。

たとえば変数へ代入した値（オブジェクト）によって、この変数のデータ型が決まる。つまり数値、文字列など、どのようなタイプのデータかということ。

またデータ型には、さまざまな種類が存在する。
いわゆる「文字列型」、「数値型」などなど。
詳しく書いていくとかなり長くなりそうなので今回は省かせていただきます。

そして、このデータ型が異なるとコードは異なる動作をする。
そのため、型変換が必要になってくる。

```py:script.py
print(2 + 2)  # 数値の計算
# 実行結果
4
print('2' + '2')  # 文字列の連結
# 実行結果
22
```

異なるデータ型である「文字列型」と「数値型」を連結するとエラーになる。

```py:script.py
price = 1000
print('この本の価格は' + price + '円です')  
# 上記は(文字列型 + 数値型 + 文字列型)となり異なるデータ型の連結

# 実行結果 
# エラー : 異なる型同士の連結はできない
TypeError: Can't convert 'int' object to str implicitly
```

####型変換 str
しかし、下記のように変数priceを出力する際に「数値型」から「文字列型」へ変換してあげると、文字列同士の連結として扱われるため連結できるようになり、このデータ型を変えることを「**型変換**」という。

「数値型」を「文字列型」に変換するには「**str(　)**」と用いる。

```py:script.py

price = 1000
print('この本の価格は' + str(price) + '円です')  
# 上記は(文字列型 + 文字列型に変換 + 文字列型)となり連結可能

# 実行結果 
この本の価格は1000円です
```
####型変換 int
先ほどとは反対に、「文字列型」を「数値型」に変換する場合は、「**int(　)**」を用いる。

```py:script.py
price = 1000
count = '5'  # 文字列型
total_price = price * int(count)  # 数値型に変換
print(total_price)  

# 実行結果 
5000
```
* * *
###おわりに
本当に初歩的な内容となっていますので、今後、学習を進めて行った際にはあらためて記事にしたいと思います。
また、何かあれば遠慮なくご指摘お願い致します！！
NAを使いたくてDataArraysを使うと[Failed to precompile DataArrays]

結論からいうと
DataArraysはduplicatedされていて非推奨とのことです。
https://github.com/JuliaStats/DataArrays.jl

えっじゃあNAはどう扱うのと思ったので調べてみました。

##環境
macOS Big Sur version11.0.1
julia version 1.5.3




###Missing型を使おう
https://dataframes.juliadata.org/stable/man/missing/

NAではなくmissingだそうです。

なんだかただの文字に思えますがちゃんと値です。

```julia
typeof(missing)
```
![スクリーンショット 2020-12-12 15.17.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573500/0af60e18-d2b4-f770-dc22-753a75530c21.png)


Missing型と表示されました。

ではpandasでやるところのdropnaをやってみましょう。
juliaではdropnaではなくskipmissingを使います。


```julia
x = [1, 2, missing]
skippmissing(x)
```

![スクリーンショット 2020-12-12 15.25.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573500/d301092f-7cfe-2c9e-367c-a20aeb6df03d.png)


この出力は直接関数に渡すことができます。
missingを取り除いたArrayが欲しいときはcollectを使用します。

```julia
collect(skipmissing(x))
```
![スクリーンショット 2020-12-12 15.30.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573500/4693302b-8134-a255-8c65-07a0b8c083ee.png)

missingを除去できました！
検証環境のURLが入ったメールを本番環境のユーザーに送ってしまった話

この記事は「[本番環境でやらかしちゃった人 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/yarakashi-production)」24日目の記事です。
遠い昔、はるか彼方の銀河系での話です。


## TL;DR

IAMの権限はしっかりやりましょう。検証環境と本番環境でアカウントを分けるとより安心できます。


## 何をやらかしたのか

### やらかし前の状態

マッチングサービスの開発をしています。そのサービスにはサービス内でメッセージが届くとその旨をEメールで通知する機能があります。
システム的にはサービスを動かしているWebアプリケーションからSQSのメール用のキュー（以後Maill Queue）にメッセージを送信し、メール送信用のWorkerがMaill Queueからメッセージを取得、差出人やURLなどの情報を埋めてEメールを送信します。差出人やURLは本番環境、検証環境でそれぞれ別の値が入ります。

![qita.001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63855/92ee63d2-cf77-fea6-9900-fb75b5cf1fd5.png)


また検証環境と本番環境は同一のAWSアカウント内にあり、WebアプリケーションとWorkerが動いているEC2インスタンスは検証環境と本番環境共に東京リージョン（ap-northeast-1）。その他のリソースは本番環境は東京リージョン、検証環境はオレゴン(us-west-2)に作成されていました。Maill Queueのリソース名は検証環境、本番環境共に同じでした。

![qita.002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63855/0a786fca-a68f-b208-e0f1-cedd6e60a1b4.png)


### やらかしたこと

ある日EC2で動いていたWorkerをFargateへ移行することになりました。WebアプリケーションにはどのリージョンのAWSリソースを参照するか設定する場所があるのですが、移行の際にその設定が漏れてしまいました。
設定が漏れてしまった結果、検証環境のWorkerが本番の東京リージョンのMaill Queueからメッセージを取得してしまいました。

![qita.003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63855/bbd69409-7629-28e5-8236-06baa7ca4eda.png)



### やらかした結果何が起きたのか

検証環境のWorkerが本番環境のMaill Queueからメッセージを取得したことにより、検証環境のURLを埋め込んだ状態で本番環境のユーザーにメールを送ってしまいました。
正しいURLではありませんし、検証環境はそもそも接続できるIPアドレスを絞っているので、ユーザーはメールで送られてきたURLを開くことができません。


### 二度と惨劇を起こさないためにどうしたのか

まずEC2インスタンスのIAMロールの権限の見直しを行いました。
検証環境と本番環境のEC2インスタンスのIAMロールにはSQSFullAccess がアタッチされており、全てのリージョンのSQSにアクセスできる状態だったので、アクセスを制限しました。

次に検証環境と本番環境でAWSアカウントの分割を行い、権限周りでミスがあっても同じことが起こりにくい状態にしました。


### さいごに

いろいろと助けてくださった方々、本当にありがとうございました。。。

明日の [本番環境でやらかしちゃった人 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/yarakashi-production) は @tsumita7 さんの「S3「 お゛め゛ぇ゛に゛権゛限゛ね゛ぇ゛がら゛！」」です。
心理的安全性を超高める方法

[Phoneappli Advent Calender 2020](https://qiita.com/advent-calendar/2020/pa_engineers) の15日目

今日は私の4X回目の誕生日です。
誕生日なんてもう二度と来てほしくない、と毎年思う年頃ですけど、
こうして、ここに書く動機と機会を与えてくれた皆様に感謝です。
Google Homeもお祝いしてくれました。

そしてPHONE APPLIに入社してからも、ちょうど1年になります。
テストプログラマー見習いとして、日々IntelliJをインストールする毎日です。

この会社で思うのは、エンジニアの皆さんがとても落ち着いていて、
難しい仕事や人生の話を聞いて感心するたびに、
自分の幼さと切なさと心弱さを感じます。

それと、、、そう、心理的安全性ってあるじゃないですか。

PHONE APPLIの人は良く話を聞いてくれるし、優しい人が多いので、
とても心理的安全性の高い会社だと思います。

でも、世の中には、心理的安全性が低い会社も多いですよね。

それをどうやったら高められるか、っていう話。

いろいろあるんですけど、心理的安全性を考える前に、
「物理的」安全性
を高める時はどうやってるのか、考えてみたんですよね。

鋼の鎧を身に着けたり、フルフェースのヘルメットかぶったりして、
しっかりと身の守りを固めるほうが、物理的には安全ですよね。

同じように、守りを固めることで、心理的安全性を高めることが
できるんじゃないかって、思ったんです。

ところが、心に鎧を着たり、ガードを固めて閉ざしたりってのは、
やっちゃいけないよって、インターネットのみんなは言うんですよ。

「思ったことを素直に言って、心をオープンにしよう」、とか、
「助け合える雰囲気を作ろう、風通しの良い組織にしよう」、とか、とか。

それって要するに、非暴力主義なのかなって、感じています。

発想がちょっとナイーブなんだよね。農耕民族というか。
悪くないと思うけど、ビジネスで競争するには、ちょっと頼りなくてね。

確実に心理的安全性を高めるには、誰の意見にもゆるがない、
強靭な精神力をみんな身に着けるほうが、簡単だし強いと思うわけ。

強靭な精神力の持ち主っていえば、ドラゴンボールの孫悟空かな。

＊＊＊＊（うぃぃーん）＊＊＊＊

（悟空）「おっす、オラ悟空！。。。今日は一人遅刻みたいだけど、
　時間だから、デイリーミーティングをはじめっぞ！」

（悟空）「まずはオイラからだな！。昨日ドラゴンボール3つ集めてハラ減っちまった！
　夕方のレビューまでに、みんなオラに元気を分けてくれ！」

（悟飯）「昨日はピッコロさんと修行。今日は午後から魔人ブゥと戦ってきます。」
（悟空）「ヒェーッ、おっかねぇなあ。おめぇ、ブッ殺されっちまうぞ！」

（悟空）「最後はフリーザ！」

（フリーザ）「、、、あなたたち、話長すぎて15分すぎてしまいましたね。殺しますよ。
　今日こそは、木っ端微塵にしてやる、あの地球人のように！！！」


（悟空）「クリリンのことかーーーーー！！！」
npmパッケージのjqueryをブラウザで使えるようにする


参考:https://designsupply-web.com/media/knowledgeside/5915/

# npm経由でjQueryをインストール

```
/*
$ npm install --save jquery
*/
```
```package.json
{
 ..........
 "dependencies": {
  "jquery": "^3.4.1"
 },
 ..........
}
```
jQueryのモジュールをrequire()で読み込んで、jQueryを使ったコードを書いてブラウザで確認してみるも。。。

```resources/js/jquery.js
const $ = require('jQuery');
$(function(){
 alert("jQueryを読み込みました！");
});

```
コンソールでエラーが表示されてしまいました。どうやら、require()が使えないとのこと。
実際のソースコードを確認してみると、jQueryのライブラリのソースコードは読み込まれていませんでした。

```
Uncaught ReferenceError: require is not defined
```
このrequire()はNode.jsの環境で使えるもので、ブラウザ側では読み込むことができません。そこで「Browserify」というパッケージをインストールすることで、ブラウザ側でもrequire()を使えるようにしていきます。

# Browserifyのインストール

```package.json
{
 ..........
 "dependencies": {
  "jquery": "^3.4.1"
 },
 "devDependencies": {
  "browserify": "^16.5.1",
  ..........
 }
 ..........
}
```

Browserifyをインストールすると、下記のコマンドで、require()で指定したモジュールのソースコードを読み込んだソースコードを生成してくれます。

```
browserifyの後に「対象となるソースファイル」続けて「-o」オプションの後に、ビルド先を指定して、「生成するソースコードファイル」を指定します。

$ npx browserify resources/js/jquery.js -o public/jquery/jquery.js
```

あとは適宜htmlで読み込んで使用！
Pythonで任意の定義域を持つヒートマップの作り方

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/336bf861-b7e0-50a1-411b-57b215ab49b2.png)

　$f=(x,y)$的なデータを図示するにあたって、[ヒートマップ](https://ja.wikipedia.org/wiki/%E3%83%92%E3%83%BC%E3%83%88%E3%83%9E%E3%83%83%E3%83%97)は強力な手段です。

　Pythonでは`seaborn`が有名ですが、xとyの定義域がそれぞれ`1,2,...`に限定されてしまいます。どうせなら任意の定義域でやりたいですよね。[scikitlearnのサンプルコード](https://scikit-learn.org/stable/auto_examples/classification/plot_classifier_comparison.html)を参考にしたやり方を解説します。

# 不格好だけどあらゆる関数に対応できるやつ

```python
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(-2,2,0.1)
y = np.arange(-2,2,0.1)
xx,yy = np.meshgrid(x,y)
z = np.zeros((len(x),len(y)))
for i in range(len(x)):
    for j in range(len(y)):
        v = np.array([xx[i][j],yy[i][j]])
        r = np.linalg.norm(v)
        z[i][j] = np.exp(-r)
plt.figure(figsize=(5,5))
plt.contourf(x,y,z,cmap='coolwarm')
plt.show()
```

　for文の中身が実質的な$f(x,y)$になっていて、上のサンプルコードでは例として、

$$
f(x,y) = e^{\frac{-1}{\sqrt{x^2+y^2}}}
$$

　を実装しています。煩雑なので3行に分けていますが、やっていることは同じです。

　これはあらゆる関数に対応可能ですが、for文を使っているのがいかにも不格好です。何より、行列を一回かければ大丈夫なパターンや、各種機械学習の予測モデル（だいたいはデータ数 x 入力ベクトル）の形に対応していないので不便です。

# データ数 x 入力ベクトルの形に直したやつ

```python
import numpy as np
import matplotlib.pyplot as plt

def model(xy):
    ar = np.array([-2,1])
    return np.matmul(xy,ar)

x = np.arange(-2,2,0.1)
y = np.arange(-2,2,0.1)
xx,yy = np.meshgrid(x,y)
xx = xx.reshape(-1,1)
yy = yy.reshape(-1,1)
xy = np.concatenate([xx,yy],1)
z = model(xy)
z = z.reshape(-1,len(x))
plt.figure(figsize=(5,5))
plt.contourf(x,y,z,cmap='coolwarm')
plt.show()
```

　x,yの形を整形しています。図にすると以下のような感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/4d4270b3-709f-b320-66d7-a8c54d58a0e5.png)


　この形式であれば、例えば`lda.precdict()`や`model()`（PyTorch等）の関数に対応できます。

# おまけ

　`contourf`ではなく`pcolormedh`にするとグリッド表示になります。見た目はキレイですが、データの傾向はむしろわかりづらくなる気がするので、個人的には`contourf`の方が好みです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/d6e4bd75-cb41-8cca-d956-5c4e041bd847.png)

```python
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(-2,2,0.01) #解像度を0.01に
y = np.arange(-2,2,0.01) #解像度を0.01に
xx,yy = np.meshgrid(x,y)
z = np.zeros((len(x),len(y)))
for i in range(len(x)):
    for j in range(len(y)):
        v = np.array([xx[i][j],yy[i][j]])
        r = np.linalg.norm(v)
        z[i][j] = np.exp(-r)
plt.figure(figsize=(5,5))
plt.pcolormesh(x,y,z,cmap='coolwarm') #ここを変更
plt.show()
```
テキストファイルの保存/読み込み

##テキストファイルに保存する

テキストファイルにテキストデータを保存するには、まず、テキストファイルのパスを作成。
ここでは、ホームディレクトリのDocumentsフォルダにtextFile.txtファイルを作ってテキストデータを保存。
ホームディレクトリまでのパスはNSHomeDirectoryで取得。

```viewController.swift
let path = NSHomeDirectory() + "/Documents/textFile.txt"
```


ファイルの保存は失敗の可能性もあるので、　do - try - catchでエラー処理に組み込む必要がある。

automaticallyをtrueにすると書き出し中に異常終了があってもファイルが壊れないように一時ファイルを使って保存処理を行う。

```viewController.swift
let textData = textView.text
do {
 //テキストデータの保存をトライ
  try textData?.write(tofile: path, automatically: true, encoding : String.Encoding.utf8)
  print("成功")

} catch let error as NSError{
 //　tryが失敗した時に実行される
  print("保存に失敗: \(error)" )　
}
```


##テキストファイルからの読み込み

 読み込むファイルのパスは保存したパスと同じ。
保存の時と同じように　do - try - catchでエラー処理に組み込む

```viewController.swift

do {
 //テキストデータの読み込みをトライ
let texData = try String(contentOfFile: path, encoding: String.Encoding.utf8)
  textView2 = textData
  print("成功")

} catch let error as NSError{
 //　tryが失敗した時に実行される
  textView2.text = "読み込みに失敗:\(error)"
  print("読み込み失敗: \(error)" )　
}
```



###ファイルが存在するかをチェック
```viewController.swift

//ファイルマネージャーを作る
let fileManager = FileManager.default
//指定のファイルがなければ中断
guard (fileManager.fileExists(atPath: path) == true) else { return }
```
肩こりが酷いので分割キーボードを使う

# 僕の欲しい分割キーボードがない。

* 癖のない一般的なキーピッチ、配列である
* 日本語配列である
* 光らなくてよい
* 一般的なテンキーレスを普通に左右に分割しただけで特殊な配列ではないこと
* 「6」、「Y」、「B」は右手で押す
* IME切り替えはトグルではなくMacのように「英数」、「かな」で独立したキー切替をする
* USB Type-C
* 左右どちら側のUSBに接続しても使える
* キーキャップにかな表記はいらない
* キーキャップに英語配列時の記号も小さく表記したい
* Thinkpad トラックポイントを右手側につけたい

kinesisキーボードを買ってみたが、1日で挫折。仕事にならなない。

結構時間がかかると思うが満足のいくキーボードを自作していくことにした
コマンドプロンプト(cmd)からpythonファイルを反復実行するのが楽になる.bat

# はじめに
こんにちは。地方公立大に通う文系学生の犬です。

この記事では、__cmdからpythonを実行するのに、毎回新しく書き直す作業を省く方法__を（備忘録的に）紹介しています。
ちなみに今回扱うのは__.bat__こと__バッチファイル__です。

# どんな時に有効か
僕の場合は、__Chainer Realtime Multi-Person Pose Estimator（以下"CRMPE"）__というモジュールのうち、__pose_detector.py__を中心とした「人が映った画像に対して姿勢推定をし、点と線を描画して保存する」という内容を反復したいと考えていました。
※1_cmd上でのfor文の記述は漸次追加します。
※2_参考にさせていただいたCRMPEの記事はこちら→https://github.com/DeNA/chainer_Realtime_Multi-Person_Pose_Estimation

大学の研究（先生が寛容なので分野が研究室のものから逸脱気味でも背中を押してくださいます）のために__大量の画像データに対し同様の処理を複数回行う__必要が出てきた、というのがこの記事、と言いますかコーディングの発端となります。

僕のケースのように、エクスプローラー（フォルダなど）の画面から__特定のファイルをクリックしただけで単純動作を反復できるようにしたい！__という方にバッチファイルは効くはずです。

# 具体的にはどうしたか
```batch

rem this is to apply pose_detector.py to images
call C:\Users\name\anaconda3\Scripts\activate.bat
C:\Users\name\anaconda3\python.exe C:\Users\name\CRMPE\pose_detector.py posenet models/coco_posenet.npz --img data/sth.png
pause
exit
```
※見づらくてすみません...
①一番上の__rem__はpythonの__#__同様、__コメント__的な役割をしています。

②私はpython3がanaconda環境のもと動いてる（確かそう）ので、anaconda3のScriptsにあるバッチファイル「__activate.bat__」を先に動かしておく必要がありました。anacondaとか特に関係なくただpythonがCドライブ直下に置いてあるだけ、というような方は次の行から初めて頂いても差し支えないかと思われます。

③__python.exe__を記述し、その後に__半角スペース__（意外と忘れがち）、続いて今回動かしたい__pose_detector.pyとその命令の詳細__を書いていきます。
気に留めておくべきなのは、この__バッチファイルの内容はほとんどきれいそのままcmdに書き写される__ということで、この辺りの詳細な部分は予めcmdに書こうと思っていたことをそのまま書いてしまって差し支えありません。
※したがって、今回はCRMPEの出典元様の記事にあったcmdへの命令をそのまま書いています。

④__pause__と書いておくことで、__cmdが結果を出した途端に消えてしまうのを防ぎます__（何かしらキー入力するまでcmdを開きっぱなしにできます）。
私の場合は、画像の出力ついでに画像内の点の座標データ（行列）をprintするにあたり、__加筆したpythonのコードが機能しているか__を確かめたいと思い、pauseを書くことで観察の時間を得ました。

⑤最後に__exit__でcmdを閉じます。

# 最後に
細かいデバッグを必要とするプログラムでは、（これはかなり単純かつ簡単なものですが）バッチファイルはある程度の役割を果たしてくれると思います。あと、もっとうまく使えるようになりたいと思いました...（for文とかも書けるそうなので）

（抱負）
研究と就活と院試準備全部頑張ろ。
グータンヌーボヌーボを定期実行させてみた

# はじめに
みなさんおはこんばんちは。Hameeアドカレ13日目です。
結論からはじめにお伝えすると。

[「デートの食事」に悩んだ時、グータンヌーボヌーボする。](https://qiita.com/yamakona/items/ea964cee43d97193b7b1)
これをcronから実行できるようにしたという話

もうcron知ってるわ!
今更マサラタウンすぎwww

って方も多いと思いますが！今年業務でもcronに触れる機会はなんどかあり、ちょうど自分でも使ってみたいなと思ったので昔の記事を改造してcronで実行できるようにしました。♻️
## 前回までのあらすじ

わたくしグータンヌーボヌーボという番組をこよなく愛しておりまして、「いつか番組で登場したお店に行ってたい!!!」という己の願望を叶えるために、**TwitterAPI**と**LINEAPI**を使って以下のことを行っていました。
1. 事前にLINEbotアカウントを作成&友達追加
2. phpファイルをローカル環境で実行
3. グータンヌーボ公式ツイッターからAPI経由でお店情報を取得
4. 2.で取得したお店情報を1.で作成したLINEBotアカウントを引数にLINEAPIを実行
5. LINEBotがお店情報を投稿

## 課題点

課題点は一つ。**phpファイルを自分自身で実行しなければいけないこと。**
この1年、自分でこのphpファイルを実行したことは1度もなかったです。
~~そもそもデートもしなかったし、必要となることなかったし当然だた:angel:~~

ということで定期実行できるように設定してみました。
## やったこと

以下のcrontabコマンドを実行し簡単設定して終わり:sunny::sunny:
番組の放送は毎週火曜 深夜0：25～0：55で
Twitterの更新は前後しているので毎週水曜の夜中の0:00に設定
cronの時間設定については[こちらの方の記事](https://qiita.com/syunyo/items/69c3523a8c500b37f33f)をご参考ください

```
crontab -e
0 0 * * 3 php /path/workspace/Gutan_Nouveau/Gutan.php
```

ちゃんと動作するのか気になる・・・！！！
気になるので試しに日曜の17:10に起動するのかデバッグ...
ちなみに５つめの**7**が日曜にを表しているのですがここは**0**でも日曜日を表してくれるようです。

```
10 17 * * 7 php /path/workspace/Gutan_Nouveau/Gutan.php
```

**きtら！！！！！！！！！！！！🎉🎉🎉🎉🎉🎉🎉🎉**
![スクリーンショット 2020-12-13 17.33.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212395/1b28fe27-bf40-10cd-a815-3fd90e66b77c.png)


## とはいえ
めちゃめちゃ簡単に定期実行行う事ができたのですが、さすがにこれじゃ、、、と思いcronについて少し調べてみました。

## crontabオプション
man crontab でcrontabについて調べてみる。
どうやらオプションは4つしかない。
-u で実行できるユーザーの指定。-l 設定済のcron情報を確認。-r cronの削除。-e cronの設定。


     -u      Specify the name of the user whose crontab is to be tweaked.  If this option
             is not given, crontab examines ``your'' crontab, i.e., the crontab of the
             person executing the command.  Note that su(1) can confuse crontab and that
             if you are running inside of su(1) you should always use the -u option for
             safety's sake.

     -l      Display the current crontab on standard output.

     -r      Remove the current crontab.

     -e      Edit the current crontab using the editor specified by the VISUAL or EDITOR
             environment variables.  The specified editor must edit the file in place; any
             editor that unlinks the file and recreates it cannot be used.  After you exit
             from the editor, the modified crontab will be installed automatically.```

## 気になったところ

そもそも、これディレクトリとか指定しなかったのにどこにできたのかな〜〜
って思ってたらcrontab -eした時に以下のディレクトリ出てた

```
/tmp/crontab.Bu5SvCojm0" 1L, 72C
```
でも実際にディレクトリをみてみたら存在していなかった。
んん〜〜〜〜〜と思ってwhichしたらヒットは一件

```
$which crontab
/usr/bin/crontab
```
調べたら、これはどうやら[crontabコマンドの本体ファイル](https://wa3.i-3-i.info/word14574.html)
再起動してもcrontab -lで確認したら設定は残っていたのでメモリに保存されている？？(詳しい方いたら教えてください。。😭😭😭)


## 最後に

ただただ、crontab使ってみたって話でした。
補足ですが、 <em>グータンヌーボのTwitterは最近お店情報をTwitterに載せなくなった</em> らしく
デートの時にお店に困ってもグータンヌーボも教えてくれなくなったので詰みです。

定期実行思ったよりも簡単だなって思えたので
今後もいろんな使い方してみたいなって気持ちになりました。☀️☀️☀️


>参考記事：【cron】定期的に処理を行う【MacOS】【Linux】
https://qiita.com/syunyo/items/69c3523a8c500b37f33f
各ユーザのcrontabファイルの場所について
https://qiita.com/iganari/items/5a61ec93d989f7c77a2c
Mac環境構築Python

# Macmini環境構築
## 概要
MacMini(M1)を買ったので、pythonを`Hello World`するまでのメモ。

* 使用するパッケージ管理ツール:Macports
* installするパッケー:Pytnon38,pip38

## 手順
Pathを通すまでは、
### 手順1 MacPortsを使えるようにする
[QuickStart](https://www.macports.org/install.php)をよむ

- XCodeをInstall
    - ネイティブアプリのAppストアからInstall
  - コマンドラインとライセンス同意済みか確認

```
$ xcode-select --install
$ sudo xcodebuild -license
```

- MacPortsをInstall
  - HPにいってダウンロード (QuickStart上部にOSバージョン別のリンクあり） 
  - Pathを通す
 
```zsh:~/zshrc	
export PATH=/opt/local/bin:/opt/local/sbin/:$PATH
export MANPATH=/opt/local/man:$MANPATH
```
### 手順2 pythonのInstall
- pythonをInstall
  - `sudo port install python38` 
- `python`で実行できるよう設定(port完了時に、以下のどちらを設定するよう推奨される)
  - `sudo port select --set python python38`
  - `sudo port select --set python3 python38`
  - `python3 --version`
- ついでに`pip`も入れておく
  - `sudo port install pip-38`
  - `sudo port select --set pip pip-38`
  - `pip --version`
- Hello World
 
```
$ python3
>>> print("Hello World")
```
「僕と契約してVMオヂサンになろうよ」

# 「僕と契約してVMオヂサンになろうよ」
### はじめに
これは [限界開発鯖 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/approvers) の15日目の記事です
14日目はフライさんの[Notionをオラオラする術](https://www.notion.so/notiontotheworld/Notion-7c76af51e9c64b5dae1020bfd039c938)
16日目は(未投稿)です

👇お前だれという方はこちら
<details><summary>何だおまえ</summary>
らみん([laminne33569](https://github.com/laminne))です.
(Arch/Alter)Linux/Ruby/Python/Dockerを少ししてる松江高専一周目です.<br>
~~[検閲により削除]~~
</details>

##⚠️注意⚠️
この記事は***仮想化関連超素人***のぼくが**†卍投稿日前日の夜の2時卍†**に*寝ながら書いたもの*です.

そしてこの記事にはWindowsユーザには全く関係ない部分が多い(動作要件がLinuxが多い)ですごめんなさい(筆者は実機環境を手に入れるまでArchの仮想マシンをWin上に建ててました)

色々間違ってたりtypoしてたりするかもしれませんが許してください......

## そもそもVM#とは
※この記事でのVMはハードウェアVMのことを指します
VMとはVirtualMachine(仮想機械)の略でコンピューターの動作をエミュレートするソフトウェアのことです.(語弊が多い)
<details><summary>Spoilor</summary>
言ってしまえばVMはコンピューターを*多重人格化*させるソフトウェアです.コンピューターの人格に相当するOSを複数起動できるためです.</details>

こんな時に便利です

- PCに他のOSを入れたい(後述)
- 別のアーキテクチャでの動作をエミュレートしたい
- できるだけ環境を汚したくない

最近だとArmアーキテクチャでの動作検証みたいなのをしたっていうツイートをよく見ます

## 何が便利なのか
### PCに別のOSをインストールしたいとき
仮想化ソフトウェアが存在しない世界線ではいちいちインストールのやり直しや新規インストールをしなければいけません.

更に一台のPC上で動作するOSは一つと限られているため同時に作業がしたいといった場合は他にPC機を用意する必要があります.

そんなことしてたら大変ですよね?HDDやSSDの寿命はともかくインストールにかかる時間が洒落になりません....
### 別のアーキテクチャ用のOSやプログラムを動作させたいとき
皆さんがいまこの記事を読んでいる端末の殆どはx86(x86_64)かarmだと思います(逆にそれ以外のCPUを積んだマシンでアクセスされることは本当に少ない).

もし,あなたがi386(32bit)用のプログラムを書いたとしましょう.
ただ、手元にはx86_64機しかありません.

こういうときにi386(や他のCPUアーキテクチャや実行環境)の環境をエミュレートしてくれるVMは非常に便利です.いちいち物理マシンを用意する必要がないのです.しかも導入コストもそこまで高くありません(個人の感想)

## VM生活を始めよう
皆さんのお持ちの開発用コンピューターの中身はきれいでしょうか？
いろんな言語がいろんなバージョンで動いていたりするはずです.
*環境を汚したくないとき*にもVMは役に立ちます.

Windowsでは動かすのが大変でもLinuxではかんたんに動くものも存在します. `e.g)Docker,Rails`

#### いろんなOSを試すこともできます.
やり直しが何回でもきくのでインストールが比較的難しいArch Linuxなどのインストール練習をすることもできます.(ちなみに私もこの方法です)

#### "やり直し"が効きます
仮想マシンの中で何があってもーたとえ,なにかの間違いで`# rm -rf /`を実行してしまったとしてもー スナップショットという仮想化ソフトの機能を使えば、短い時間でもとに戻すこともできます

#### その環境,あなたと共有しません？
あと、多くの仮想化ソフトは一つのファイルの中にVM内部の情報を保存しているのでそれをUSBに入れたり他人と共有することによって開発環境を揃えることもできます.
...最近はDocker(コンテナ型仮想化ソフト)に置き換えられていますが.

## 仮想化ソフト(ｵｽｽﾒ順)
### ホストOS型
#### Hyper-V(Microsoft)
普通.何から何まで普通.
どちらかというと使いにくいがVMが強制終了サれたりといったことはない.かなり安定した仮想化ソフト.
Winのみ.
#### VirtualBox(Oracle)<-ｵｽｽﾒ
普通.扱いやすくて情報量が多い.
macOS,Windows,Linuxのほとんどの環境に対応している.
Vagrantと相性がいい.
#### VMware(VMware)
色々良くわかっていない仮想化ソフト(私が触ったことがない).
有料版を使っているとドヤれるらしい.
対応OS不明.(調べてない)
#### QEMU(OSS)
どちらかというとCPUのエミュレートに使われるもの.
x86でない環境でwineを動作させたり,組み込み機器向けのクロスコンパイルに使える(らしい).
Win,macOS,Linux,BSD
####KVM(OSS)
みんな大好きKVMｻﾝ.
Linuxカーネルをハイパーバイザ化するための仮想化モジュールという位置づけ.
Linuxで仮想マシンと言ったらだいたいこれというイメージ.
もちろんLinuxでしか使えません.

### 仮想化ソフトをかんたんに扱うためのGUIソフト
触ったことのある人はわかると思いますが、KVMとQEMUにはGUIのフロントエンドが**存在しません**.
なので,ほかのソフトをインストールするという方法でKVMやQEMUとおしゃべりしてVMを操作するわけです.

### virt-manager(Red HatのOSS)
ちょっと触るのにコツの要る中級者以上向けフロントエンド.
XenやKVM,QEMUをあやつることができる.
メモリの仕様状況等を見やすく表示してくれるので非常に便利.
### GNOME Boxes(OSS)
GNOME(Linuxのデスクトップ環境)のアプリケーションの一つ.
※GNOME以外のVMでもインストールすれば使えます
簡単に扱えるのでさっとVMを立てて壊す,といった用途に向いてる.
QEMU,KVM,libvirtに対応.

## ...さいごに
内容がペラッペラで申し訳ないです....~~まるで僕の腕のよう~~

VM以外にも仮想化の技術はいっぱいあるのでそういうのも勉強してはいかがでしょうか.

明日はSouさんで`ゲーム制作のTips集 ~ DXRubyを添えて`です！
ct.jsとは

javascriptで書かれた2Dゲーム向けのフレームワーク。ct.IDEという優秀なエディターが提供されている。
ゲームを

- `texture` スプライト、タイルセット、背景など。
- `copy` キャラや弾など。他のエンジンだと"object"や"actor"と呼ばれる。
- `type` copyのテンプレとなる。「型」とややこしい。
    - (v2.0では、`ct.types`は`ct.templates`に改名された)
- `room` copyを置く平面。"level"や"map"とも。

で表現する。[^basic]
`copy`という概念はいわゆるインスタンスやオブジェクトと呼ばれるモノのことなので"copy"という名前のクラスは存在しない...?(パッと見た限り。)

イベントの流れは以下の通り。[^eventorder]

1. `room`の`oncreate`
2. 各`copy`の`oncreate`
3. 現在の`room`についてメインループ
    1. 各`copy`の`onstep`
    2. `room`の`onstep`
    3. `kill`された`copy`の`ondestroy`
    4. 各`copy`の`ondraw`
    5. `room`の`ondraw`
    6. インプットイベントがクリアされる。
4. 新しい`room`に到達したら`onleave`

# 例) ct.IDEで編集する主人公Catの`type` [^example]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619160/329a5424-c359-0e3c-3ce5-d866d7e07d43.png)

最初の`room`である"Level_01"に1つだけ、このCatが配置されているので、ゲームが始まり次第この`type`をもとにCatオブジェクトが生成され、カメラが寄るなどの初期設定を行う。
なお、Catは`onstep`で

```javascript:onstepの抜粋
if (ct.actions.Shoot.pressed) { // bulletを生成、方向を指定 => 発砲
    const bullet = ct.types.copy('Bullet', this.x, this.y - 5);
    bullet.direction = ct.u.pdn(this.x, this.y - 5, ct.mouse.x, ct.mouse.y);
}
```

と弾オブジェクトを生成する。

# ct.jsのいいところ

- IDEが用意されていることに尽きる。逆にこれありきなのが欠点だけど仕方ない。
- "Learn about ..."みたいなボタンを押すとすぐにドキュメント(英語)が読める。
- あまつさえエディタ右側中央の"<"ボタンからも見れる。
- 2D限定でこじんまりとしたC#を見ずに済むUnity。
- 初心者、非技術者へのやさしさがある。

まだまだ発展途上だと思います。がんばって使っていきたいです。誰か全和訳してほしい。


[^basic]: https://docs.ctjs.rocks/#basic-concepts
[^eventorder]: https://docs.ctjs.rocks/event-order.html#call-order-with-mod-s-injections
[^example]: ct.jsの用意したサンプルをもとに
クリスマスは遅延評価セグメントツリーを飾ろう

#前置き
この記事は公立はこだて未来大学 Advent Calendar 2020　https://adventar.org/calendars/5150
の14日目の記事です。
遅延評価セグメント木の抽象化の部分で詰まったので記事を残しておこうと思いました。

#本題
遅延評価セグメント木に載せられるのは作用付きモノイドです。
作用付きモノイドとは
モノイド(X,〇,ex), (M,★,em)と□: X□M→Xが成り立つ二項演算□について

* **Xの任意の元xについて x□em = x**
* **Xの任意の元x1, x2,Mの任意の元mについて (x1〇x2)★m = (x1★m) 〇 (x2★m)**
* **Xの任意の元x,Mの任意の元m1, m2について (x□m1) □ m2 = x □ (m1□m2)**
を満たしているものです。

モノイド(X,★,e)とは集合XとXの二項演算★: X × X → Xについて

* **結合律**
* **単位元eを持つ**

を満たしている代数的構造です。★: X × X →　Xとは、Xの任意の元a,bについてa★bもXの元であるということです。

遅延評価セグメント木に対して、
(X,〇,ex)は区間取得の部分、(M,★,em)は区間更新を貯める部分、□: X□M→Xは区間更新を貯めている配列を元の配列に作用させる部分に対応しています。

#最後に
時間が無くかなり雑になってしまいました。自分の中で分かったつもりになっているものも、言葉できちんと説明するのは難しいですね。
遅延評価セグメント木についてもっと詳しく知りたい方はreferenceの記事を読むといいかなと思います。

##Reference
セグメント木を徹底解説！0から遅延評価やモノイドまで
https://algo-logic.info/segment-tree/
Wikipedia モノイド
https://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%8E%E3%82%A4%E3%83%89#%E3%83%A2%E3%83%8E%E3%82%A4%E3%83%89%E4%BD%9C%E7%94%A8%E3%81%A8%E4%BD%9C%E7%94%A8%E7%B4%A0%E3%83%A2%E3%83%8E%E3%82%A4%E3%83%89
ACL Beginner Contest解説
https://www.youtube.com/watch?v=D0Op33UL_cA&feature=youtu.be 1:19:22~
遅延評価セグメント木をソラで書きたいあなたに
https://tsutaj.hatenablog.com/entry/2017/03/30/224339
僕らがDockerを使う理由

就活に有利だからとかモダンな自社開発で使用している技術だからなどと下心でDockerをいじり始めた筆者ですが、学習を続けるうちにDockerという技術がとても強力な技術というのが理解できてきました。

## Dockerとは
コンテナ型仮想化技術を実現するためのアプリケーションとCLI(コマンド実行できる)からなるプロダクトです。2013年にDocker社のソロモンハイクがオープンソースソフトウェアとして公開し人気が集まりだしました。既存のソフトウェアと比べてゲストOSを使用せずにホストOSからリソースを確保して処理するためオーバーヘッドが少なく軽量に動作します。

## コンテナでの運用・開発
既存の仮想化技術と大きく違う点はこのコンテナ化です。アプリケーションごとに箱に梱包(コンテナ化)し、それをオーケストレーションツール(docker-composeなど)にて通信させていきます。このコンテナ化というのが強力で、依存するライブラリなどをコンテナに入れておけば別のDocker環境でも全く同じように作動します。
つまり開発者のローカル環境のライブラリのバージョンなどを気にせずに一瞬で同じ環境が再現できます。

## 本番環境にも使える
筆者が大変感動したのがここです。前述のコンテナ化による高いポータビリティ性により、本番環境と同じ状況を開発環境にて再現し、そのまま開発したものをデプロイしてしまうことが可能となります。
またサポートが現在はかなり充実しており、***AWS***では***ECR***(Docker Hubみたいなリポジトリ),***ECS***(オーケストレーションとスケーリングを行える)がありデプロイも簡単で、運用もものすごく容易となります。さらにAWSのCLIツール(ecs-cliやaws cliなど)の利用で数行のコマンドでVPCやEC2なども一瞬で立ち上げることが可能となります。

## 環境差異の脱却
これらにより、私の環境では動いたがあの人の環境では動かない。デプロイしたがうまく動かないなどの環境差異による無駄な時間が削減できます。プログラミングを始めたてのときに詰まった環境構築などはもう次の世代の駆け出しエンジニアは体験しないのかもしれませんね...

## 所感
Dockerをこれまで勉強してみて、便利なところしか見つからず、たしかにこの技術を採用できていない企業からは転職を考えたほうがいいという過激な意見にも一理あります。
とはいえ駆け出しエンジニア全員がモダンな技術を使った自社サービスに携われるわけもなく、私が入社する企業でも、Dockerなど使わず、泥臭い環境構築をすることになりそうです。
ただ思うのは便利になっていく半面Webエンジニアはどんどんインフラが弱くなっていくのではないかな？と思いました。やはり現在業務にてDockerを触っている現場のエンジニアの方も秘伝のタレと化した環境構築などを経験していき今のスタイルに行きついたのではないかと考えています。修行と思い、数年後業務にてあの***クジラ***を見ることができればと思いました。
Windows10環境でmakeコマンドを使用する方法【ハマリ回避】

* [Windowsでmakeコマンドを使う](https://qiita.com/tokikaze0604/items/e13c04192762f8d4ec85)
* [Windows10でmakeしたい](https://qiita.com/taki-ikat/items/f501f44a8d44e3fd6987)

こういう記事があったのでやってみたのですが、残念ながら私の環境では動かなかったので備忘録を置いておきます。
また、MinGWと一緒に入れたmakeはうまく動きませんでした(後述)。
手間を惜しまず、おとなしくMake for Windowsを入れましょう。

# 手順

## Make for Windowsのダウンロード

下記からダウンロードできます。
[Make for Windows](http://gnuwin32.sourceforge.net/packages/make.htm)
「Complete package, except sources」を選択すればOKです。
![2020-12-14_011606.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633415/f4d69f03-d655-c0fe-daee-257cb5af39ee.png)

## インストール先をCドライブ直下に変更する

Program Filesフォルダにインストールすると、makeコマンドのパスにスペースが入ってうまく動かないようです。
具体的には、

```
syntax error near unexpected token ('
```

が出ます。
ですので、インストール先をCドライブ直下に変更しておきましょう。
![2020-12-14_011948.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633415/315f13df-342a-5382-3bda-c3fc4d51d5c4.png)


## makeコマンドを実行できるようにパスを通す

さて、インストールしただけでは、makeコマンドを実行できません。
コマンドプログラムがあるディレクトリにパスを通すことで、初めてmakeを実行できるようになります。
Windowsでパスを通す方法は色々なところで説明されていると思いますので、それを参考にするのがよいでしょう。

Cドライブ直下にMake for Windowsをインストールした場合は、
`C:\GnuWin32\bin`
をパスに追加することになります。
![2020-12-14_012250.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633415/9b7de554-3923-777a-9221-6c8d9c4482b2.png)


# MinGWインストール時に入れたmakeが動かない件

MinGWをインストールする際にmsysを一緒にインストールするとmakeプログラムもインストールされますが、
この方法でインストールされたmakeは一部の組み込み変数の値がおかしくなっているようです。

具体的には`$(MAKE)`の内容が正しいパスになっていないみたいな問題が発生していました。
これによりcmakeで作ったMakefileを実行しても`No such file or directory`が出てしまい、ダメでした。

この件については色々調査しましたが、makeコマンド側の問題だと思われます。
実際、

```Makefile
all:
	@echo $(MAKE)
```

とだけ書いたMakefileファイルを用意してmakeコマンド実行したところ、
この`$(MAKE)`変数の中身が「PowerShell」や「コマンドプロンプト」では正しい値になっていないようでした。
「Git Bash」や「cygwin terminal」では正しい値になっていたのですけどね。
Windows用に最適化されていないからでしょうか。

なお、私はこれで2日ハマリました…。
Unity+NGUIで仮想的にタッチ処理を呼ぶ話

# 概要
諸般の都合でNGUIを使ってるプロジェクトでプログラムから座標を指定してタップ処理をコールする処理を作りました
・ゲーム内にカーソルを用意したい場合
・UIの自動テストをしたい場合
で利用できるかもしれません

まあ今更NGUI使う人はいないですよね
uGUIも似たような実装になってるの？機会があればコード読みます

# 検証環境
Unity: 2018.4.26f1
NGUI: 2019.3.0

# 実装
UICamera.csに以下を追記します

```c#
public void VirtualProcessTouch(Vector2 pos, bool pressed, bool unpressed)
{
    currentTouchID = 1;
    currentTouch = GetTouch(currentTouchID, true);
    currentTouch.touchBegan = pressed;
    if (pressed)
    {
        currentTouch.pressTime = RealTime.time;
        activeTouches.Add(currentTouch);
    }
    currentTouch.delta = pos - currentTouch.pos;
    currentTouch.pos = pos;
    currentKey = KeyCode.None;
    currentTouch.clickTime = RealTime.time;

    Raycast(currentTouch);

    ProcessTouch(pressed, unpressed);

    currentTouch.last = null;
    currentTouch = null;
}
```

あとは呼びたいところでVirtualProcessTouchをコールすればOKです
ツールチップやドラッグ処理をしたい場合はマイフレームコールする必要があるので注意。



# 解説
NGUIのUIへのタップ処理はUICameraで実装されています
Update関数からコード読むといいです
Update - ProcessEvents - ProcessTouches でタッチ処理が実装されてるのでコピぺしました
ちなみにRaycastは何もしてなくても全UICameraから毎フレーム飛ばしてます。

## おまけ１
ProcessOthersにコントローラーを想定した処理がありますがUIKeyNavigationのための実装です。
これをボタンに設定しておくと十字キーでどのボタンに移動するか定義できるんですね。便利。

## おまけ２
最初、自分でカメラからRaycastして要素を全取得してタップ処理をコールしようとしましたが
座標とdepthで前後関係がちゃんと取れなかったりScrollViewの子要素がとれてしまったりで無理でした
結果UICameraをいじるのが早かったというオチ
Tcl/Tk婆婆もサロゲートペアに対応させてみた


いつの間にか湯婆婆アドベントカレンダーに1日だけ空きができて侘しかったので、勢い余って書いた続編を投稿させて頂きます。

# はじめに
[湯婆婆 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/yubaba)への[投稿](https://qiita.com/qoLop/items/11f0678eeb83003903b8)を終えてほっと一息ついていたところ、翌日の「[Flutterの湯婆婆にサロゲートペア文字を理解させたら可愛くなった💗](https://qiita.com/simontanz/items/690fb1b22ac75410d87e)」を読んで[Tcl/Tk婆婆](https://qiita.com/qoLop/items/11f0678eeb83003903b8#tcltk%E3%81%A7%E6%B9%AF%E5%A9%86%E5%A9%86%E3%82%92%E5%AE%9F%E8%A3%85%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B)でも試してみたくなりました。

# 灯台もと暗し
実は私の姓にもサロゲートペアの「𠩤」が含まれているのですが、自分の名前ではテストしていませんでした。
![hara1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165786/1d6720e8-6988-c44b-41d5-15ed4b9d722e.png)
やはりサロゲートペアには対応していませんでした。

# サロゲートペア対応
公式にどういう状況なのかは理解していませんが、いくつか動きはあるようです。

* [TIP 389: Full support for Unicode 10.0 and later (part 1)](https://core.tcl-lang.org/tips/doc/trunk/tip/389.md)
* [Tclによるサロゲートペア文字列の切り出しとか](http://reddog.s35.xrea.com/wiki/Tcl%E3%81%AB%E3%82%88%E3%82%8B%E3%82%B5%E3%83%AD%E3%82%B2%E3%83%BC%E3%83%88%E3%83%9A%E3%82%A2%E6%96%87%E5%AD%97%E5%88%97%E3%81%AE%E5%88%87%E3%82%8A%E5%87%BA%E3%81%97%E3%81%A8%E3%81%8B.html)

しかし難解でついていけなかったので、今回は「[Flutterの湯婆婆にサロゲートペア文字を理解させたら可愛くなった💗](https://qiita.com/simontanz/items/690fb1b22ac75410d87e)」で紹介されていた「ゴリゴリと対応するならば」でやってみました。

```tcl:yubaba.tcl
#!/bin/sh
#-*-mode:tcl;coding:cp932;tab-width:8-*-\
    exec wish -encoding cp932 "$0" ${1+"$@"}

proc string_split {str} {
    set ret [list]
    binary scan [encoding convertto unicode $str] su* letters
    set bytes ""
    foreach letter $letters {
        append bytes [binary format su $letter]
        if {0xd800 <= $letter && 0xdbff >= $letter} {
            continue;# surrogate pair
        }
        lappend ret [encoding convertfrom unicode $bytes]
        set bytes ""
    }
    return $ret
}

grid [label .w1 -text "契約書だよ。そこに名前を書きな。"] -sticky w
grid [entry .w2 -textvariable name] -sticky w
grid [label .w3 -textvariable contract -justify left] -sticky w
bind .w2 <Key-Return> {
    set contract "フン。${name}というのかい。贅沢な名だねぇ。"
    set nameLetters [string_split $name]
    set newNameIndex [expr {[clock microseconds] %% [llength $nameLetters]}]
    set newName [lindex $nameLetters $newNameIndex]
    append contract "\n今からお前の名前は${newName}だ。いいかい、${newName}だよ。分かったら返事をするんだ、${newName}!!"
}
```
string_splitでサロゲートペアを考慮しつつ文字列を文字のリストに分割しておき、後の処理はstringコマンドではなくリスト処理コマンドで文字数や切り出しを行います。
![hara2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165786/1eaeae38-a405-f40e-aa29-7a6779c26988.png)
うまくいったみたいです。

「𠮷𠩤」さんではどうでしょう？
![hara3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165786/2668a7e0-2ea8-cf77-7be5-1e2096276f9e.png)
![hara4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165786/25834819-a3d0-6efa-8cf1-26f869a49c35.png)

勉強になりました。