OmniAICreator/Qiita-1.07M huggingface dataset:
Alloyでパズル (14) 僕は僕のおじいちゃん

さてネタ切れというか、書いてまとめるのが間に合わなくなってきた。
今無料で受けられる [N予備校](https://www.nnn.ed.nico/) の「ものがたり創作」面白いです。
物語の構造を抽象モデル化して分析する話になっています。

今回は Alloy 本から、どう書くか以前に定義がどうあるべきかに悩まされた問題。
しかしそこを悩むときにこそ、「モデル発見器」とも称される Alloy の強みが発揮されると思っている。

# 問題

Alloy本 4.1 例題：自分が自身の祖父
> 『僕は僕のおじいちゃん』（“I’m My Own Grandpa”）という古いポピュラーソングがある。
一体どうやったらそんなことが起こるのか、Alloy を使って見ていくことにしよう。

# リスト
『僕のおじいちゃん』とはどういう存在なのか、その定義が問題。

実親の実親が自分であることはあり得ない。
なので結婚とそれによって生まれる義理の親という関係を定義する必要があるが、誰との結婚が認められるかは国や時代によっても異なるだろう。
また、どこまでを義理の親と認めるかはおそらく法律的な話とは異なる。
結婚しないと子どもが生まれない訳ではないので、それを無視してもいけないだろう。

同性婚や重婚を認めた場合も、簡単な変更で試せるようにした。
「僕は僕のおじいちゃんではない」に対する反例を挙げさせる形とした。

```alloy
// 僕は僕のおじいちゃん
// 義理の親の義理の父 までおじいちゃんと認定（親夫妻と配偶者の直親までを広義の親とした）
// 同性婚や重婚を許すと結果も増える
// 近親婚をどのくらい省くべきか不明だが、ありなら母と結婚するだけで成立する

abstract sig 人 {
    父: lone 男性,
    母: lone 女性,
    配偶者: lone 人,
    おじいちゃん: set 男性,
    おばあちゃん: set 女性
} {
    this not in this.祖先                   // パラドックス防止
    no 配偶者.祖先' & this.祖先'             // 近親婚防止１
//撤回    no 母.祖先' & 父.祖先'                   // 近親婚防止２
    おじいちゃん = this.親'.親' & 男性        // おじいちゃんとは
    おばあちゃん = this.親'.親' & 女性        // おばあちゃんとは
}
fact { 配偶者 = ~配偶者 }   // 双方向関係
sig 男性 extends 人 {} { no 配偶者 & 男性 }
sig 女性 extends 人 {} { no 配偶者 & 女性 }
one sig 僕 extends 男性 {}

let 親[p] = p.(父+母)
let 親'[p] = p.親 + p.親.配偶者 + p.配偶者.親   // Alloy本では親夫妻まで
let 祖先[p] = p.^(父+母)
let 祖先'[p] = p.*(父+母)   // p自身を含む

run { some 配偶者 } for 4
run { one おじいちゃん } for 5
check { no 僕 & 僕.おじいちゃん } for 4
```
Alloy本では兄妹婚や姉弟婚を禁止していないが、本リストでは「近親婚防止１」で省いている。

注）このリストはあくまで例であり、日本の法律や私の見解を示すものではありません

# 結果

提示される例を見て、不適切として除外すべきか判断するのにも苦労した。
「この例は子が生まれてから離婚して、元妻の母と再婚したと考えるべき？」など。

Alloy 本では２パターンだが、今回の定義では４パターンとなった。

1. 義理の父の義理の父
![Grandpa1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20005/bf926326-f8c0-3a0b-fd2e-4ccc2594f3d7.png)

2. 義理の母の義理の父
![Grandpa2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20005/c83c469d-c05e-ef79-ae82-395731e29357.png)

3. 義理の父の義理の父
![Grandpa3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20005/d6456718-2f45-c0c4-577d-86d62b7f39c5.png)

4. 義理の母の義理の父
![Grandpa4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20005/9eb7072f-03ad-cf10-9f4d-d5805af7e549.png)

# 追記

そういえば、「近親婚防止２」は「結婚しないと子どもが生まれない訳ではないので、それを無視してもいけない」に抵触している。
これを外すと図のような関係が出てくるが、倫理面はともかく現実にあり得るだろうからモデルから外すのは厳しすぎた。
（４人以内で母という関係が２つより多い `run { #母>2 } for 4` で簡単に出てくる例）
![MotherAndChildsBaby.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20005/f4d55def-9ca1-dcff-d692-1de79d30c5d7.png)
![SIblingsBaby.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20005/e20b225f-e517-cce4-3acc-751d60252a41.png)

「近親婚防止２」は撤回しよう。
あり得ない関係が出てくるようなら、それはまた別の修正ということで。
（近親婚防止**と言いながら**結婚に**関係ない条件**になっているのが、何かを物語っていた気も）

# 追記２

養子縁組によって生まれる親子関係を忘れていた。
これを考慮すると何か変わるか試してみるのもいいだろう。

# 参考

- Daniel Jackson : [抽象によるソフトウェア設計 ―Alloyではじめる形式手法](https://www.amazon.co.jp/dp/B07BKRG85J)
- Wikipedia : [近親婚](https://ja.wikipedia.org/wiki/%E8%BF%91%E8%A6%AA%E5%A9%9A)
React + Redux + TypeScript で Ducks パターン

`Typescript` で `react/redux` の ducksパターンをやるとき。

## modules

```modules/counter.module.ts
export type CounterState = {
  count: number;
};

type IncrementCountAction = {
  type: 'INCREMENT_COUNT',
}
type DecrementCountAction = {
  type: 'DECREMENT_COUNT',
}
type SetCountAction = {
  type: 'SET_COUNT',
  count: number,
}
export type CounterActions = IncrementCountAction | DecrementCountAction | SetCountAction;

export default (
  state: CounterState = { count: 0 }, action: CounterActions
): CounterState => {
  switch (action.type) {
    case 'INCREMENT_COUNT':
      return { ...state, count: state.count + 1 };
    case 'DECREMENT_COUNT':
      return { ...state, count: state.count - 1 };
    case 'SET_COUNT':
      return { ...state, count: action.count };
    default: return state;
  }
};

```

## store

```store.ts
import { combineReducers, createStore, Dispatch } from 'redux';
import counter, { CounterState, CounterActions } from './modules/counter.moudle';
import user, { UserState, UserActions } from './modules/user.moudle';

export type RootState = {
  counter: CounterState,
  user: UserState,
};
export type RootDispatch = Dispatch<CounterActions | UserActions>;
export const rootReducer = combineReducers({ counter, user });
```

## how to use
```component.tsx
const dispatch = useDispatch<RootDispatch>();
const count = useSelector<RootState, number>(s => s.counter.count);
dispatch({ type: 'INCREMENT_COUNT' });
```
【ブロックチェーン】MineChainを使ってブロックチェーンを動かしてみた


Creating new genesis block.
{
  "id": "00087e9a97a60eeb95875be24552d3c17d6be200d9a284d314bad6e3063fd6d6",
  "prev": "0000000000000000000000000000000000000000000000000000000000000000",
  "difficulty": 2E-06,
  "nonce": 234219852044107443,
  "timestamp": "2020-03-17T22:02:38.6081521Z",
  "root": "6fd8GrtxHI2XP/B+HF+zd3/qEEM+esUQb7pt7vskkYo=",
  "height": 0,
  "txs": [
    {
      "id": "a35d1682ef49da5def1beefd081984f4902a460c25ce6e67946bb9124af892cb",
      "timestamp": "2020-03-17T22:02:38.3112078Z",
      "in": [],
      "out": [
        {
          "to": "ec5d40eac3e3d3f7ed8cce06ef34eae0aca38218342ba3afa5e3fadcc04ce784",
          "val": 1000000
        }
      ]
    }
  ]
}
/MinChain/MinChain/bin/Debug/netcoreapp2.0$ dotnet MinChain.dll config | sudo tee config.json
{
  "listen": "0.0.0.0:9333",
  "peers": [
    "127.0.0.1:9333"
  ],
  "keypair": "<YOUR OWN KEYPAIR>.json",
  "genesis": "<GENESIS BLOCK>.bin",
  "mining": true
}

＝＝＝＝＝＝＝＝＝＝＝＝
dotnet MinChain.dll run config.json

        "id": "00001bfa45fcca7f3ab16b7cf0e7482e80ecdc6facdf520e57508c86f485ca78",
        "prev": "00001d8713d27b69445f1d6f8ddc7bceee71a90f4b232ae516cd615886a0bf8b",
        "difficulty": 0.00011573274015682705,
        "nonce": 15956159822150272815,
        "timestamp": "2020-03-17T22:08:16.6218344Z",
        "root": "V4zYmQSAh4jR3OftTnGYb/OMYjVth0jbI6U02zO6ogI=",
        "height": 0,
        "txs": [
          {
            "id": "ad11fadbc2d869bb1e20a66431c177e42d7ad7950fb3ab2589f2947bf0d4dfa3",
            "timestamp": "2020-03-17T22:08:16.4878086Z",
            "in": [],
            "out": [
              {
                "to": "ec5d40eac3e3d3f7ed8cce06ef34eae0aca38218342ba3afa5e3fadcc04ce784",
                "val": 1000000
              }
            ]
          }
        ]
      }
dbug: MinChain.Executor[0]
      Attempt to run Block:00001bf
dbug: MinChain.Executor[0]
      Attempt to run TX:ad11fad
warn: MinChain.Executor[0]
      Applying Block 51:00001bf.
dbug: MinChain.Executor[0]
      Attempt to run TX:0b13d00
info: MinChain.Mining[0]
      Block mined: {
        "id": "00003190ff1d93263284385b9e24f0124608171c37beca82d51c2868d9cc6497",
        "prev": "00001bfa45fcca7f3ab16b7cf0e7482e80ecdc6facdf520e57508c86f485ca78",
        "difficulty": 0.00012730601417250975,
        "nonce": 13007236693602512082,
        "timestamp": "2020-03-17T22:08:17.3243703Z",
        "root": "0kkczUREp0SVjMyPwUqGN3BfCAYRd4zsv0n3svMKSR8=",
        "height": 0,
        "txs": [
          {
            "id": "0b13d00abf0a325388081cb9aacc4cb33e4f8f74e548b9c4a66585ca5e07ed33",
            "timestamp": "2020-03-17T22:08:16.6224256Z",
            "in": [],
            "out": [
              {
                "to": "ec5d40eac3e3d3f7ed8cce06ef34eae0aca38218342ba3afa5e3fadcc04ce784",
                "val": 1000000
              }
            ]
          }
        ]
      }
dbug: MinChain.Executor[0]
      Attempt to run Block:0000319
dbug: MinChain.Executor[0]
      Attempt to run TX:0b13d00
warn: MinChain.Executor[0]
      Applying Block 52:0000319.
dbug: MinChain.Executor[0]
      Attempt to run TX:f77642f
初心者によるプログラミング学習ログ 265日目

#100日チャレンジの265日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
265日目は、

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>265日目<br>・webサイト模写　1.0h<br>・以前購入した模写教材のコンテンツ部分作成<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1240001023273357312?ref_src=twsrc%5Etfw">March 17, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【Unity】全角を2、半角を1としてbyte文字数を数える

プレイヤー名やモンスターのニックネームなど文字数の制限を行いたい場合に、全角は2、半角は1として合計30まで、といった数え方で文字数を制限したいケースの実装方法です。

よくある内容ですが、実際に実装するのはなかなか手順が多く大変でした。

## 要点

 - Shift_JISでByteにエンコードする
 - 「I18N.CJK.dll」と「I18N.dll」をプロジェクトにインポートする

## Shift_JISでByteにエンコードする

通常のエンコードといえばUTF8だと思いますが、UTF8だと漢字が３byte、かなが２byteだったりするため、文字数のカウントには向いてません。

そこで、文字数のカウントではShift_JISへのエンコードを行います。

```C#
using System.Text;

public static class StringEncodingExtension 
{
    public static int GetSJISByteCount(this string text)
    {
        return Encoding.GetEncoding("Shift_JIS").GetByteCount(text);
    }
}
```

拡張メソッドで書いておけば、適当な場所でstringのbyte文字数を数えられます。

```C#
using UnityEngine;

publiｃ class StringEncodingExtension 
{
    public void Start()
    {
        string nickName = "キラーマシン2";
        // >>> 13
        Debug.Lot(nickName.GetSJISByteCount());
    }
}
```


## 「I18N.CJK.dll」と「I18N.dll」をプロジェクトにインポートする

Unityエディタならコード書くだけで済みますが、実は実機でやろうとするとShift_JISエンコードがサポート対象外となってエラーになってしまいます。

対応策として、「I18N.CJK.dll」と「I18N.dll」をプロジェクトにインポートさせてあげると上手くいきました。

### 参考
http://baba-s.hatenablog.com/entry/2019/03/18/155000


## 感想

完全にぼやきですが、なんで文字数数えたいだけなのにこんな苦労しなきゃならないんだ...？ って思いました。
リポソームの外形を抽出するImageJのマクロ

ImageJを使って画像を二値化し、リポソームの外形を抽出するマクロ。下記論文中のFig. S10.の作図に使ったImageJのマクロです。論文ではImageJで顕微鏡画像からリポソームの外形データを抽出した後にRで解析してリポソームの変形を可視化しています。

[De Novo Synthesis of Basal Bacterial Cell Division Proteins FtsZ, FtsA, and ZipA Inside Giant Vesicles](https://pubs.acs.org/doi/10.1021/acssynbio.7b00350)
Furusato T. *et al*., (2018), *ACS Synth Biol*, 7(4), 953-961
![visualization.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564846/12d5301e-e656-8388-2f90-9e5b285e9953.jpeg)

#インストールと使用方法
下記コードをtxtファイルとして`ImageJ/macros`に保存。ImageJを開き`Plugins->install`でインストール。これで、`Plugins`に`Extract_liposome_form`というメニューが追加される。あとは、解析したい画像ファイルが入ったフォルダを選択するだけ。これで、tifデータからリポソームの外形データが抽出されたファイルが作成される。

```{ImageJ}
//Extract_liposome_form ver1.0
//20180607ami

macro "Extract_liposome_form" {

//setting
dir = getDirectory("Choose a Directory");
filelist = getFileList(dir);
run("Set Measurements...", "area circularity perimeter redirect=None decimal=3");

//Start Loop
for (i=0; i<filelist.length; i++){

path1 = dir + filelist[i];
open(path1);

run("Smooth");
run("8-bit");
run("Threshold...");
setThreshold(0, 255);
run("Convert to Mask");
run("Analyze Particles...", "size=100-Infinity circularity=0-1.00 show=Outlines display exclude");
}

saveAs("Results", dir + "Results.xls");
}
```
[payjp]tokenは発行できているのに呼び出せるはずのデータがテーブルに入らないエラーの解決方法

#1.どのような状態だったか

javascriptで`payjp-token`取得はコンソールで確認すると全て成功しており、ページ遷移の部分でもエラーは出ず、validationに関するエラーも出ないのに、コントローラーで`payjp-token`の値が取り出せないという状態でした。（エラー文が出ず、正常にnewアクションに戻るという症状でした。）


下記の二つの記事を参考にpay.jp機能を実装をしていました。（大元が上の方で、それの詳細まで記述されていたのが下記の方でした。）

https://qiita.com/takachan_coding/items/f7e70794b9ca03b559dd
https://qiita.com/emincoring/items/ce29dbbd182aa3c49c6b

なのでとりあえず動作を見るべく細部まで記述のあった下記のブログを参考に下記のようにviewを作成しました

※今回はviewの記述によるエラーだったので、その部分についてのみ記述します

```haml:app/view/cards/new.html.haml
.content__title
  %h2 クレジットカード情報入力
.content__credit-card
  .content__credit-card__inner
    = form_with url: cards_path, method: :post, html: { name: "inputForm" } do |f| -# createアクションのパスを指定
      = f.label :カード番号, class: 'label'
      %span 必須
      = f.text_field :card_number, type: 'text', class: 'input-number', placeholder: '半角数字のみ', maxlength: "16"
      .cards-expire
        = f.label :有効期限, class: 'label'
        %span 必須
        %br
        .cards-expire__wrap
          = f.select :exp_month, [["01",1],["02",2],["03",3],["04",4],["05",5],["06",6],["07",7],["08",8],["09",9],["10",10],["11",11],["12",12]],{} , class: 'input-expire'
          %span.expire-text 月
          %br
        .cards-expire__wrap
          = f.select :exp_year, [["19",2019],["20",2020],["21",2021],["22",2022],["23",2023],["24",2024],["25",2025],["26",2026],["27",2027],["28",2028],["29",2029]],{} , class: 'input-expire'
          %span.expire-text 年
      .cards-expire
        = f.label :セキュリティコード, class: 'label'
        %span 必須
        = f.text_field :cvc, type: 'text', class: 'input-number', placeholder: 'カード背面4桁もしくは3桁の番号', maxlength: "4"
      .content-bottom#card_token
        = f.submit '追加する', class: 'content-bottom--add-btn', id: 'token_submit'

```

#2.原因

`payjp-token`の受け渡しを図解すると、
**submitを押してjavascriptに入力情報送信→javascriptで`payjp-token`に変換→form_withの実行でcontrollerに`payjp-token`受け渡し**
となります。
この時、数値の受け渡し毎にそれぞれidが1つずつ必要になるのですが、自分は1つしか用意していませんでした。
そのため、`受け取りid=受け渡しid`となり、入力情報（カードの期日など）を素のままでform_withで受け取り、コントローラに値を返してしまっていたというのが原因でした。


#3.解決方法
form_withにも新たにidを定義すれば希望通りの挙動をしました

```haml:app/views/cards/new
〜前略〜
= form_with url: pay_cards_path, method: :post, id: 'charge-form',html: { name: "inputForm" }do |f|
# idの名前はどのようなものでも大丈夫です。筆者はpayjpのホームページで記述のあったid名を引用しました。
〜後略〜
```

#4.（補足）エラーの見つけ方

まず今回のように、railsのエラー文やjavascriptのエラー文（Google Chromeの検証のconsole上のもの)が出なければ数値の受け取りミスであることがほとんどだと思われます。

したがって筆者はまずコントローラでbinding.pryを挟んでどこまで数字が取れているか確認し、次にjavascriptにもconsole.log();を挟んで確認しました。結果、javascriptは問題ないということがわかり、コントローラとビューの確認を行いました。

その結果、javascriptには送れているから、そのあとの受け取りのタイミングで間違いがあると考え、submitの後に処理されるのはなにかと考えた時、残るのはform_withだけなのでその記述に関する資料を検索していたところ、このメソッドもid指定できることがわかり解決に至りました。

このようにエラー文が出なくて困ったら、デバックのコードを１行ずつ挟んで確認すれば原因を特定しやすくなり、エラーを見つけることができます。
Windows 上のNeovim+QFixHowmでカーソル位置のURIが開けないとき

windows上のNeovimにQFixHowmを導入したところ，カーソル位置のURIを\<ENTER>で開けなかったので，実施した対処をメモしておく．

# 環境
|               | バージョン情報など        |
|:--------------|:------------------------ |
| OS            | Windows 10 Education 1903|
| Neovim        | Neovim v0.4.3            |
| QFixHowm      | QFixHowm Ver.3           |

#対処
qfixhowm-mastar/autoload/openuri.vimの中に以下の記述を加えた．
* 番号の前に+がついた行が追加箇所

```vim
...
 125  "カーソル位置のファイルを開くコマンド"
 126  if !exists('g:openuri_cmd')
 127    if has('mac')
 128      let g:openuri_cmd = "call system('open %s')"
+129    elseif has('win64')
+130      let g:openuri_cmd = "call system('start %s')"
 131    elseif has('unix')
...
```

#おわりに
Windows 上のNeovim+QFixHowmでカーソル位置のURIが開けないときの対処を示した．もしかすると，こんなことしなくても動くのかもしれない．．
bat でマウススクロールを有効にする

A _cat(1)_ clone with syntax highlighting and Git integration. である **bat** (https://github.com/sharkdp/bat) でマウススクロールが使えないのを有効にする。詳しいことは公式ドキュメントの [Using a different pager](https://github.com/sharkdp/bat#using-a-different-pager) に書いてあるが、バージョンが 530 以上の less をインストールし、`BAT_PAGER` 変数を `less -RF` にするか、`bat --config-file` が示す場所に `--pager="less -RF"` と書けば良い。以下 macOS で brew と fish を使っている私の環境では以下のコマンドを実行すれば bat でマウススクロールが有効になる。

```sh
#!/usr/bin/env fish
brew install less
mkdir --parents (dirname (bat --config-file))
echo '--pager="less -RF"' > (bat --config-file)
```

ちなみにこれを書いたときにインストールされた less のバージョンは 551 だった。今まで聞いたソフトウェアのバージョン数の中では一番大きいかもしれない。

## 追記

iTerm2 上の less でマウススクロールできるようにするには、Preferences > Scroll wheel sends arrow keys when in alternate screen mode. > Yes にする必要がある。less を利用する bat も同様である。
https://stackoverflow.com/questions/14437979/iterm2-scroll-less-output-with-mouse
dockerコンテナにサブドメインなどもまとめて1つのIPに名前解決する

# やりたいこと

1. docker-composeで立ち上げたコンテナから任意のホストに名前解決したい
2. docker-networkには参加させない(E2EテストやブラウザでURLを打ってアクセスさせるなど)
3. かつ、サブドメインで同じIPに名前解決したい

// TODO: つまりどういうことだってばよ (説明する)

# 2までの場合

例として、`uyu.pun` ドメインを192.168.1.11に受け流すように変更してみます。

// TODO: extra_hostsが何をしているのか

```yml:docker-compose.yml
version: '3'
services:
  app:
    image: node:13.10.1
    ports:
      - 3000:3000
    # ↓ 足す
    extra_hosts:
      - 'uyu.pun:192.168.1.11'
    command: "node app.js"
    volumes:
      - ./:/src
    working_dir: /src
```
[参考: Docker で Node.js 開発環境を簡単に用意する](https://qiita.com/ka-miyata/items/5dfc03af6d73c8bacc84)
ポートについては固定値に変更させていただきました。

↓コンテナ立ち上げ後、シェルで `/etc/hosts` ファイルを参照した結果です。(他の項目は省いています)

```hosts:/etc/hosts
192.168.1.11 uyu.pun
```


# 鬼の仕様変更

…ではないと思いますが、サブドメインで同じホストの別ポートにマッピングしたい、といった状況になったとします。

例として、`admin.uyu.pun` も192.168.1.11に向けてみます。

```yml:docker-compose.yml
version: '3'
services:
  app:
    image: node:13.10.1
    ports:
      - 3000:3000
    # 失敗する
    extra_hosts:
      - 'uyu.pun:192.168.1.11'
      - 'admin.uyu.pun:192.168.1.11'
    command: 'node app.js'
    volumes:
      - ./:/src
    working_dir: /src
```

↓出力後

```hosts:/etc/hosts
192.168.1.11 uyu.pun
192.168.1.11 admin.uyu.pun
```
この状態でpingを打つと失敗します。どうもhostsファイルの仕様っぽいです。
[参考: Hostsファイル：複数の行に同じIPアドレスがあるのは間違っていますか？](https://qastack.jp/unix/102660/hosts-file-is-it-incorrect-to-have-the-same-ip-address-on-multiple-lines)
ざっくりとしか読んでいませんが、先に書いたほうが優先される？模様。

# 対策 : コロンより前をスペース区切りで記述する

```yml:docker-compose.yml
version: '3'
services:
  app:
    image: node:13.10.1
    ports:
      - 3000:3000
    # コロンより前をスペース区切りで記述する
    extra_hosts:
      - 'uyu.pun admin.uyu.pun:192.168.1.11'
    command: 'node app.js'
    volumes:
      - ./:/src
    working_dir: /src
```
↓起動後の `/etc/hosts`ファイルの確認

```hosts:/etc/hosts
192.168.1.11	uyu.pun admin.uyu.pun
```

pingを打ってみます。

```shell
 # ping uyu.pun
PING uyu.pun (192.168.1.11) 56(84) bytes of data.
From 192.168.1.22 (192.168.1.22) icmp_seq=1 Destination Host Unreachable
^c
# ping admin.uyu.pun
PING uyu.pun (192.168.1.11) 56(84) bytes of data.
From 192.168.1.22 (192.168.1.22) icmp_seq=1 Destination Host Unreachable
```

無事、２つのドメインを同じIPに名前解決できた。(IPアドレスは適当にしたので疎通できていませんが、期待したIPにpingを投げていることがわかると思います。)

## 応用

今回これを試したのは、なるべく実運用に近い環境でE2Eテストの実行をしたいという背景でした。
各自のローカルマシンのdockerコンテナ上にあるサーバーにリクエストを向けるために、IPアドレスの部分は変数にし、参照元の`.env`ファイルは以下のようにし .gitignoreしています。
ちなみに、.envの環境変数を展開する場合は"で囲うようです。

```yml:docker-compose.yml
...
extra_hosts:
  - "uyu.pun admin.uyu.pun:${HOST_MACHINE_IP}"
...
```
```:.env
HOST_MACHINE_IP=192.168.1.11
```
# 課題

記入するドメインが増えると横に長くなっていってしまうので、ymlファイル上では改行してきれいに表示したい。。

# おわりに
uyu.punって何？うゆぷん？って方へ
[こちら](https://github.com/uyupun)
OracleのODBC接続

# はじめに
表題の通り。一旦調査...

# 参考サイト
◆わかりやすく解説！ODBCドライバの設定方法【Oracle（オラクル）】
　https://enoxproduction.com/oracle-odbc/
　　※ここが一番わかりやすい!?

◆WindowsでODBCドライバを設定する方法
　https://qiita.com/tarosa0001/items/0d68b38b61c1eaaa4bbe
◆ORACLE 設定方法
　https://www.microlab.jp/xcutedoc/Documents/sup_db/Oracle.htm
　　※画面もあるから、ここをベースに設定してみる...

◆Oracle Developer Tools for Visual Studio 
　https://www.oracle.com/technetwork/jp/developer-tools/visual-studio/overview/index.html
◆ODAC for Visual Studio 2017 Downloads
　https://www.oracle.com/database/technologies/dotnet-odacmsi-vs2017-downloads.html
　※ODTforVS2017_193100.exe/183000/122011

◆24 Oracle ODBC Driverの使用方法
　https://docs.oracle.com/cd/E96517_01/adfns/odbc-driver.html#GUID-7931EDFB-7A70-4BBE-903E-8A2BB09DBE9D
　https://docs.oracle.com/cd/E57425_01/121/ADFNS/adfns_odbc.htm
　　※流石Oracleのサイトだから、めっちゃ詳しく書いてある。。。ただ、読むの疲れるから、上手くいかなかったときに参考に

◆データベース接続あれこれ
　http://kojama.la.coocan.jp/works/rdbms/conn/connstr.html
◆接続文字列一覧
　https://blue-red.ddo.jp/~ao/wiki/wiki.cgi?page=%C0%DC%C2%B3%CA%B8%BB%FA%CE%F3%B0%EC%CD%F7
　　※別件で参考になるかもなので、一応記載

# 途中経過...
ODBCは32/64bitの関係でBadImageFormatExceptionが出てしまう...
JavaScriptでタイムゾーン付きの文字列（ISO8601）をJSTの"yyyy/mm/dd HH24:mi:ss"で表示する

## 概要

タイムゾーン付きの文字列（ISO8601）をJSTで表示する。

## 実装

```javascript
a = new Date('2020-03-09T19:21:13+09:00')
// Mon Mar 09 2020 19:21:13 GMT+0900 (日本標準時)
a.toLocaleDateString("ja-JP", {timeZone: "Asia/Tokyo"})
// "2020/3/9"
a.toLocaleString("ja-JP", {timeZone: "Asia/Tokyo"})
// "2020/3/9 19:21:13"
a.toLocaleString("ja-JP", {timeZone: "America/New_York"})
// "2020/3/9 6:21:13"
```

## おまけ

月日を0パディングしたい場合は、

```javascript
a = new Date('2020-03-09T19:21:13+09:00')
a.toLocaleDateString("ja-JP", {timeZone: "Asia/Tokyo", year: "numeric", month: "2-digit", day: "2-digit"})
// "2020/03/09"
```

※参考
* [options部分（timeZone指定している部分）](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat)
初心者におすすめ！絶対に挫折しないWordpressの環境構築について

今回は初心者におすすめのlocal by flywheelを使ったwordpressの開発環境の構築方法について説明します。
アプリ起動からWordpressの環境を構築するまで１分ぐらいで完了します。

#local by flywheelを使用するメリット
###環境構築で挫折しない
プログラミング経験がない人にとって、環境構築は一つの大きな壁になっていますがlocal by flywheelを使用することでクリックするだけで環境が構築できる。
また複数のwordpressの管理を一元化できるのでプロジェクトごとにwordpressを管理することが可能

###動作が軽い
とにかく起動が早くクリック一つでサーバーのオンとオフを切り替えることができる。

###無料で使える
有料プランも用意されているがよっぽどな理由がない限り無料プランで不自由なく利用することができる。

#Wordpressの環境を構築

###local by flywheelをインストール
まずは<a href="https://localbyflywheel.com/">local by flywheelのサイト</a>からソフトをダウンロードしてください。

###サイトを作成
###CREATE A NEW SITE をクリックしてサイトを作成
![スクリーンショット 2020-03-18 1.23.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111504/2699f967-eb71-b5c0-11cb-b9efa836734c.png)

###サイト名を入力
任意のサイト名を設定
![スクリーンショット 2020-03-18 1.26.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111504/b026a1e9-46b6-72b7-65bd-83378d5f3170.png)
###Preferredを選択
![スクリーンショット 2020-03-18 1.27.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111504/6be9d7ca-2fbb-29af-89f9-eef9927ef213.png)
###Wordpressのセットアップ
Wordpressで利用する任意の「ユーザー名」「パスワード」「Eーmail」を入力
![スクリーンショット 2020-03-18 1.28.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111504/7bdd9e13-7cd4-c657-6cb1-e24f6771029c.png)

ADD SITEをクリックしてwordpressの環境構築は完了です。

#local by flywheelの基本操作
###右上のSTOP SITEでサーバーのオンとオフを切り替えることができます。
![スクリーンショット 2020-03-18 2.02.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111504/5a159770-a61d-be2f-2619-b06880d38b7e.png)


###ADMINをクリックすることでWordpressの管理画面にアクセスすることができます。
![スクリーンショット 2020-03-18 2.03.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111504/1eea420a-3d04-d5e5-2d41-05c0838fbfd5.png)

![スクリーンショット 2020-03-18 2.03.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111504/b09300bf-473c-b946-6491-52a5df3c64a4.png)


###VIEW SITEで作成したサイトを確認することができます。
![スクリーンショット 2020-03-18 2.05.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111504/1a2327d2-43d7-84aa-4b34-5ae0c6238f76.png)

![スクリーンショット 2020-03-18 2.22.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111504/99123485-1120-35eb-aa45-d41202adf9a8.png)


###作成したサイトのフォルダーにアクセス
サイト名の下に記載されたディレクトリーをクリックすることでサイトのフォルダーにアクセスすることができます。

![スクリーンショット 2020-03-18 2.07.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111504/7ec03ad0-1cc5-ed6d-bb8c-898e7e922d8d.png)

Wordpressのテーマなどを自作する場合は、[サイト名]/app/public/wp-content/themesにフォルダーを置くことでWordpressの管理画面から自作したテーマを選択することができます。

###LIVE LINKを使ってサイトを共有
LIVE　LINKを利用することで作成したwebサイトをチームやクライアントに共有することができます。
利用する場合　ENABLEをクリックしてリンクを取得
![スクリーンショット 2020-03-18 2.13.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111504/a6ec9ca5-2d24-00df-37c6-7ca38543cf7a.png)
Node.jsのworker_threadsに何を渡すべきか

久々にScalaの世界からJSの世界に帰ってきました。

#1. 本日の課題
本来Node.jsは非同期処理をストイックに突き詰めることでマルチスレッドやマルチプロセスのようなオーバーヘッドを伴う方法よりも高効率に並列処理を実現しているわけです。
ただし、それが有効なのは頻繁に「待ち」≒「I/O処理」が発生する場合に限られます。
ひたすらI/OなしでCPUをぶん回す処理、を複数同時にやれって言われたらシングルスレッドなNodeはマルチスレッドに勝てません。

ですがですが、Nodeにだってマルチスレッド/マルチプロセスの仕組みはあります。

さて今回は、

- 数百MB～数GB程度のデータ構造(変数として持っている)に対して
- 秒オーダーの時間をかけておこなう検索処理を
- 複数回おこなう
- 元のデータ構造は更新しない(Read Only)

という要件で、この「複数回おこなう」というところをマルチスレッドかマルチプロセスで並列化して時間を短縮したい、というお題になります。[^heavy]

# 2.候補
## child_process/cluster
どちらもマルチプロセスなアプローチです。
マルチプロセスなので、メモリは各自が持ちます[^shared]。GB単位のメモリをそれぞれのプロセスが持ってたらちょっともったいないですね[^fork]。ということで早々に候補から排除。

## worker_threads
今回の本命です。
本家にはこのように書いてあります。

> child_processやclusterとは異なり、worker_threadsはメモリを共有できます。

ふむふむ、スレッドですからね。そりゃそうですよね。ですが続けてこうも書いてあります。

> これは、ArrayBufferインスタンスを転送するか、SharedArrayBufferインスタンスを共有することにより行われます。

What's?
つまり、何も考えなくてもメモリが共有されるわけじゃないようですよ。
それが今回の本題というわけです。

# 3. Bufferを使うということ
ArrayBuffer/SharedArrayBufferというのはつまり中身はバイナリですから、

```JSON
{
    "こんな": 1,
    "好き勝手な": "aaa",
    "形をした": [
      "JSONから",
      "作った",
      "object/arrayなんか",
    ],
    "面倒みないよ": true
}
```
てなもんですよ。最後のtrueがなんだかムカつきますね。
なんとかBufferの基本的な使い方は、Uint32ArrayみたいなTypedArrayをViewとして使うことが多いんではないかと思います。[^typedarray]

メモリは大事にしたい(共有したい)、JSON-likeな構造も扱いたい、そんなわがままに答えてくれるものはないでしょうか。

## JSON
メインスレッドでJSON.stringifyしてBufferに載せて、ワーカースレッドでJSON.parseする・・・えーと、parseしてしまったらメモリの共有になってません。ダメです。

## JSON以外のシリアライザ
messagePackとかありますね。これもデコードせねばならないのでメモリの共有にはなりません。messagePackならJSONよりエンコード状態のサイズが若干小さいという利点はありますが、デコードしてしまうのでささいな差ですね。[^json]

# 4. ないものは自分で作ればいいじゃない
そう、それ！
やっと本題だ。
要するに、

- SharedArrayBufferに載せられて
- デコードせずとも中身にObjectやArrayのようにアクセスできる

何かを作ってしまえばいいじゃないか、という話。

> 「デコードせずとも中身にObjectやArrayのようにアクセスできる」？は？

と思ったあなた！
あるんですよ、JSにはいにしえより伝わる黒魔術、その名もProxyが。
つまり、「Object(あるいはArray)に見える」Proxyが動的にBufferをデコードしてあげればいいんじゃないか、と思ったわけです。

この用途だとJSONやmessagePackなどのシリアライザでエンコードしておいて、SharedArrayBufferに載せて、ワーカー側では全体のデコードは「せず」に読み出しの時だけ必要部分をエンコードするようにすればいいわけですが、ここでもう一つ問題が。
JSONは、全体をスキャンしないと、構造が分からない。keyがあるのかどうか、あった場合に何byte目に入っているのかは、先頭から順に追っていかないとわからない。メモリが節約できても、それではあまりに遅すぎる。messagePackも「ほぼバイナリ形式のJSON」であり同じこと。

そういうわけですから、

- Objectならkeyの有無、Arrayなら配列のサイズがすぐに分かって、
- 値の格納場所にダイレクトにたどり着ける

そんなデータ構造のシリアライザが欲しい！
ということで作ってみましたよ。

[roJson(Gistに飛びます)](https://gist.github.com/ayatty/4702df32e6bdac50fb3486be51145b4d)

使い方(sample.js)もGistに載せてますが一応再掲。
一般的なシリアライザ(JSON/messagePack等)と同じようにごくシンプル。

```sample.js
const roJson = require('./roJson');

const buffer = roJson.encode({a: "Hello roJson.", b: 1, c: [0, 100, 200]});
const proxiedObject = roJson.getProxy(buffer);

console.log(proxiedObject.a); // "Hello roJson."
console.log(proxiedObject.c[1]); // 100
```

長くなったのでいったんここまで。
工夫ポイント、ベンチマークなどは[次回](https://qiita.com/ayatty/items/4b662dba4395388c7138)！

[^heavy]: そんなヘビーな用途にNode.jsを使うなんて、なんてツッコミはなしの方向で。
[^shared]: OSの機能でプロセス間共有メモリってのがありますからそういうので共有できないことはないです。Node.jsから使う猛者がいるかどうかは知りませんが。
[^fork]: 昔の知識なので最新は違うかもしれないしOSにもよるんでしょうが、プロセスをforkするとすぐにはメモリはコピーされなくて(つまり共有されていて)、書き込んだ時点でページ単位でコピーしてそれぞれの道を歩むようになってました。大部分のメモリに書き込みが発生しないならそれに頼るのも一つの見識ですね。
[^typedarray]: そういうデータを使うのって機械学習とかCG系とかのイメージ。そういう用途Node.js使いますかね・・・。
[^json]: あと、JSON.stringify/parseはJSエンジンネイティブ実装だし、最適化されまくってるので速さで勝てません。憎いです。
yoctoでpluginをpatchでなくソースコードとして管理する場合のレシピの書き方

# 背景
OSSのpluginを自分で作って、それをyoctoを使ってビルドしたい。
そのOSSはgithubなどで管理されており、yoctoにもレシピはある。
yoctoだと通常はpatchを作って管理するため、pluginもpatchで管理すれば出来ないことはない。
ただ、patchで管理するとdiffが見辛い。
管理しにくい。
pluginは自分たちでgitを使ってソースコードとして構成管理したい。
この場合のレシピの書き方について調べたので備忘録として残す。

# アプローチ
まず類似例がないか考えた。
nginxのpluginが同じような構成になるのではと考え調べると、見事にヒットした。
https://medium.com/@zertsekel/yocto-how-to-add-nginx-module-35f03dd2ede3
https://www.yoctoproject.org/pipermail/yocto/2018-November/043102.html
やはり先人はいるようだ。
# 考え方
- pluginはpluginだけのレシピを作る
  - レシピの中身はfetchしてinstallするだけ
    - OSS本体から参照できるようになる
- OSSの本体はbbappendファイルを作る
  - DEPENDにpluginを追加
  - do_configureなりdo_compileなりを修正

なるほどー。

# 最後に
今回引っかかったのはnginxのngx-http-auth-pam-moduleだが、nginx-http-auth-digestやngx_mrubyなどももちろん同様にできる。
さらにapacheのmodulesやlighttpd、h2oのpluginも同様の仕組みで実現できる。

dlopenに対応しているOSSだと、bbappendファイルにDEPENDの依存関係は不要になり、
plugin側にOSS本体のDEPENDが必要となる。OSS本体のビルドが終わっていればplugin単体のcompileもできるため素直なレシピになる。
[Heroku]デプロイ失敗から得られた２つの知見[備忘録]

# tl;dr
###1. herokuではmigration fileは日付順にmigrateされるため、外部キーを設定したmigration fileがある場合は、migrateの順番を考慮する。

###2. heroku logsより詳細な情報が欲しいなら`heroku run rails c`を使う

---
#環境
ruby  2.6.5
rails 5.1.6.2
heroku/7.39.0 linux-x64 node-v12.13.0

---
#問題1
`heroku run rails db:migrate`を行うと以下のようなエラーが発生した

```console:
PG::UndefinedTable: ERROR:  relation "test_types" does not exist
: CREATE TABLE "param_values" ("id" bigserial primary key, "name" character varying, "test_type_id" bigint, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL, CONSTRAINT "fk_rails_j74mou9ds5"
FOREIGN KEY ("test_type_id")
  REFERENCES "test_types" ("id")
)
```

#原因
親(参照元)のテーブルが作成される前に子のテーブルが作成されているから

#対処
手動でmigration fileの名前を変更することで
migrationの順序を変更した。

```:
//[timestamp]ではなく番号を割り振った

[timestamp]_create_test_types.rb
　　　　　　　↓
01_create_test_types.rb
```

---
#問題2
Herokuへのデプロイ後にサイトを開くとApplication errorのエラー画面が表示された

#原因
`heroku logs`をしてみると
`at=error code=H10 desc="App crashed"`と出力された。
さらに、`heroku run rails c`をすると、
新規に追加したテーブルのカラム名のタイポが原因であることが分かった。

#対処
タイポを修正し、再び`git push heroku`する

#参考文献
>[PG::UndefinedTable: ERROR: relation "XXXXXX" does not exist] への対応
>>https://qiita.com/after4649/items/0144ee436d82822d2535

>[Ruby on Rails Tutorial]Herokuにデプロイ後Application error[H10 (App crashed)]が発生した時の対処法
>>https://qiita.com/m-itoidcf/items/77d064147a32169b5449
Linux(Ubuntu)にDockerを入れる便利なスクリプト

Docker公式が便利なスクリプトを用意してくれている。
毎回インストール後に思い出すのでメモ。

https://docs.docker.com/install/linux/docker-ce/ubuntu/
の下のほうに書いてある。

```bash
# インストールスクリプトをダウンロードして実行
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
rm -f get-docker.sh

sudo usermod -aG docker ${USER}
sudo service docker start

# docker-composeコマンドが必要な場合(Ubuntu)
sudo apt install -y docker-compose
```

また、公式のドキュメントには、
- プロダクション環境で使うのはお勧めしない
- sudo権限で動くスクリプトのため、実行前に内容を確認しておくこと
などと書かれてある。
メール周りのDNS設定に関する覚書

## メールの設定をしたいときにDNSで気にすること

メールの専門家でもないけれど、Route53でガイダンスに沿ってメール送受信の設定をしたり、むかしさくらのVPSの中でpostfix運用しようとして爆死したり、SendGrid使ってメール運用したり、Mailtrap使ってメール系の挙動のテストしたりしたことがあるような人が書く覚え書き。

たまにしか設定しなくてわりとすぐに忘れてしまうので、自分なりに言語化しておく。

### メール送信

メール送信は、実はどんなドメインでも送信側で名乗ることができる。FROMのメールアドレスに文字列を入れるだけだからだ。
なので基本的に、メールの送信者がドメインの正当な所有者であることを証明するためにDNS側の設定は行われる。

メール送信時は、以下のことをDNS側に問い合わせたときに確認できればよい(はず(すごい厳密にやる場合は他にいろいろ必要かもしれないけどそれ以上は詳しくないです))。

| 情報の名前 | 使うDNS側のレコードタイプ | 説明 |
| --- | --- | --- |
| DKIM | CNAME(とか) | DomainKeys Identified Mail.<br>メール送信時に電子署名を追加しておき、DNS側ではこの署名が正しいことを確認するための公開鍵を公開[^1]しておくものとのこと。<br>CNAMEって書いたけど必ずしもそうじゃない気もする |
| SPF | SPF | Sender Policy Framework.<br>そのドメインを送信元として送ってもいいIPアドレスの一覧みたいなのを埋め込むらしい。<br>そのまま SPFレコード というのがDNSの設定項目にある<br>SESではなくても動くけどあったほうがベター |

### この辺の設定が甘いと何が起きるか

怪しい送信だと疑われてブラックリスト入りすると、メールの受信側で弾かれたりする。
一度こうなってしまうとドメインそのもののメール方面での活用が超めんどくさくなってしまうし、アンコントローラブルな感じになってきてとてもつらいので予め回避しておくのが良いです。

SendGrid御大が記事をまとめてくれているので詳しくはこちらで。
https://sendgrid.kke.co.jp/blog/?p=11357

#### 参考にしたURL
https://www.nic.ad.jp/ja/basics/terms/dkim.html
https://www.nic.ad.jp/ja/basics/terms/spf.html

## メール受信

メール受信は、受け取り側が何番かのポートを開放しておくわけだが、基本的に送信されてきたメールはまず当該ドメインを管理するDNSに届くためそこから何処かに転送したりする必要がある。

原則、MXレコードというのを設定してなんとかする。

| 情報の名前 | 使うDNS側のレコードタイプ | 説明 |
| --- | --- | --- |
| MXレコード | MX | Mail Exchange.<br>送信されてきたメールをどこで処理すればいいかを指定する |

#### 蛇足(テーブルに収めるにはちょっと見た目が悪かったので別セクション)

G Suiteとかで扱いたいときにはMXレコードの宛先をG Suite側が用意してる受け口に送ったりする。SESとかで用意している送信用のSMTP情報と組み合わせるとGmailがそのドメインのメールボックスみたいに使えるようになったりしてとても便利。ただし `Re: Re:` みたいに繋がっていくタイプの処理はまるっとメールサービスに任せたりしないとうまく動かなかったりするので、あまり考えなしにメールの取り扱いを請け負わないように注意。普通にG Suite契約時にドメイン取っちゃったり、合わせて設定しちゃうぐらいの方がかなり楽です。ただ、システムからメール送りたいときとかはSES挟みたいとか出てくるから難しいところだよね、、と思ったりする。

#### 参考にしたURL

https://jprs.jp/glossary/index.php?ID=0163

以上、大した内容でもないですが、あんまりまとめてる人がいない印象だったので書いてみました。
誰かのお役に立てば幸いです。

[^1]: 頭痛が痛いみたいな感じする
2次元配列の行を増やす方法

Redimを使うと列を増やすことができますが、行を増やすことができません。
それで、Transposeを２回使うことで、２次元配列のデータを残して行を増やす関数を定義しました。
関数名にQLがついているのは、QueryListObject という意味で、
前に書いたQL_INITを改良するために使用する予定です。 
列が１行だと、Transposeで一次元配列になってしまいますので、関数TA_で判断します。

```vb
Function QL_REDIM(M, Optional N = 1, Optional S = "")
    On Error Resume Next
    
    If TR_(M) Then M = M
    
    If TV_(M) Then
        S = WorksheetFunction.Transpose(M)
        
        If TA_(S) Then
            ReDim Preserve S(1 To UBound(S, 1) + N)
        Else
            ReDim Preserve S(1 To UBound(S, 1), 1 To UBound(S, 2) + N)
        End If
        
        S = WorksheetFunction.Transpose(S)
    End If
    QL_REDIM = S
End Function

Function TR_(R, Optional T = "Range")
    TR_ = (TypeName(R) = T)
End Function

Function TV_(R, Optional T = "Variant()")
    TV_ = TR_(R, T)
End Function

Function TA_(R, Optional S = 0)
    On Error Resume Next
    S = (InStr(LUB(R), ",") = 0) * True
    TA_ = S
End Function
'
'   配列　上限下限
'
Function LUB(R, Optional S = "") ' LOW-UP BOUND
    On Error Resume Next
    
    V = R
    S = CC(S, LBound(V, 1), "-", UBound(V, 1))
    S = CC(S, ",", LBound(V, 2), "-", UBound(V, 2))
    S = CC(S, ":", TNAME(R))
    If ￢(R.ListObject Is Nothing) Then S = CC(S, " T ", R.ListObject.Name)
    
    LUB = S
End Function
```
UniRx で特定の期間にx回入力があったときに購読するヘルパーを作ってみた

マウスのダブルクリックを検知したかったり、あるキーを3回押したときだけデバッグモードの画面表示したかったりしませんか？
UniRx で簡単にダブルクリックなどを検知できますが、回数や検知期間を設定できるヘルパー関数を作ってみました。
これでいつでも簡単にデバッグ画面が開けます。

## ヘルパー関数

```C#
using System;
using System.Collections.Generic;
using UniRx;

public class UniRxHelper
{
    public static IObservable<IList<long>> InputCountDetection(Func<bool> input, int count = 2, int waiting = 200)
    {
        var stream = Observable.EveryUpdate().Where(_ => input());
        var throttle = stream.Throttle(TimeSpan.FromMilliseconds(waiting));
        return stream.Buffer(throttle).Where(i => i.Count >= count);
    }
}
```

### 仕様
* 検知したいイベント、回数、検知が成立する期間を設定することができます。
* 回数と検知期間を設定しなかった場合、2回、２００ms以内に発生したときに、イベントが発行されるようになっています。

## 使用例
マウスの左ボタンのクリックが、3回、500ms以内に、押されたことを検知して、ログを表示する例です。（面白くなくてすいません）

```C#
using UniRx;
using UnityEngine;

public class MouseInput : MonoBehaviour
{
    void Start()
    {
        UniRxHelper
            .InputCountDetection(() => Input.GetMouseButtonDown(0), 3, 500)
            .Subscribe(_ => Debug.Log("トリプルクリックを検知しました。"))
            .AddTo(this);
    }
}

```
enum や switch 文の中で include することもあるよ

https://qiita.com/takuyaw-w/items/0a2de13ec9c6685828e2
を読んで、必要があれば仕事で普通に書くよ、という話を。

# とりあえずソースコード

実際に使ったのは、window id とかそういう感じの情報だったと思うけど、都道府県ということにして例を作ってみた。

```c:list.h
ITEM(hokkaido, 1, "北海道")
ITEM(aomori, 2, "青森")
ITEM(akita, 3, "秋田")
```

```c:main.c
#include <stdio.h>
#include <stdlib.h>

#define CONCAT(a, b) a##b

enum {
#define ITEM(a, b, c) CONCAT(sym_, a) = b,
#include "list.h"
#undef ITEM
};

char const *name(int n) {
  switch (n) {
#define ITEM(a, b, c)\
  case b:\
    return c;
#include "list.h"
#undef ITEM
  default:
    return "no such place";
  }
}

int main() {
  printf("sym_aomori = %d\n", sym_aomori);
  printf("sym_akita = %d\n", sym_akita);
  printf("name(1)=%s\n", name(1));
  return 0;
}
```

# 簡単に解説

まず。
ファイルの include は、そこにそのようなテキストがあるかのように振る舞うというだけのことで、それ以上でもそれ以下でもない。

それ以上でもそれ以下でもないので、`enum` の中身だけとか、 `switch`〜`case` の中身だけとか、なんでもよい。

で。 
include されるファイルの記述は
`ITEM(hokkaido, 1, "北海道")`
のような、C言語のマクロとして使える形にしておくとつぶしがきく。
これが
`sym_hokkaido = 1,`
となるように `ITEM` を定義してもいいし、
`case 1: return "北海道";`
となるようにしてもいい。上記のソースに入れなかったけど
`somefunc( sym_hokkaido, "北海道");`
とか
`char const * get_hokkaido_name(){  return "北海道";  }`
とかにしてもいい。

わりとびっくりされるけど、はまると便利だし DRY になるので C言語なら普通に使っていい小技だと思っている。

# 実用上の注意

上記の例ではわざと `CONCAT` マクロを使って `sym_hokkaido` のようなシンボルを定義したが、これはやめたほうがいい。
ソースコード上に「`sym_hokkaido`」というシンボルを使っている箇所があるのに、どう grep しても `sym_hokkaido` の定義を見つけることができず、わりと人々を苦しめる。

昔これで同僚を苦しめたことがある。
Swift で map (closure) のこんな書き方

Swift の map などで使用する closure には書き方が色々ありますね。
下記のような書き方は知っていました。

```swift
let numbers = [0, 1, 2, 3]

// 下記すべて[String]型 ["0", "1", "2", "3"]
numbers.map({ (number: Int) -> String in return String(number) })
numbers.map({ (number: Int) -> String in String(number) })  // 暗黙的な戻り値
numbers.map({ number -> String in String(number) })         // 引数の型省略
numbers.map({ number in String(number) })                   // 戻り値の型推論
numbers.map({ String($0) })                                 // 引数名の省略
numbers.map { String($0) }                                  // 括弧の省略
```

こんな書き方を発見しました。勉強不足でした。

```swift
numbers.map(String.init)
```

結果は上記の例と同じですが、
単純に `numbers.map{ String($0) }` と全く一緒というわけではなさそうです。
http://swiftlife.hatenablog.jp/entry/2015/12/27/213058 こちらで解説されていましたのでご参照ください。

現に、Playgrounds で試すと結果の表示のされ方が異なります。右半分の表示です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42826/71afc292-562d-1e25-13ad-01b95952523d.png">


# 実験

## イニシャライザ以外にも使えるのか

いけた。

```swift
// いけた
func f(_ number: Int) -> String {
    return String(number)
}
numbers.map(f)

// 引数ラベルをアンダースコアで省略できるようにしとかなくてもいい
func ff(number: Int) -> String {
    return String(number)
}
numbers.map(ff)

// クラス関数とかでも問題なく使用可
class C {
    class func f(_ number: Int) -> String {
        return String(number)
    }
}
numbers.map(C.f)
```

## 関数の引数の数

closure の引数の数と、関数の引数の数があってないと **エラー** です。
引数2つ目以降無視されるとかはないです。

```swift
// エラー！！
func f(a: Int, b: Int) -> String {
    return String(a)
}
numbers.map(f)

// これは OK (sorted のクロージャの引数は2つのため)
func ff(a: Int, b: Int) -> Bool {
    return true
}
numbers.sorted(by: ff)
```

# 参考

- http://swiftlife.hatenablog.jp/entry/2015/12/27/213058
- https://qiita.com/saenuruki/items/19c304d7940f6ea4a293
ECEFとgeodetic への座標系の変換

GPSなどの衛星測位計算を行っていると、地球上の位置を表すのに

- ECEF (earth-centered earth-fixed)で定められるＸＹＺの直交座標系
- geodetic datum と呼ばれる緯度、経度、高さで表す方法

の２つが用いられます。高さは地球を楕円体でモデル化した時の球面からの鉛直方向で計算したものを「楕円体高」と言い、ジオイド（平均海水面に相当）からの高さを標高と言います。

参考資料はたくさんあり、

- [WGS84と座標変換のはなし](https://www.enri.go.jp/~fks442/K_MUSEN/1st/1st060428rev2.pdf)
- WikiPediaの　[経緯度](https://ja.wikipedia.org/wiki/%E7%B5%8C%E7%B7%AF%E5%BA%A6) 

などたくさんあります。

おじさんは今まで自分で実装したライブラリを用いていたのですが、今日見たらpython のライブラリがあったのでメモします。

## pymap3d を用いた座標変換の動作確認

### pymap3d 

- https://github.com/geospace-code/pymap3d でソースあり
- https://pypi.org/project/pymap3d/ に登録あり。pip で問題なくインストールできた。

目的の座標変換の関数は ```pymap3d.ecef.ecef2gedetic``` にあります。名前の通り。

### 動作確認

電子基準点のつくば１の座標値を使用します。

```python
from math import isclose
from pytest import approx
from pymap3d.ecef import ecef2geodetic

def test_ecef2geodetic():
    x_ecef = [-3957162.4119, 3310203.4927, 3737752.2980]
    x_geod = [36.106112803, 140.08720184, 70.336]
    x_geod_from_ecef = ecef2geodetic(x_ecef[0], x_ecef[1], x_ecef[2])
    print( "x_geod_from_ecef=", x_geod_from_ecef)
    print( "x_geod=", x_geod)
    assert x_geod[0] == approx( x_geod_from_ecef[0] )
    assert x_geod[1] == approx( x_geod_from_ecef[1] )
    assert isclose(x_geod[2], x_geod_from_ecef[2], rel_tol=0.01)
```

いざ ```pytest --capture=no -v``` をすると警告がなぜか出ますが、ＯＫでした。

```
x_geod_from_ecef= (36.10611280179599, 140.08720184317684, 70.33612007893962)
x_geod= [36.106112803, 140.08720184, 70.336]
PASSED
```

これからはこれを薦めよう。
競プロ界隈でpython強者がやっていることをまとめてみた

はじめまして。
先週競プロに入門した初心者です。
今はpythonを使っています。

出来ればC++に頼ることなく競プロで良い結果を出したい！
ということでpythonのままスコアを上げる方法を考えました。

例えばC++では

```C++
#define rep(i,n) for((i)=0;(i)<(int)(n);(i)++)
```
こんな感じで高速化をする人が多いです。
要するに、頻繁に使う記述を簡略化しておくって感じですかね。
前からこういうおまじない的な慣習があることは知っていました。

が、これのpythonバージョンはpythonで競プロをやっているのに知りません。

そこで、pythonの競プロ強者の慣習を学んでいこうと思い、この記事を書きました。
同じような方にも参考になれば幸いです。


# はじめにしたこと
強い人の提出コードを読みました。
やっぱりC++競プロと同じようなおまじないがあったので解読していこうと思います。
(とある強そうな人から引用しています)

# 実際のコード
実際のコードを順に説明していく。

```python
sys.setrecursionlimit(10 ** 6)
```
再帰関数の再帰の深さを設定する。(defaultは1000)
意味はわかるが必要性がピンとこない。

調べてみたところ、これで引っかかる場合もあるらしく、とりあえず大きめに設定するという感じ。
確かに、これが原因でエラーが出た時、気付くの難しそう。

次に、こんなものも見つけた。

```python
int1 = lambda x: int(x) - 1
```
入力した数字に1を引いたものを返す関数。
ここまでするのか、、、競プロ強い人の執念を感じる笑

## 出力関連

```python
p2D = lambda x: print(*x, sep="\n")
```
リストの要素を改行を挟んで表示する関数。
確かに、この前Atcoderやった時も、これがあると良い場面があった笑


## 入力関連 

```python
# 入力を整数に変換して受け取る
def II(): return int(sys.stdin.readline())

def MI(): return map(int, sys.stdin.readline().split())
def MI1(): return map(int1, sys.stdin.readline().split())

# 入力全てを整数に変換したものの配列を受け取る
def LI(): return list(map(int, sys.stdin.readline().split()))
# 入力全てを整数に変換して1引いたものの配列を受け取る
def LLI(rows_number): return [LI() for _ in range(rows_number)]
```

初心者の私はinput()ばかり使っていたので、まずreadline()との違いを整理する

- readline()は末尾の改行文字も読み取る
- input()は読み取った改行文字を消してくれる(つまりreadline().rstrip()と同値)

ただ、int('1\n')=1なので、このように記述できる。
引用先の人はこのようにreadline()を使っているが、input()でも代用できそう。


# よく使われるライブラリ
次に、頻繁に使われているライブラリを洗い出してみました。

## 配列関連
pythonは配列のpop,appendが遅いので、実行時間で不正解となる場合は以下のように記述してデック（両端キュー）を使う。

```python
from collections import deque
l = deque
l.append(1)
l.pop()
```

次に配列を複製する際の話

```python
# 配列が1次元の場合
list2 = list1[:]
# 2次元以上の場合
import copy
list2 = copy.deepcopy(list1)
```

1次元の場合、「list2=list1」とすると参照渡しのせいで、list2自体を書き換えてしまうとlist1も書き換えられるので、このように記述する。
2次元以上の場合は、このように記述できないのでdeepcopyを使う。

## データ構造
競プロにおいてヒープ(プライオリティーキュー)を使うことは多い。(中央値を求める場合とか)
ヒープは次のような性質を持つ

- 要素の追加(push)、除去(pop)がO(logN)の時間で出来る
- 最小値(最大値)探索がO(1)で出来る
 
最小値が頂点にくるような仕様になっているため、最大値を頂点に持っていきたい場合は-1を掛けてヒープに保存すれば良い。

以下のようにしてヒープを扱える。

```python
import heapq
heap = []
heapq.heappush(heap, 1)
heapq.heappop(heap)
```

## 辞書
pythonで通常の辞書を使う場合、キーに対応するバリューが存在しているか確認する必要がある。
そのような手間を省いてくれるのがdefaultdictである。
(競プロとかでなくとも使う場面が多い気がする)

以下のように使う

```python
from collections import defaultdict
d = defaultdict(int)
# キーがない場合のデフォルトを設定する場合、このように記述
d = defaultdict(lambda : 'Initial Value')
```

# まとめ
ざっくりこのくらいかと思うが、まだまだ足りないところも多いと思うので、随時更新していく予定。
こういう知識がいつか実務でも役に立つと信じて学習も続けていこうと思う。
Kotlinと図で学んでみるデザインパターン -6章 Prototypeパターン-

# Prototypeパターン
`prototype == 原型／模範`

```kotlin:
abstract class Product : Cloneable {
    abstract fun use(s: String)
    fun createClone(): Product {
        var p: Product? = null
        try {
            p = clone() as Product
        } catch (e: CloneNotSupportedException) {
            e.printStackTrace()
        }
        return requireNotNull(p, { "product must not be null" })
    }
}
```
```kotlin:
class Manager {
    private val showCase = hashMapOf<String, Product>()

    fun register(name: String, product: Product) {
        showCase[name] = product
    }

    fun create(photoName: String): Product {
        val p = showCase[photoName] as Product
        return p.createClone()
    }
}
```

```kotlin:
class MessageBox(private var decoChar: String) : Product() {
    override fun use(s: String) {
        val length = s.toByteArray().size
        repeat(length + 3) {
            print(decoChar)
        }
        println("")
        println("""$decoChar $s $decoChar""")
        repeat(length + 3) {
            print(decoChar)
        }
        println("")
    }
}

class UnderLinePen(private var ulchar: String) : Product() {
    override fun use(s: String) {
        val length = s.toByteArray().size
        println("¥\"" + s + "¥\"")
        print(" ")
        repeat(length - 1) {
            print(ulchar)
        }
        println("")
    }
}
```
```kotlin
fun main() {
    val manager = Manager()
    val upen = UnderLinePen("~")
    val mbox = MessageBox("*")
    val sbox = MessageBox("/")

    manager.run {
        register("strong message", upen)
        register("warning box", mbox)
        register("slash box", sbox)
        create("strong message").use("Hello World")
        create("warning box").use("Hello World")
        create("slash box").use("Hello World")
    }
}
```
MEMO
---
[データクラス - Kotlin Programming Language コピー](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/data-classes.html#%E3%82%B3%E3%83%94%E3%83%BC)
ユーザー名を変えようとしたらUbuntuが吹っ飛んだ

#初めに
僕のノートPCにはWindowsとUbuntuがデュアルブートしてあって、普段の開発等はすべてUbuntuの方で行ってました。そんな中、ふと「Ubuntuのユーザー名変えたいな」という衝動に駆られたわけです。これが後に悪夢となろうとは。好奇心のままに動いただけの少年は絶望を味わうのです。~~100秒後に死ぬOS。~~
#ユーザー名を変えようとしただけなのに
というわけで、最初にrootユーザーにログインしようとしました

```
[myname@ubuntu]$sudo su -
Password
[root@ubuntu]#
```

ここでパスワードを聞かれるのでパスワードを入力します。すると、真ん中の`$`がrootユーザーを示す`#`になり、左側の表示がちゃんとrootになりました。rootユーザーにログインできました。ここで

```
[root@ubuntu]#usermod -l 新ユーザー名 旧ユーザー名
```

を叩いて、ユーザーネームを変更し、続いて

```
[root@ubuntu]# cd /home
[root@ubuntu]# mv 旧ユーザ名/ 新ユーザ名/
[root@ubuntu]# vim /etc/passwd
```

でVim上でユーザー名を変更する所までしました。ここでですよ。ふと気付いたんですね。

***日 本 語 入 力 が で き な い***

Scrapboxとかに逐一情報をメモしてて気づいたのですがローマ字入力が効かなくなっていたんですね。僕のUbuntuはちょいちょい音割れを起こしたり、注意しないと文字入力のカーソルがあさっての方向に飛んだり、いろいろ不具合が観測されてたので、さして気にしませんでした。が、直後にまた異変が見られたんですね。

***C h r o m e が 落 ち た***

「どうやら内部でエラーが起こったようなので、Scrapboxに問い合わせてみてね」のと内容で、さすがに僕も**「あ、なんかマズい」**って思ったわけです。それで、さっきのVimの変更を戻したんですよね。すると、Scrapboxは復旧しました。よかった、日本語入力も治ったかな？

治 っ て な い

急いで元のユーザー名に戻しました。今覚えば、直した気になっていただけだったのかもしれませんひととおり治した後、一旦

```
[root@ubuntu]#exit
```

で一般ユーザーに戻った後、再び

```
[myname@ubuntu]$sudo su -
```

でrootユーザーにログインしてみました。するとどうでしょう。

```
#
```

**左側のユーザー情報が一切表示されなかったんですよね。**「やばばばばば。」何度も先ほどの手順をさかのぼり、ユーザー設定も見直しました。しかし一向にrootユーザー情報は表示されません。
「こうなったら再起動だ」と、Ubuntuを一回落として再起動させようとしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588760/e619dbb7-0e68-4cbf-79cf-0bbed7bec75b.png)
***この画面から進むことはありませんでした。***終わった。まさか再起動することなく、永遠の眠りにつかれるとは。しかし何分かした後、画面に変化がありました。「お！もどったか？」微かな期待を胸に抱きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588760/e2ff6dda-ffcd-abcd-9675-7bbd263e4e9e.png)
**非 情 な W e l c o m e**

UIをMac風にカスタマイズし、春休み中に一緒にプログラミングの勉強をしようと毎日向き合っていたLinuxディストリビューションはもういないのです。あるのはもう、偽りのUbuntuだけ。幸か不幸か、コードのファイル群はほぼすべてGitHubに上げていたので大丈夫でしたが、[サーバーの勉強会](https://qiita.com/osshan9/items/f315032285be9e3f0c4a)に行ったときに設定したSSH秘密鍵がお亡くなりになられました。これイチから設定できるのかな…しんどい…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588760/9f7a3faa-9884-961d-146f-1be7ee0028df.png)
※ちなみにUbuntuの復旧用のオプション開いたらこの有様だったので、新しくUbuntu入れるか、新しいLinuxディストリを入れることになりそうです

#最後に言いたいです
どういった理由でデータが吹っ飛ぶかはわかりませんが、その時は突然やってきます。これがWindowsに起こらなくて本当に良かったです。皆さん、悪いことは言いません。***今すぐPC上にあるすべてのファイルのバックアップを取りましょう。***ソースコードはGitHubへ。ダウンロードしてきた画像？GooglePhotoに入れておけばひとまずは安心です。OS自体は吹っ飛んでも割と復旧が効きますが、***おそらくファイル群は戻ってきません。***僕と同じ目に合わないように、日ごろからバックアップを取っておくと、いざというときに被害を最小限に抑えられるでしょう
Swift Vapor + Heroku で 本番環境やステージング環境を分けて用意できるようになる

## 概要
Swiftのvaporを利用し始め、herokuにデプロイしてアプリを動かせるようになりました！
そこで、本番環境とかステージング環境とかどうやって分けて運用するんだろうと思い、調べたら意外とさくっといけたのでメモ書きを記事にしてみました。

オチもなければ、説明も雑ですがメモベースということで許していただけると幸いです。。。

## 前提
- vaporで作成したプログラムがある or vaporの概要は知ってる or vaporの話も調べながら進められる
- homebrew がインストール済み
- herokuの概要はあらかた知ってる or herokuの話も調べながら進めれる

## 参考文献
- [vapor Deploy Heroku](https://docs.vapor.codes/3.0/deploy/heroku/)
- [Managing Multiple Environments for an App](https://devcenter.heroku.com/articles/multiple-environments)
- [Herokuに本番環境とステージング環境を構築する(Rails5、MySQL5.7)](https://qiita.com/fukuyama012/items/a09627e60718ee94bbe2)

## 手順（基本は上記の「参考文献」参照）
### 1. homebrewのインストール
```shell
brew install heroku/brew/heroku
```

### 2. vaporのディレクトリに移動（helloというアプリを作っていた場合）
```shell
cd hello
```

### 3. herokuのログイン
```shell
heroku login
heroku auth:whoami
```


### 4. gitのリポジトリ初期化
とりあえず初期化して、masterブランチ用意してコミットを終わらせときましょう

```shell
git checkout master
git add .
git commit -m "first commit"
```

### 5. 各環境向けHerokuアプリの作成（ステージング：staging、本番環境：production）
Heroku上で作成するアプリの名前はそれぞれ、vapor-staging（ステージング環境）・vapor-production（本番環境）とします。

#### 5.1 ステージング環境用のHerokuアプリ作成
```shell
heroku create vapor-staging --remote staging
```

#### 5.2 本番環境用のHerokuアプリ作成
```shell
heroku create vapor-production --remote production
```

ここから先、各環境ごとに設定を変えたい場合はherokuコマンドの末尾に`--remote staging`や`--remote production`をつけます。

### 6. Buildpackの設定
Herokuのサーバ上でSwiftのvaporを起動させるための設定をします。

#### 6.1 ステージング環境に設定
```shell
heroku buildpacks:set vapor/vapor --remote staging
```

#### 6.2 本番環境に設定
```shell
heroku buildpacks:set vapor/vapor --remote production
```

### 7. Swiftバージョンを設定
`.swift-version`ファイルがあればOK。
以下のコマンドを打ちましょう（5.1.3の部分は利用したいSwiftのバージョンにする）

```shell
echo "5.1.3" > .swift-version
```

### 8. Procfileの用意
起動するためのコマンドを`Procfile`に定義しときます。
以下のコマンドを打ちましょう。

```shell
echo "web: Run serve --env production" \
  "--hostname 0.0.0.0 --port \$PORT" > Procfile
```

### 9. Herokuへのデプロイ
Herokuのアプリが指定するリモートリポジトリにプッシュしたら、
デプロイまで自動で動いてくれます（便利！）

#### 9.1 ステージング環境にデプロイ
```shell
git push staging master
```

#### 6.2 本番環境にデプロイ
```shell
git push production master
```

エラーが出てなければ、OK

### 10. プロセス数の指定
各環境で実際に稼働するプロセス数（≒インスタンス数）を指定する。
デプロイが終わっても、この設定をしないと実際に稼働しません。

#### 10.1 ステージング環境に設定
```shell
heroku ps:scale web=1 --remote staging
```

#### 10.2 本番環境に設定
```shell
heroku ps:scale web=1 --remote production
```

### Herokuアプリで定められたURLにアクセス、Webページが表示されたらOKです！