OmniAICreator/Qiita-1.07M huggingface dataset:
Rails 3.2をmojaveにbundle installする

Mojaveで渡された古いRails動かそうとしたらbundlerコケるので備忘録。

cloneしてきて魔法の呪文、`bundle install --path vendor/bundle`を唱えると、、、コケる。

ので、コケたのに対して、淡々とオプションを指定してひたすら逃げていく。

homebrew?
---

homebrew？そんなの使うわけないでしょ。
調べててhomebrew前提の何の解決もしてないノイズ記事が多すぎてつらかった、、、、、、、

備忘録。
---

みんな嫌いなnokogiriわかる。libxml2を指定すればイケた。

```
bundle config --local build.nokogiri --use-system-libraries --with-xml2-include=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/libxml2 --with-xml2-lib=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/libxml2
```

```
bundle config --local build.libv8 --with-system-v8
```

つづいて、libOpenSSLがないっぽいので、ビルドして入れておく。要らなかったかも？
https://www.openssl.org/source/

さらにmysqlの古いのも入れる。
rails3.2はmysql2の0.3系しかダメらしく、mysql2の0.3系はmysqlの8ではビルドが通らない。
幸いにmojaveにはmysql 5.7.24が入るらしいので、dmgから。
https://dev.mysql.com/downloads/file/?id=481129

で、そいつを使うべく試行錯誤の末が以下。

```
bundle config --local build.mysql2 --with-mysql-config=/usr/local/mysql-5.7.24-macos10.14-x86_64/bin/mysql_config --with-ldflags=-L/usr/local/mysql-5.7.24-macos10.14-x86_64/lib
```

```
otool -L vendor/bundle/ruby/2.1.0/extensions/x86_64-darwin-18/2.1.0-static/mysql2-0.3.21/mysql2/mysql2.bundle
```
で確認してリンクされてるライブラリが`libmysqlclient.20.dylib`になってればOK。21.dylibだと新しい方。


```
bundle update libv8
```

therubyracerのやつ。さっぱりわからんが
`Fetching libv8 3.16.14.19 (x86_64-darwin-18) (was 3.16.14.17)`
`Installing libv8 3.16.14.19 (x86_64-darwin-18) (was 3.16.14.17)`
で新しくなってビルド通った。


`bundle exec rails server`で動いた。

ら、終わり。


正直、、、
---
こんな無駄な事に苦労するくらいだったらrailsのバージョンあげたほうがいいと思う、、、
動いてよかった。
type-gimeiというnpmモジュールを作った

# type-gimeiとは


type-gimeiは日本人の名前をランダムに返すライブラリです。

テストの時に使うことを想定しています。

rubyのgimeiにインスパイアされており、インターフェースをなるべく踏襲するようにしています。

https://github.com/abcb2/type-gimei

# 使い方

## TypeScript

```typescript

import { Gimei, Name } from 'type-gimei';

for (let i = 0; i < 10; i++) {
  const name: Name = Gimei.randomName();
  const hiragana: string = name.hiragana();
  const romaji: string = name.romaji();
  const kanji: string = name.kanji();
  const katakana: string = name.katakana();
  console.log(`
    ${hiragana}
    ${romaji}
    ${kanji}
    ${katakana}
  `);
}
```

## ES6, ES5

```javascript

const {Gimei} = require('type-gimei');
for (let i = 0; i < 10; i++) {
  let name = Gimei.randomFemale();
  console.log(name.hiragana());
  console.log(name.kanji());
  console.log(name.romaji());
  console.log('----');
}
```

```javascript


var gimei = require('type-gimei').Gimei;

var name = gimei.randomName();
var hiragana = name.hiragana();
var romaji = name.romaji();
var kanji = name.kanji();
var katakana = name.katakana();

console.log(hiragana);
console.log(romaji);
console.log(kanji);
console.log(katakana);
```

というような感じ

# 気づいた点
もともとはangularの中でダミーのデータを気軽に作りたいと思っていたところ、gimeiというgemを知り、実装もお手軽そうだったのでTypeScriptで書いてみるちょうど良いお題だと思ったので書きました。

でもRubyで簡単にかける部分をTypeScriptでやると冗長な感じになってしまったりして、そういえばTypeScriptやES6とかでメタプロってどうやるんだろうと思った次第です。

TypeScriptをbuildしてnpmにpublishする部分は[RxJS](https://github.com/ReactiveX/rxjs)のその部分からだいぶ拝借してきたのでそれなりに良い勉強になった。

TypeScript上で使う場合、tsconfigのtargetを指定することでtype-gimeiの_esm5や_esm2015にビルドしたソースを使い分けているようだった。

angular6からはnode由来のfsとかpathだったりのモジュールが使えなかったので、サンプルデータを記述しているymlファイルの読み込みを実行する方式ではなくあらかじめ変数として定義する方式に変更した。

originは[こちら](https://abcb2.github.io/blog/2018/11/27/type-gimei/)
gcloudとkubectl入りのDockerイメージを作る

# なにこれ
GKEでPersistentVolumeClaimで確保したディスクのバックアップを取るために、`gcloud`コマンドと、`kubectl`コマンドの入ったDockerイメージが必要になって、作ってみたのでメモ。

`gcloud components install kubectl`だと、容量がたくさん必要になったので、別の方法を考えた。

# できたもの

```Dockerfile
FROM google/cloud-sdk:226.0.0-alpine

RUN apk --no-cache upgrade && \
    apk --no-cache add ca-certificates && \
    curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && \
    chmod +x ./kubectl && \
    mv ./kubectl /usr/local/bin/kubectl
```

やってること自体単純で、Google公式リポジトリにあるAlpine版のcloud-sdkのイメージをベースに、kubectlのバイナリを落としてきて、実行可能にしているだけ。

単純に `gcloud components install kubectl` だと、200MBぐらい増えちゃったのが、この方法だと50MBぐらいの増加。

もしかしたら、gcloudの方も、本当に必要なコマンドだけに絞ればもっと容量が削れるのかも。

ちなみに、バックアップの方は、うまくいきました。
FlutterのRowで高さが小さい方のビューをボトムに揃える

Rowで複数のビューを配置するときにデフォルトの状態だとそれぞれのビューの高さが異なる場合、
大きいビューを基準にしてその中央に揃う形でビューが配置されます。

こんな感じ↓
<img src="https://qiita-image-store.s3.amazonaws.com/0/18273/51f47f48-b271-6b01-bb95-ab2cc83f8ed0.png" width="300px">

しかしこの小さいビューを大きいビューの上や下に整列させたいこともあります。
そんなときはRowのcrossAxisAlignmentプロパティを指定します。
crossAxisAlignmentはRowが水平方向に要素が並ぶのに対して交差する方向、つまり垂直方向のalignを指定することができます。

例えば以下のように`CrossAxisAlignment.end`を指定すると垂直方向のend、つまりボトムで整列させることができます。

```dart
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Align(
        alignment: Alignment.center,
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: <Widget>[
            Container(
              color: Colors.blue,
              width: 200.0,
              height: 200.0,
            ),
            Container(
              color: Colors.red,
              width: 50.0,
              height: 50.0,
            )
          ],
        ),
      ),
    );
  }
```

結果↓
<img src="https://qiita-image-store.s3.amazonaws.com/0/18273/463442fb-de7f-ac3e-80b8-5f1cad9fdf6f.png" width="300px">
【雑メモ】Go言語環境構築

#【雑メモ】Go言語環境構築

##1．リンク踏む。公式ダウンロードページへ
https://golang.org/dl/

##2．安定版のとりあえず一番新しいインストーラーをダウンロード
今回はWindows64bit版用、go1.11.2.windows-amd64.msiを落とした。
https://dl.google.com/go/go1.11.2.windows-amd64.msi
(2018/11/27時で安定版最新)

##3.ライセンスの同意と、環境パス設定。
特に変更する必要性がなさそうだったのでそのままnext押しまくって、
installボタン押してインストール開始

##4.インストール確認
"こんにちは"を出力するファイルを適当につくる。
ファイル名は__test.go__

    package main
    
    import "fmt"
    
    func main() {
        fmt.Printf("こんにちは\n")
    }

##5.コマンドプロンプトを実行し、以下のコマンドを実行

    $ go run test.go

こんにちは、と表示される。

おしまい。
必要があれば環境変数PathにGoのbinディレクトリを追加しておくこと。
今回インストールしたら勝手に追加されてた。
もし、コマンドプロンプトでgo runコマンド反応しなかったら再起動すること。
JavaScriptで二つの配列の差分を取得する

#はじめに
JavaScriptで配列の差分を処理する方法を考察します。
なお、本記事では以下の記事を大変参考にさせていただきました。
[JavaScriptで2つの配列の差分を抽出する - Qiita](https://qiita.com/Sekky0905/items/c9c063a826cb4322ced4)
[js 二つの配列の差分を求める - Qiita](https://qiita.com/may88seiji/items/b8fe10ebd33c0cdaf601)

#差分の処理を関数で渡してしまう
JavaScriptだと関数の引数に関数が渡せるので、差分の要素の処理を引数に関数として渡せたら面白いかなと思いまして以下のコードを考えました。

```javascript
const a = [1, 2, 3, 4];
const b = [3, 4, 5, 6];

// xにあってyにないものに対してopeに渡した関数の処理をする関数
function getDiff(x, y, ope){
    x.forEach(item =>{
        if(!y.includes(item)){
            ope(item);
        }
    })
}

// aにあってbにないものを表示する
getDiff(a, b, item => console.log('a include and b do not inclode :' +item));

// bにあってaにないものを表示する
getDiff(b, a, item => console.log('b include and a do not inclode :' +item));
```

結果

```
a include and b do not inclode :1
a include and b do not inclode :2
b include and a do not inclode :5
b include and a do not inclode :6
```

getDiffでは、配列x,yを受け取り、xにあってyにない要素に対してopeで渡された処理を行います。
opeはただconsole.logで結果を表示してるだけですが、関数自体を渡してしまえるので色々と使いわませます。
例えば差分だけのリストを作ることも出来ます。

```javascript
// 差分だけのリストを作る
let diffArray = new Array();
getDiff(a, b, item => diffArray.push(item));
getDiff(b, a, item => diffArray.push(item));

console.log(diffArray);
```
結果

```
(4) [1, 2, 5, 6]
```
テレポートした直後に特定のアクターがボケボケで表示されるから予め綺麗なやつを読み込みたい

#AActorのPrestreamTextures

指定した時間の間、実距離にかかわらずMiplevelのリクエスト値を最大まで引き上げる
0.0秒を設定した場合は30日が設定されます
これを移動が起こる、すくなくとも数秒前に呼び出しておきます

![image.png](https://qiita-image-store.s3.amazonaws.com/0/223804/c8dcc700-fffc-0064-f9de-ff4281a9fcf9.png)

#またはマテリアル毎にやりたいなら、UMaterialInterafceのこれ

![image.png](https://qiita-image-store.s3.amazonaws.com/0/223804/f020a118-efad-6dc6-ef54-4ae60dbfe134.png)

#いやいやそうじゃなくて、パーシスタントレベル移動後にボケボケになっちゃうんだけど

**フェードとか被写界深度エフェクトなんかを組み合わせて「演出」でごまかそう！**

ほかにはNumStreamingMipsを設定して、レベル移動時に最初に読み込まれるMipレベルを高めのものにする方法もあります。

https://answers.unrealengine.com/questions/427713/numstreamedmips%E3%81%AE%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6.html

例えばNumStreamMipsを3に設定する場合、
対象のマテリアルが読み込まれた時、一番解像度の高いもの(2048x2048)から3枚分小さいレベル(256x256)が下限MipLevelとして予め読み込まれるようになります。
ディフューズテクスチャだけでも高くしておくと、テクスチャストリームされるまでの時間なら割とごまかせるかもしれません。

トレードオフとしてレベルの読み込み時間が長くなり、高いレベルのテクスチャが常駐してテクスチャープールを圧迫することになってしまうのであまり極端なものにするのはおすすめしません。
爆速理解！超簡単Vuex入門①[初心者対象]

Vue.jsを業務で触り始めて半年が経過し、少しずつネタも溜まってきたので、
最初の頃に躓いた事をまとめていきたいと思います。

まずVuexを導入する際にめっちゃ初心者向けの記事がまだあまりなかったので、
（よく記事に書かれている、ストアとか状態管理とかの時点で？？？なレベルでした・・・）
・Vueコンポーネントのどのライフサイクルでdispatchするの？
とか、
・gettersで他のgettersで取得した値を引数にしたいよー
とか、
・単方向データフローがよくわからん

等々・・・初期でつまづいた箇所をまとめていければなと思います。

今回はVuexについてざっくり理解してもらえる事をゴールとして書いて行きます。

##Vuexって？
状態管理パターン＋ライブラリです。（読み方はビューエックス）
ふむ、状態管理？？

例えば、ショッピングサイトをVue.jsで作成して、
ユーザーが欲しい商品を買いものカゴに入れたり出したり、入れたり出したり、入れたりしたら、
カゴの中身は変わりますよね？
でも、カゴの中身の状態を複数のパーツで表示させたい場合、
（マイページ、購入画面、ヘッダーとかに表示したカートアイコンにカゴに入れたアイテム数とか・・・etc）
同じ共通のデータを使えたら、
それぞれのページやパーツで変更を加えても
マイページで表示したカゴにはアイテムが3件、
購入画面で表示したカゴにはアイテムが2件、
ヘッダーに表示したカートアイコンのアイテム数が5件、
なんていう不整合が起きなくなるのです。
参照も変更も各コンポーネントからアクセスできる場所に管理するので、
マイページでデータを変更しても、他のパーツも同じデータを参照しているので、同じ状態を参照できます。
また、入れ子になったコンポーネントでも、データの参照ができるので、
コンポーネントの親子間でデータのバケツリレーをするより、データが扱いやすくなります。

ローカルのデータベースだと思えばイメージしやすいかもしれません。
この各コンポーネントからアクセスできる状態を保持している場所をstoreと呼んでいます。

このstoreの管理に特定のルールを敷いてコードの構造と保守性を向上させたのがVuexなのです。
Vuexを使わずにstoreを作って運用する事も可能で、独自のstoreパターンを定義して運用しているプロジェクトもあります。

##Vuexをプロジェクトに入れる？入れない？
Vuexを入れるべきか？入れないべきか？を調べた際に出てきた記事の意見が半々くらいで（当時は）
この辺りも、私は混乱したポイントでした。

・Vuexの方が独自store定義よりも、後からプロジェクトに参画した人が触りやすくなるかも
・お気に入り機能、削除機能、ソート、絞り込み等、データに変更を加える機能が多かった
・コンポーネントが入れ子になっているので、参照しやすいように
・独自のstoreを設計できるほどの熟練者がチームにいなかった
・ゼロからstoreを設計する工数がもらえてない
等の理由から今参画させて頂いているプロジェクトでは導入しましたが、
typeScriptでゴリゴリ実装したい、とかデータフローに慣れた熟練のエンジニアがいる(独自storeの設計もドンと来い！）、とか
規模が小さいからstoreを定義するまでもなかったりとか、データ使わず部分的にVue入れてるよーとかとか・・・
プロジェクトによるので、チームで話し合って決めていくのが良いかなと思います。

##単方向データフローって？
簡単に言うと、データの流れを単方向にすること！
なんですが、ちょっと難しいですよね。。。

まずVuexには

■actions (コンポーネントから実行されて、APIの実行や、mutationsの実行を行う。)

■mutations (actionsから受け取った値をstateに保存する)

■state (状態のデータを保存しておく場所)

■getters (stateに保存された値をコンポーネントに返す)

があり、

常に

vueコンポーネントからdispatchでactionsが実行されて
↓
■actions でAPI通信して取得したデータや、VueComponentから引数で渡された値をセットしてmutationを実行
↓
■mutations でactionから引数で受け取った値などをstateにセット
↓
■state の変更は必ずmutationから行われる
↓
■getters でstateのデータをvueコンポーネントに返してあげる

のような流れになっており、
図にするとこのような図になります。
![vuex.png](https://qiita-image-store.s3.amazonaws.com/0/143859/10cb91e4-361d-a703-371c-c0a207804355.png)

図を見ると矢印が一定方向ですね！

actionsから直接stateを変更したり、mutationsからactionsを実行したりはできないのです。
このように常に同じ方向でデータを管理することを単方向データフローと言っています。

##まとめ

■Vuexって？→状態管理パターン+ライブラリだよ。
■状態管理って？→同じアプリ内で各コンポーネントや画面で同じ状態を参照、変更できる仕組み
■storeって？→取得したデータやデータの変更を保存して同じアプリ内の各コンポーネントや画面で参照、変更できる場所。
（イメージはデータベース）
■Vuexを導入する？しない？→プロジェクトの状況による。チームで話し合おう！
■単方向データフローって？→データの流れを常に一定方向で管理

ざっくりですが、なんとな～くはイメージが出来たでしょうか？
次回は簡単なサンプルを作っていきたいと思います！
xcodeで「/Fabric.framework/run: No such file or directory」でビルドできない場合

```shell
/Users/hoge/Library/Developer/Xcode/DerivedData/Kitinto-binugjelbeybstezkdkevmnfndyl/Build/Intermediates.noindex/Kitinto.build/Debug-iphoneos/Kitinto-mobile.build/Script-846C77D81C0D4E53008D6432.sh: line 2: ./Fabric.framework/run: No such file or directory
```

こんなエラーでビルドできない。


**TARGETS > Build Phases > Run Script** の


![image.png](https://qiita-image-store.s3.amazonaws.com/0/37406/d7e35eeb-707d-86ad-9087-406e0834a69c.png)


の

```./Fabric.framework/run 〜```

を

```"${PODS_ROOT}/Fabric/Fabric.framework/run" 〜```

に変えたらビルドできるようになりました！


Podfileで入れた場合や、xcodeやswiftのバージョン等で変わってくるようです。

>参考記事様
https://stackoverflow.com/questions/29071277/integrate-fabric-crashlytics-via-cocoapods/31440066

以前は通ったのに、久々触ったら通らなくなったｗ
Windowsでpexpectを利用する

<h1>経緯</h1>
以前、pexpectでWindowsのコマンドの自動化みたいなのをやろうとしてpexpectのspawnが使えないことが分かり、その流れからPexpectが使えないと思い込み、結局Linuxに切り替えて開発した経験があった。
その後はLinux中心で開発していたため知らなかったのだが、Windowsでpexpectが使用できるとのことだったので、以前を振り返りながら実際にWindowsでpexpectを利用してみた。

<h2>実行環境</h2>

```
OS:Windows10
Python Version: 3.6.1
Pexpect Version: 4.2.1
```

<h2>前提</h2>
<h3>なぜspawnが利用できなかったのか</h3>
そもそもspawnが利用できなかった理由は2つある。
1つはimport時の問題で、もう一つはspawnそのものにあった。

<h4>import時の問題</h4>
私がpexpectを使用する際に書いていたコードは以下になる。

```python:python
import pexpect
process = pexpect.spawn("cmd")
```
上記ではimportはできるものの、spawnを使用できない(has no Attributeエラーが出る。)
その原因はpexpectというmoduleの__init__.pyファイルにある。
spawnはclassであり、pexpectというpackageの中のpty_spawn.py内にある。
このpty_spawnはpexpectの__init__.pyの中でsys.platform != 'win32'の時のみimportされるように書かれている。
よってWindowsではimport pexpectではspawnが利用はできないのである。

<h4>spawnの問題？</h4>
では、なぜそのようなimport方法になっているか？
それはpty_spawnが名前の通りpty(擬似端末)を使用するplatformでの使用を前提に作られたものだからである。(そもそもpexpectがその前提で作られていたのかもしれない)
Windowsではptyを使用することはできない。そのためpty_spawnをimportしようとするとExceptionを吐く。興味がある方はやってみてほしい。

<h2>解決策</h2>
Windowsでpexpectを使用するには、pexpectのpackageの中のpopen_spawn.pyにあるPopenSpawnクラスを使用するとのこと。
pexpectのdocument[^1]に記載があるが、このクラスはpexpectのversion4.0から追加になったwindows向けのクラスとのこと。
documentのhistory等このクラスやversion周辺を読むと、既存のspawnクラスやクロスプラットフォームについても少し触れられているので、一度読んでみても良いと思われる。

<h2>作成プログラム</h2>
PopenSpawnクラスを使用したコードを作成したため載せておく。
ただし、コマンドプロンプトのコマンドを実行させて結果を取得するという用件のみを満たしたコードなので、さまざまな考慮抜けがあると思われるが、そこはご了承いただきたい。
動作確認は行っており、コマンドの実行ができていることは確認済みである。

```python:test.py
import pexpect.popen_spawn as psp

class WinPexpect():
    def __init__(self):
        self.process = psp.PopenSpawn("cmd")
        self.prompt = ">"
        try:
            self.process.expect(">", timeout=10)
        except:
            Exception("cmd expect fail")
        print(self.cmd_readlines())

    def cmd_readlines(self):
        res = ""
        res = self.process.before.decode("shift-jis", errors="ignore") + self.process.after.decode("shift-jis", errors="ignore")
        self.prompt = res.splitlines()[-1]
        self.prompt = self.prompt.replace("\\", "\\\\")
        return res

    def cmd_sendline(self, cmd, timeout=10):
        self.process.sendline(cmd)
        if cmd.find("cd ") > -1:
            self.prompt = self.prompt[:-1] + "\\\\" + cmd.split("cd ")[1] + ">"
        try:
            self.process.expect(self.prompt, timeout=timeout)
            return True
        except:
            import traceback
            traceback.print_exc()
            return False

if __name__ == '__main__':
    wincmd = WinPexpect()
    wincmd.cmd_sendline("dir")
    print(wincmd.cmd_readlines())
    wincmd.cmd_sendline(" cd log")
    print(wincmd.cmd_readlines())
```

<h2>反省点</h2>
windowsでpexpectが使えないと判断したのは、ほぼほぼ私がしっかりソースコードやdocumentを読まなかったことに原因があるといってもいい。
これに関しては今後も似たような判断をしないとは言えないため、細心の注意を払ってプログラミングを行っていきたい。


[^1]: pexpectのdocument: https://pexpect.readthedocs.io/en/stable/history.html
phpipamの日本語翻訳ファイル

[phpipam](https://phpipam.net/)はネットワーク構成管理用のPHP製のツールです。

以前、日本語翻訳ファイルを作成したのですが、本家のphpipamには、別の方のプルリクが出ていました。
一足遅かった〜と思いつつ、折角なのでなんとなくリポジトリを公開しておきます。

ちなみに本家に出ているプルリクは、エラーでまだマージされていないようです。


リポジトリは以下です。
ご自由にご利用ください。

https://github.com/undrthemt/phpipam-japanese

この記事はそのうち消すかと思います。
国土地理院の標高タイルをJavaScriptで適切に取得する

**追記**
Python版も書いた。
[国土地理院の標高タイルをPythonで取得する - Qiita](https://qiita.com/sw1227/items/877d966da9a5af53b05d)

# 1. 地理院タイルについて
## 1.1. 概要
タイル座標を指定して特定のURLにリクエストを投げると、地図画像や標高など様々な種類のタイルを取得することができる。URLはタイルの種類ごとに異なり、一覧は[地理院タイル一覧](https://maps.gsi.go.jp/development/ichiran.html)で確認できる。

## 1.2. 標高タイル
名前の通り各地点の標高が記載されたタイルで、仕様は[標高タイルの詳細仕様](https://maps.gsi.go.jp/development/demtile.html)に記載されている。
それぞれのタイルは$256 \times 256$ピクセルで、テキスト形式とPNG形式が提供されているが、以下では簡単のためテキスト形式を扱う。

### 注意点
- 単に標高がコンマ区切りで記載されているだけだが、**標高値が存在しない画素（海など）は「e」の文字が入っている**ことに注意。
- [地理院タイル一覧](https://maps.gsi.go.jp/development/ichiran.html)をみると、`DEM5A`, `DEM5B`, `DEM10B`, `DEMGM`など複数種類の標高タイルが提供されている。それぞれ対応するズームレベルや測量方法・精度が異なるため、[標高値について](https://maps.gsi.go.jp/help/pdf/demapi.pdf)を読んで適切なものを選択すること。
- 東方向がX、南方向がYになっており、ディスプレイの座標系と相性が良い


# 2. 実装
[Fetch API](https://developer.mozilla.org/ja/docs/Web/API/Fetch_API)を利用して下記のような`fetchTile`関数を使うと扱いやすい。

- コンマ区切りのテキスト形式で取得したレスポンスを改行コードで行に分割
- 各行はさらにコンマで分割
- 標高の数値はFloatへ変換
- 「e」文字（海など）を標高0[m]に変換

などの前処理を行い、二次元配列としてタイルを取得できるようにしている。

```javascript
function fetchTile(coord) {
    return new Promise(resolve => {
        fetch(`https://cyberjapandata.gsi.go.jp/xyz/dem/${coord.z}/${coord.x}/${coord.y}.txt`)
            .then(response => response.text())
            .then(text => text.split("\n"))
            .then(rows => rows.slice(0, rows.length - 1)) // Last row: empty
            .then(rows => rows.map(r => r.split(",").map(d => d === "e" ? 0 : parseFloat(d)))) // e: sea
            .then(data => resolve(data))
            .catch(error => {throw error});
    });
}
```
この実装では`DEM10B`の標高タイル（対応するズームレベルが0-14ともっとも広い）を取得しているが、必要に応じてURLの部分を変更（あるいはfetchTileの引数で指定できるよう修正）すれば良い。

# 3. タイルの取得方法
## 3.1. `fetchTile`関数の使い方
タイル座標を先述の`fetchTile`関数に与え、以下のようにする。

```javascript
const nabewariTile = {z: 13, x: 7262, y: 3232}; // 鍋割山のタイル座標
fetchTile(nabewariTile).then(d => {
    // dを利用
});
```

## 3.2. タイル座標の調べ方
### (1) 目視で確認
地図上でタイル座標を確認したければ[タイル座標確認ページ](https://maps.gsi.go.jp/development/tileCoordCheck.html)が便利。
例えば鍋割山は
<img src="https://qiita-image-store.s3.amazonaws.com/0/58850/50a93571-74f7-8e99-a632-b98886fc5dc0.jpeg" width="300px"/>
となっている。

### (2) 緯度経度から計算
ある地点の緯度経度を指定して、その地点が属するタイル座標を知りたい場合、以下のような関数を用意する。

```javascript
function getTileCoords(lat, lon, zoom) {
    const xTile = parseInt(Math.floor((lon + 180) / 360 * (1 << zoom)));
    const yTile = parseInt(Math.floor((1 - Math.log(Math.tan(lat * Math.PI / 180) + 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * (1 << zoom)));
    return { "z": zoom, "x": xTile, "y": yTile };
}
```
以上
Collection内のバリデーションを行うマクロ

Collectionで与えられた値のバリデーションをチェックするマクロです。

```php
Collection::macro('validate', function (array $validates) {
    collect($validates)->map(function($typeName, $key) {

        $data = $this->get($key, false);

        // required check.
        if (! $this->has($key) || ! $data) {
            throw new \Exception(sprintf('"%s" is required.', $key));
        }

        $messase = '"%s" Must be of the type %s, %s given!';

        // objectとそれ以外で出し分け
        switch (gettype($data)) {
            case 'object':
                if ( ! $data instanceof $typeName) {
                    throw new \Exception(sprintf($messase, $key, $typeName, get_class($data)));
                }
                break;
            
            default:
                if (gettype($data) != $typeName) {
                    throw new \Exception(sprintf($messase, $key, $typeName, gettype($data)));
                }
        }

    });
    return $this;
});
```

結果

```text
"name" Must be of the type string, integer given!
```
[Lightning Network] ⚡Lapps入門⚡

[ビットコインとか勉強会#24](https://cryptocurrency.connpass.com/event/106923/)で行った講演のスライドを公開します。これを読んでソースコードを見れば、Web Lapps がサクサク作れる！　……はず。

作ってみて不明点が出てきたら、[こちら](https://lapps.green/communicate)のコミュニティで質問すると良いと思います。

Lapps を盛り上げていきましょう！
Pythonで競プロに挑む日誌 vol.22 ~提出前のテスト~

# 現在の目標
* 2018年内に茶色になる**←イマココ**
 * [ABC](
https://kenkoooo.com/atcoder/?user=&rivals=&kind=category) の A, B 問題を全部解く
* 2018年度内に緑色を取得する
 * [ABC](
https://kenkoooo.com/atcoder/?user=&rivals=&kind=category) の C 問題を全部解く
* (水色になったら, [APG4b](https://beta.atcoder.jp/contests/apg4b) で C++ にも手を出す)

# 今日のおはなし
### 結論
問題文の入出力例以外でもテストケースを考えよう.

#### 解いた問題
[B - Counting Roads](https://beta.atcoder.jp/contests/abc061/tasks/abc061_b)

#### 入出力例だけでは穴がある
入出力例では Pass するのに, 提出したら WA となりました.

```WA.py
# coding: utf-8
N, M = map(int, input().split())

val = ",".join([input().replace(" ",",") for _ in range(M)])
print(val)
for i in range(1, N+1):
    print(val.count(str(i)))
```
下記で通りました.

```AC.py
# coding: utf-8
N, M = map(int, input().split())

lst=[]
for _ in range(M):
    lst += input().split()
for i in range(1, N+1):
    print(lst.count(str(i)))
```
文字列の連結で処理しようとすると, N が一桁であれば所望の値が出力されますが, 二桁になるとダメですね. たとえば, "12" という文字は 1 と 2 が一つずつあると判断されてしまいます.

今回はすぐ気づいたのですが, 提出前のテストで気づきたかったところ. テストのコツとかあるんでしょうか. とりあえず, 境界値や, 入出力例以外の条件でテストしてからコードを提出するのがよさそうですかね.

というか, AtCoder のテストケース公開されないかな..

# むすび
[paiza のレッスン](https://paiza.jp/works/skillcheck/primer/skillcheck1/20003) でも眺めて, 勉強しよう.
C70K2 レストア日誌 その2 〜 始動を試みる

## とりあえずオイル交換する
![IMG_0512.JPG](https://qiita-image-store.s3.amazonaws.com/0/230921/33da816b-ff3d-b3a1-429c-fb857c8e92ef.jpeg)
覚悟していたけど、乳濁した状態ではなく量は少ないながらもちゃんと黒いオイルが出てきた。
雨ざらしではなかったのか、保存状態は良かったみたい。ドレンボルトもすんなり回った。

## ガソリンを入れる
ガソリンタンクをチェック
![IMG_0513.JPG](https://qiita-image-store.s3.amazonaws.com/0/230921/16808c2c-34c0-83c2-72f9-934a212ac710.jpeg)
見た感じサビも無さそう。水も入って無さそうでカラッカラな状態。普通にガソリンを入れた。
多分問題ない。。。かな？

## とりあえずエンジンをかける準備完了
謎のスイッチがどっちがONなのかわからないので、とりあえずスイッチを切り替えながらキック。
![IMG_0518.JPG](https://qiita-image-store.s3.amazonaws.com/0/230921/9a64df3c-e01c-6901-78ae-b5f5564d4780.jpeg)

ひたすらキック。ガンガンキック。。。。 かからないねぇ。
そんな甘いことにはならないか。 キャブからガソリンが滲んでいるので（これは縦キャブの持病らしい）ガソリンはOKそう。
![IMG_0520.JPG](https://qiita-image-store.s3.amazonaws.com/0/230921/6f01d8f2-b66c-472e-7c95-95fe28d3a9e1.jpeg)

あわよくばエンジンかかればと思ったけど横着せずに、レッグシールドを外してプラグの火が飛んでるかをチェックする。レッグシールドは最近のカブと違ってエンジンにボルトオンされてるし、色々コストが掛かってそう。
![IMG_0527.JPG](https://qiita-image-store.s3.amazonaws.com/0/230921/ca267f46-c481-d652-98aa-5e172620b110.jpeg)

火が飛んでない様なので、プラグを変える。元ついてたプラグもそこまで悪くはないのだけど。。。
![IMG_0528.JPG](https://qiita-image-store.s3.amazonaws.com/0/230921/c28998ed-2246-893f-209d-0d4d1df40b8f.jpeg)

家にあった新品プラグに交換。
![IMG_0529.JPG](https://qiita-image-store.s3.amazonaws.com/0/230921/d2789311-04db-7a73-82b0-d7e06cf5f78b.jpeg)

やっぱ火が飛ばない。 メインキーについてるスイッチをどっちに入れても火が飛ばない。
このスイッチ自体も怪しいのでリフロ品のキーシリンダーに交換して様子を見ようかな。
Play With Dockerがどれほど便利か試してみた

「[Docker 入門にはインストールなしで使える「Play with Docker」がいいと思う](https://qiita.com/tag1216/items/ec7228440f6eaf849cd6)」の記事を参考に「Play With Docker」を試してみました。

今回は試しに[Rocket.Chat](https://rocket.chat/)をDockerで起動してみようと思います。

### 手順
#### ログイン
1. [Play With Docker](https://labs.play-with-docker.com/)をブラウザで開く
2. 「Login」ボタンを押し「docker」をクリック
3. Docker Hubアカウントでログイン

#### インスタンスの追加
1. 左ペインメニューの「＋ADD NEW INSTANCE」をクリック

![image.png](https://qiita-image-store.s3.amazonaws.com/0/26911/b121309d-62da-2575-d441-bafbac63663f.png)

#### Docker Compose用意
1. コマンドプロンプトエリアで　`touch docker-compose.yml` と入力してEnter
2. 「コマンドプロンプトエリア」上部にある「EDITOR」ボタンを押下すると入力できる
3. 「[Rocket.Chat を docker compose で立ち上げた](https://qiita.com/high-u/items/5303488b9cbe73b3c433)」にある「docker-compose.yml」をコピーして持ってきて貼り付ける
    * `rocketchat` の `ROOT_URL` だけは起動したインスタンスのIPに書き換え
5. 「SAVE」ボタンで保存しウィンドウを閉じる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/26911/201f6201-82a0-c1cb-e374-a32c873852b4.png)

#### Docker起動
1. `docker-compose up -d` とコマンドプロンプトエリアで打ちEnter

イメージのダウンロードが開始され、インスタンスのIPアドレス横にdocker-compose.ymlで開けたポート番号が表示されますのでクリックするとRocketChatが使える状態になります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/26911/df78b712-01af-4365-c52c-55f0f5d5ea01.png)

ポート番号はリンクになっており、クリックするだけで別タブで起動したRocketChatが開きます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/26911/b2c800ca-2242-e582-2e6b-635c444eeef2.png)

すごくお手軽に起動することができましたし、お試しで使い終わったゴミのイメージの掃除が不要なので大変便利です。

「あのイメージバージョンアップされてるけど何が変わったんだろう？」、「このOSS入れたいんだけど説得する材料として実際に触ってもらいたい」といった短期的な目的にはすごくもってこいだと思います。


以上ですー！
Kagglerへの道！

#Kaggleを始めた理由
ズバリaiの勉強がしたかったのですが、下記の理由で散々挫折。
１，以前流行ったTensorflowをやってみた。
→高マシンスペックがマスト。（当時ビットコインのせいでグラボも高止まりで手が出ず。。。）
　また、学習データが必要、検証結果のチェックも大変。
　学習と言うよりは、子供のお世話？？なんか違う。。。

２，SFDCのAIのAPIを使ってみた。
→いい感じで動くけど、ロジックが非公開。
　なので、結果揺れの原因もわからず、これではただの利用者でしかない。。。
　（SFDC派の人に誤解無いように、ワタシ的に合わなかっただけです。すみません。）

自分なりにaiというか、機械学習と言うか、ディープラーニングと言うか色々と整理してみるとやりたいことはデータを使って新しい気づきがどう生まれるかを知りたかったです。
そこで出会ったのが、Kaggleです！

#Kaggleとは
ちょっと前まではあまり日本語サイトがなかったのですが、最近はたくさんです。
あまり知見がないので、サラッと紹介すると、
##データがたくさんある！
夜空の写真、NBA試合の予想から、パン屋のレシート情報まで。
著作権にドキドキしないデータが沢山！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/256178/42d7f170-9376-50f1-7cd5-dcfe1bd366cf.png)

##答えがある？
タイタニックの生存の課題がよくサンプルでありますが、コンペ形式で答えに近いものがある。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/256178/ae04b310-7c81-bba2-ead4-5c199e62c58d.png)

##データセット、APIが公開されていてChromeBookでも開発可能！
いつもコアな開発はWindows OSやMac OSがマストでした。。。
パケットも節約しないといけないのに。。。
クライアントを経由しないの最高です！

#kaggleを始めるには
##まずはアカウント登録
Kaggleのアカウント登録です。
英語のみですが、恐れることはありません！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/256178/4e19c7e5-1884-28b1-f75d-f24c84ac250b.png)
なぜか、アイコンは可愛くないアヒル？です。

##つぎは開発環境の用意
私は最終的に、Google　Colaboratoryを採用しようと思います。

###ちょっと脱線
最初はAWS＋Dokkerで環境作って試しました。
理由は、「Dokker知らないとやばい」って２０１７年のトレンドまとめにあったので。
確かに、これは今の仕事のいろんな課題を解決してくれるメシアとなりそう。
そのときの参考は下記。
https://qiita.com/NewGyu/items/d0b0d6074e13acd51f3e

でも、Dokkerはまたしてもマシンスペック問題が発生。
安価なAWSインスタンスではおっそい。。。

そこで見つけたのが、Google　Colab！
##Google　Colabとは
端的にまとめると、Google Colabとは、Jupyter Notebookを必要最低限の労力とコストで利用でき、ブラウザとインターネットがあれば今すぐにでも機械学習のプロジェクトを進めることが可能なサービスです。
https://www.codexa.net/jupyter-lab-beta-review-ml-ide/

とても、簡単・早い・安いの３拍子です！！

ただ、ちょっと癖がある。
最低限のLinuxの知識がないとわからない。
いまいち内部構成がよくわからないので、パーミッションとかにハマるとTeratermでつなぎたくなるけど、つなげられないジレンマ。
と戦いながら進めます！

#前置きが長くなりましたが、ここからKaggleに提出までをサラッと紹介します！
##データセット読み込み！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/256178/a1825d45-3b32-d629-f746-56b131bc230d.png)
APIでGoogle　Colabにファイルをロードします。
そして、ディレクトリを作成し、kaggleのモジュールといいますかファイルをインポートします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/256178/76a0a110-cf14-997e-ae5f-1acdcdd633a5.png)
ディレクトリにパーミッションを割り当てたり、ちょっと好奇心でechoしてみたり。
##提出！
```
# submit
!kaggle competitions submit -c <competition-name> -f <submit.csv> -m "My submission message"
```
結果をクライアントを経由せずにアップロードできるのはとても幸せです。
##結果
これからに期待ということで、結果ランクは内緒です。
年末年始の宿題にしようかな。
IBM i (旧AS400）の自己学習メモ０３

# 自己学習メモインデックス

[IBM i (旧AS400）の自己学習メモ　インデックス](https://qiita.com/You_name_is_YU/items/3964849e7803c8eaf767)

# IBM i (旧AS400）の自己学習メモ０３

## モダナイゼーション

モダナイゼーションとは、数十年と経過した既存の情報システム（情報資産）を活用しつつ、最新のIT技術へとマイグレーションしていくことを意味する。
いわゆる、レガシーシステムのマイグレーションにおける、既存資産の活用だ。

## モダナイゼーションで活用できそうなキーワードメモ

### Arcad Transformer RPG

既存のRPGソースで、OPM RPG（RPG Ⅲ）やILE RPG（RPG Ⅳ）のRPGソースを、フリーフォームRPGへ変換するツール。
製品の特徴として以下のような記載がある。

> 既存のビジネスロジックをそのまま踏襲し、ソースコードコンバージョンを行うので、プログラムの挙動は一切変わりません。

引用元：https://www.sct.co.jp/business/product/000993.shtml

フリーフォームRPGは固定フォーマットのRPGと異なり、コードの記述方法がC言語やJavaなどの言語と類似する部分が多く、エンジニア不足となりつつある従来のRPG開発者問題を解決する１つの方法かもしれません。

### aXes

aXesとは、1行もソースコードを変更せずに IBM i アプリケーションをWebUIにモダナイゼーションするシステムです。
以下のような特徴があります。

- 既存の5250画面をすぐにWebページに変換
- 新しいWebアプリケーションをカスタマイズ
- モバイル機能を追加することでマルチデバイス対応が可能（スマホ、タブレットなど）
- ブラウザにDB2データを簡単に抽出して、Microsoft WordやExcelなどのデスクトップアプリケーションにクエリ出力を送信可能
- OUTQやスプールファイルへのポイントアンドクリックでアクセスを提供し、PDF、HTML、テキスト形式も利用可能
- RPGやCOBOLアプリケーションをプログラムで操作するためのホスト連携APIがある

### SSTOOL-ADV

SSTOOL-ADVとは、

> 『 IBM i 資産の継承・技術者の世代交代 』を支援するためのツールです。
> 
> 　IBM i 搭載PowerSystems(AS/400,System i,i5,iSeries)の、アプリケーション・システムの構成情報、およびプログラム解析、データベース解析などを簡単な操作で行うことができます。
> 
> アプリケーションと同一プラットフォームで稼動するため「速く、正確に、直感的に」分析結果を照会でき、美しいPDFで 各種ドキュメント作成を支援します。

引用元：https://www.istechnoport.co.jp/product/sstool-adv/

このツールで自動生成されるPDFの仕様書としては次のようなものがある。

- プログラム仕様書
    - 対象プログラムがどのファイルをIN/OUTしているか
    - 入力画面や出力帳票
    - 依存関係のある上位／下位プログラム
    - など
- プログラム機能書
    - サンプルのPDFを見た感じでは、プログラム内のコメントをいい感じにまとめて仕様書っぽくしたもの
- ファイル参照プログラム・ダイアグラム
    - 対象ファイルに対して、どのプログラムが参照しているか（依存しているか）が判別できる仕様書
- ファイルフィールド・プログラム使用表
    - 対象ファイルに対して存在するフィールドが、どのプログラムからどのように（CRUD）利用されているか
    - フィールドレベルのCRUD図？
- などなど

非常にたくさんのPDF仕様書を出力する機能があるので、メンテナンスされなくなった仕様書を最新化したい場合などにはいいと思われます。
GeoLite2をBigQueryに格納してGeoLocationを取得（IPアドレス→国情報変換）

#2021-04-11更新

Googleにgeolocationをbigqueryで扱う記事の解説
https://cloud.google.com/blog/products/data-analytics/geolocation-with-bigquery-de-identify-76-million-ip-addresses-in-20-seconds

1. サブネット表記から network_bin, maskを抽出し、付き合わせテーブルに仕込んでおく

```
create table geolite2_city as 
(SELECT *
  , NET.IP_FROM_STRING(REGEXP_EXTRACT(network, r'(.*)/' )) network_bin
  , CAST(REGEXP_EXTRACT(network, r'/(.*)' ) AS INT64) mask
FROM `fh-bigquery.geocode.201806_geolite2_city_ipv4` 
JOIN `fh-bigquery.geocode.201806_geolite2_city_locations_en`
USING(geoname_id))
```

2.join する時に下記のようにINNER JOINでIPアドレスとそれに一致するネットマスク表記を結合する。

```
select * from 
(select * , NET.SAFE_IP_FROM_STRING(ip_address) & NET.IP_NET_MASK(4, mask) network_bin from
ip_table ,UNNEST(GENERATE_ARRAY(9,32)) mask
where 
BYTE_LENGTH(NET.SAFE_IP_FROM_STRING(ip_address)) = 4)
 JOIN
  geolite2_city
using (network_bin, mask)
```

下記の方法はIPアドレスを数値に戻してIPレンジで指定していた。ネットマスクの方がASNの付き合わせとかにも応用が聞くので上の方法を推奨ですね。

#やりたいこと

IPアドレスに対してGeoLocation情報を付与したい。
BigQueryに格納しているIPアドレスにCountry,Cityの情報を付与したい。

#必要なもの

GeoLite2データ
フリー版はこちらからダウンロード
https://dev.maxmind.com/geoip/geoip2/geolite2/
GeoLite2 City CSVを使う

#手順
1
GeoLite2-City-Locations-en.csv (city_locaion)
GeoLite2-City-Blocks-IPv4.csv (city_blocks_ipv4)
をBigQueryにインポート
2.
突き合せのためのテーブルを作成

```
create table yumano.geolite2_city as 
select * from
 yumano.city_location as a 
inner join  
(SELECT
network,
NET.IPV4_TO_INT64(NET.IP_FROM_STRING(REGEXP_EXTRACT( network, '(.*)/' ) ))   as startIpNum, 
CAST(NET.IPV4_TO_INT64(NET.IP_FROM_STRING(REGEXP_EXTRACT( network, '(.*)/' ))) + POW(2, 32- CAST(REGEXP_EXTRACT(network, '/(.*)')  as  INT64 )) -1  as Int64)  as   endIpNum ,
CAST(TRUNC(NET.IPV4_TO_INT64(NET.IP_FROM_STRING(REGEXP_EXTRACT( network, '(.*)/' )))/(256*256)) as Int64)   as ClassB, 
ifnull(geoname_id, registered_country_geoname_id  )
as uniq_geoname_id, is_anonymous_proxy,is_satellite_provider,postal_code
  FROM city_blocks_ipv4 )  as b 
 on uniq_geoname_id = a.geoname_id
```
3. 
IPアドレスが入っているテーブルとJOIN

```
select 
    ACCESS_IP_ADDRESS,
    IFNULL(country_name, 'Other') AS country_name,
    IFNULL(city_name, 'Other') AS city_name
FROM (
  SELECT
    ACCESS_IP_ADDRESS,
    NET.IPV4_TO_INT64(NET.IP_FROM_STRING(access_ip_address)) AS clientIpNum,
    TRUNC(NET.IPV4_TO_INT64(NET.IP_FROM_STRING(access_ip_address))/(256*256)) AS classB
  FROM
    yumano.IP_LIST ) AS a
LEFT OUTER JOIN
  yumano.geolite2_city AS b
ON
  a.classB = b.classB
  AND a.clientIpNum BETWEEN b.startIpNum AND b.endIpNum
```


#参考

http://matsukaz.hatenablog.com/entry/2017/08/17/133923
TypeError: log.gauge.isEnabled is not a function

## 状況

- nodeのバージョン管理にtj/nを使っている
- [この記事](https://qiita.com/jigen098/items/8eec7052d235b96d5c6c)のような手順でnpmをグローバルインストールしたことがある

という状況でタイトルのエラーが出ました。ログはこんな感じです。

```
$ npm install
/usr/local/lib/node_modules/npm/node_modules/npmlog/log.js:57
log.progressEnabled = log.gauge.isEnabled()
                                ^

TypeError: log.gauge.isEnabled is not a function
    at Object.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npmlog/log.js:57:33)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:20:18)
    at /usr/local/lib/node_modules/npm/bin/npm-cli.js:22:13
    at Object.<anonymous> (/usr/local/lib/node_modules/npm/bin/npm-cli.js:148:3)
```

なお、 `$ yarn install` でも同じ状況になりました。

## 対処

`/usr/local/lib/node_modules/npm/` 以下を `rm -r` コマンドで消去し、nでnodeのバージョンを変更したら直りました。

## 考察

おそらく[この記事](https://qiita.com/jigen098/items/8eec7052d235b96d5c6c)みたいなハックをしたのが原因な気がしています。素直にnpmは放置して、yarnを使うのがよさそうな気がしました。

ぜひ同じようなエラーに当たった人は参考にしてみてください。
Git Bashのttyで怒られないように

the input device is not a TTY.  If you are using mintty, try prefixing the command with 'winpty'
というメッセージを見たくない方々へ

Git bashのMinTTYがアレなのはいつものことですが、
dockerを起動したりワンライナーを書いたり、
Node.jsに標準入力を渡たしたいときに困ることがよくあります。

```bash
$ docker run -it alpine echo Hello,World
the input device is not a TTY.  If you are using mintty, try prefixing the command with 'winpty'

$ echo 'console.log("Hello,world")' | node
stdin is not a tty
```

## 解決策


bash自体をwinptyすると幸せになれます。

```bash
$ exec winpty bash

$ docker run -it alpine echo Hello,World
Hello,World

$ echo 'console.log("Hello,world")' | node
Hello,world
```

面倒な人は最初からbashがwinpty付きで起動するように登録しても良いかもしれません。

```bash
$ echo 'exec winpty bash' >> ~/.bash_profile
```

よく調べてないですが、[この記事](https://qiita.com/icoxfog417/items/33e6b1f3dd9358923e21)によるとデフォルトでなっていないのにはなにか理由があるみたいですね。

ちなみに```.bash_profile```に書く自動起動の設定を```.bashrc```に書き込むとbashの呼び出しが再帰して死ぬので気をつけましょう。私は死にました。
Chromeのinput[type="file"]で同じファイルがアップロードできない時の対応メモ

## 現象
htmlの`<input type="file">`を使って画像アップロードの機能を実装した際、GoogleChromeで同じファイルを複数回選択しても反映されなかった。

## 原因
単純にvalueが初期化されてなかったのが原因だった。

```javascript
input.value = ''
```

GoogleChromeではvalueが自動で毎回初期化されないらしく、同じファイルを選択すると`onChange`が発火しなかった。
この3つを抑えとけばOK！パフォーマンスを意識したCSSコーディング

個人的に最近CSSを書く時に脳死になっているので、自分を戒めるためにもまとめます。

## この3つの基礎を頭に入れておく

### セレクタの詳細度
CSSはその名の通り上から順にスタイルがレンダリングされますが、どのセレクタが優先されスタイルが適用されるかを表したものが詳細度です。
詳細度はよく`A=0, B=0, C=0`のような形で表現され、優先度は`A > B > C`になります。
セレクタの指定方法によって詳細度は変わってきます。詳しく見てみましょう。

| セレクタ | 詳細度 |
| ------- | ------- |
| 全称セレクタ（*） | A=0, B=0, C=0 |
| 疑似要素（::before, ::afterなど） | A=0, B=0, C=1 |
| 要素セレクタ（div, p, inputなど） | A=0, B=0, C=1 |
| classセレクタ（.class-name） | A=0, B=1, C=0 |
| 擬似クラス（:first-childなど） | A=0, B=1, C=0 |
| 属性セレクタ（[type='button']など） | A=0, B=1, C=0 |
| idセレクタ（div, p, inputなど） | A=1, B=0, C=0 |
| インラインスタイル | ボス |
| !important | ラスボス |

上から順に詳細度が高くなっています。
例を見てみましょう。

```css
/* 1.詳細度：A=1, B=2, C=0 */
#header .gnav .gnav-item {
  color: red;
}

/* 2.詳細度：A=2, B=1, C=0 */
#header #gnav .gnav-item {
  color: red;
}
```

上記の場合、詳細度の高い2番目のスタイルが適用されます。

### セレクタは右から左に照合される
セレクタは右から左の順に照合されます。

```css
div p span {
 color: red;
}
```

上記の場合、最初に`span`要素を探します。
次にその親要素に`p`要素があるもの、さらにその親要素に`div`があるものを調べ、スタイルを適用します。
この例の場合、多数ある要素セレクタを調べレンダリングしているので、時間がかかりパフォーマンスがよくありません。

### 同じスタイルを何度も書かない
同じようなスタイルを複数回書いていると気づいたならば、その記述は共通化することができます。
汎用的に使えるクラスや変数、sassのmixinやextendsを定義するとよいでしょう。

## 結局どんな書き方がパフォーマンスいいの？
上記を踏まえたポイントをまとめます。

- 1.セレクタを連ねるほど照合とレンダリングに時間がかかるので、セレクタの数は最小限に！
- 2.詳細度は常になるべく低く設定することを心がければ、上書きする際もシンプルに記述できる！
- 3.同じスタイルは共通化する

例を見てみましょう。

```css
/* パフォーマンスの悪いCSS */
#hoge .box .box-inner p span {
  padding: 10px;
  color: #000;
  font-size: 14px;
}
#fuga .box .box-inner p span {
  padding: 10px;
  color: #000;
  font-size: 14px;
}
```

この場合、`span`から順にセレクタを照合していき、一番左のidセレクタに到達するまでレンダリングが開始されません。
しかも同じスタイルなので、この照合の時間はとても無駄になります。
3つのポイントを参考にリファクタリングしてみましょう。

```css
/* パフォーマンスを改善したCSS */
.box-text {
  padding: 10px;
  color: #000;
  font-size: 14px;
}
```

`span`に共通のスタイルを適用するためにclassを付与し、`.box-text`だけをセレクタに指定しました。
こうすることで`.box-text`を照合するだけでよくなり、同じスタイルをレンダリングするのに無駄な時間を使うことはなくなりました。

## まとめ
CSSのパフォーマンスを改善する方法は他にもありますが、この３つを常に頭に入れて実行すれば、きれいでパフォーマンスの良いCSSを保つことができるはずです。
Windows PowerShell　初回スクリプト実行時に弾かれる問題

# 問題

Windows 使用時にフォントを一括でインストールしてくれるスクリプトが配布されていたのですが、
実行するときにエラーが出てしまいました。

```powershell

C:\Users\TestUser\Documents\Project\fonts\install : このシステムではスクリプトの実行が無効になっているため、ファイル
 C:\Users\TestUser\Documents\Project\fonts\install.ps1 を読み込むことができません。詳細については、「about_Execution
_Policies」(https://go.microsoft.com/fwlink/?LinkID=135170) を参照してください。
発生場所 行:1 文字:1
+ C:\Users\TestUser\Documents\Project\fonts\install
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : セキュリティ エラー: (: ) []、PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess
```

PowerShellは日本語で細かく対処法を記述している他、URL等も提示してくれるなんて、、優しい世界。

# 解決法

解決した時のコマンドを記載します。

```powershell
> Get-ExecutionPolicy
Restricted

> Set-ExecutionPolicy -Scope CurrentUser Unrestricted
実行ポリシーの変更
実行ポリシーは、信頼されていないスクリプトからの保護に役立ちます。実行ポリシーを変更すると、about_Execution_Policies
のヘルプ トピック (https://go.microsoft.com/fwlink/?LinkID=135170)
で説明されているセキュリティ上の危険にさらされる可能性があります。実行ポリシーを変更しますか?
[Y] はい(Y)  [A] すべて続行(A)  [N] いいえ(N)  [L] すべて無視(L)  [S] 中断(S)  [?] ヘルプ (既定値は "N"): Y
```

細かな内容は以下のURLに書いてありますが、せっかくなので簡単に解説していこうと思います。

https://docs.microsoft.com/ja-jp/previous-versions/windows/powershell-scripting/hh847748(v=wps.640)

## ポリシー

信頼されているスクリプトしか実行しないようにポリシーが設定されています。
ポリシーには、

- 署名の有無
- 署名の信頼度
- スクリプトファイルの実行可否
- 実行時の警告の有無

などが定義されています。
適切なポリシーに設定することで悪意あるスクリプトなどの実行を防ぐことができます。
誤ったポリシーに設定してしまったまま放置すると危険なので、行いたいことが終われば元に戻すなど対処しましょう。

## ポリシーの設定

ポリシーの設定はコマンドを使用します。
まず、現在のポリシーを確認しましょう。

```powershell
> Get-ExecutionPolicy
Restricted
```

`Restricted`となっています。これは、 Windows 8、Windows Server 2012、Windows 8.1 の既定の実行ポリシーです。
これではすべてのスクリプトの実行ができませんので、新たにスクリプトが実行できるように設定を変更します。
変更方法は以下です。

```powershell
> Set-ExecutionPolicy -Scope CurrentUser AllSigned
```

`AllSigned`というのがポリシー名です。
こちらは、説明されているサイトでこう記載されています。
> - スクリプトを実行できます。
> - ローカル コンピューター上で記述されたスクリプトを含むすべてのスクリプトと構成ファイルが、信頼された発行元によって署名されている必要があります。
> - 信頼されているかどうかがまだ分類されていない発行元のスクリプトを実行する前に、確認メッセージが表示されます。
> - 署名されているが悪意のあるスクリプトが実行される危険性があります。

## 名称一覧

https://docs.microsoft.com/ja-jp/previous-versions/windows/powershell-scripting/hh847748(v=wps.640)#windows-powershell-%E3%81%AE%E5%AE%9F%E8%A1%8C%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC

詳しくは上記URLを見ましょう。簡単に文言の一覧だけ以下に記載します。

||名称|スクリプトの実行|署名（信頼済み）である|署名（信頼なし）である|インターネット上からダウンロードした|ローカルで作成した|備考|
|:---|:---:|:---:|:---:|:---:|:---:|:---:|:---|
|1|`Restricted`|×|×|×|×|×|スクリプトの実行が出来ない|
|2|`AllSigned`|〇|〇|×|△|△|信頼された発行元の署名が必要|
|3|`RemoteSigned`|〇|〇|△|△|△|インターネット上は署名が必要、ローカルはなくてもよい|
|4|`Unrestricted`|〇|〇|〇|〇|〇|インターネット上のものは警告が表示される|
|5|`Bypass`|〇|〇|〇|〇|〇|警告等表示もなし|
|*|`Undefined`||||||未定義。すべて定義されていない場合は既定の`Restricted`となる|

## さいごに

WindowsPowerShellはちゃんと解決方法がシェル上に出てくれるので、ありがたいなと思いました。
最近はUbuntu18もWindowsStoreからダウンロードして、Bash on Ubuntu で起動できるので、使っています。

一応備忘録として書きました。間違ってたらご指摘お願いいたします。
IBM i (旧AS400）の自己学習メモ０２

# 自己学習メモインデックス

[IBM i (旧AS400）の自己学習メモ　インデックス](https://qiita.com/You_name_is_YU/items/3964849e7803c8eaf767)

# IBM i (旧AS400）の自己学習メモ０２

## AS400上でのプログラム開発 RPG

### OPM RPG と ILE RPG

ざっくり表現すると、

- OPM RPGはRPG Ⅲ
- ILE RPGはRPG Ⅳ

を指すようだ。

- OPM RPG
    - OPM(Original Program Model）と呼ばれる
    - `CRTRPGPGM`コマンドによってプログラムオブジェクト（*PGM）のファイルを生成する
        - RPGソースコードをコンパイルして生成したプログラムオブジェクト
- ILE RPG
    - ILE（Integrated Language Envoroment）
    - プログラムオブジェクトの生成方法がOPM RPGよりもバリエーション豊富
        - `CRTBNDRPG`コマンドでRPGソースコードをコンパイルしてプログラムオブジェクトを生成
        - `CRTRPGMOD`コマンドでモジュール（*MODULE）を生成し、そのモジュールを利用して`CRTPGM`コマンドによりプログラムオブジェクトを生成
        - 生成したモジュールを利用し`CRTSRVPGM`コマンドによりサービス・プログラム(*SRVPGM)を生成
        - サービス・プログラムとモジュールオブジェクトを複数組み合わせて`CRTPGM`によりプログラムオブジェクト（*RPG）を生成することが可能
    - ILE RPGでは、１ソース＝１プログラムオブジェクトではなく、Nモジュール＋Nサービス＝１プログラムオブジェクトという考え方となっている。
    - サービスプログラムはWindowsでいうところのDLLであるため、生成されたプログラムオブジェクトに同梱されることがなく、実行時にサービスプログラムを参照して依存関係を解決する仕組みとなっている。

## RPG開発

### 仕様書

RPGの開発では、プログラムの処理内容に応じた最大7種類の仕様書があり、必要に応じて使用する。

- 制御仕様書（H仕様書）
    - プログラム名や日付の形式などの機能を指定し、プログラムの生成および実行に関する情報をコンパイラに提供する
- ファイル仕様書（F仕様書）
    - プログラムで使用する全ファイルを記述する
- 定義仕様書（D仕様書）
    - プログラムで使用するデータの固定情報や変数などを記述する
- 入力仕様書（I仕様書）
    - プログラムで使用される入力レコードやフィールドを記述する
- 演算仕様書（C仕様書）
    - プログラムの開始から終了までの処理の流れを記述する
- 出力仕様書（O仕様書）
    - プログラムで使用される出力レコードやフィールドを記述する
- プロシージャ仕様書（P仕様書）
    - サブプロシージャの始めと終わりにマークを付け、サブプロシージャ名およびエクスポートするかどうかの指示を記述する
DSaaSのインスタンス側の基本設定(Agent push)

# インストール

ここから自分のOSにあったパッケージをダウンロード。
https://help.deepsecurity.trendmicro.com/ja-jp/software.html

今回はUbuntu 14.04にインストール。

```
wget https://files.trendmicro.com/products/deepsecurity/en/10.0/Agent-Ubuntu_14.04-10.0.0-3107.x86_64.zip
mkdir Agent-Ubuntu_14.04-10.0.0-3107.x86_64
unzip Agent-Ubuntu_14.04-10.0.0-3107.x86_64.zip -d Agent-Ubuntu_14.04-10.0.0-3107.x86_64
cd Agent-Ubuntu_14.04-10.0.0-3107.x86_64
sudo dpkg -i Agent-Core-Ubuntu_14.04-10.0.0-3107.x86_64.deb
```
これでインストール完了。起動も完了。
ポリシーをManagerで設定したあとはdeployment scriptで適用したいポリシーなどの項目を設定。
スクリプトが下に表示されるので、最後のコメントアウトされた一文をコピーしてターミナルから実行。

```
/opt/ds_agent/dsa_control -a dsm://agents.deepsecurity.trendmicro.com:443/ "tenantID:XXXX-YYYY-ZZZZ-WWWW-VVVVVVVVVVVV" "token:VVVVVVVV-WWWW-XXXX-YYYY-ZZZZZZZZZZZZ" "policyid:XXX"
```
これでManager側からみて表示されればOK


# アンインストール
[ここ](https://help.deepsecurity.trendmicro.com/ja-jp/Get-Started/Install/ig-uninstall-basic.html)に書いてありますが、

```
sudo dpkg -r ds-agent
```
これで完了。
CSS グラデーションでドロップシャドウ

ドロップシャドウだと難しいときあるので
疑似要素でグラデーションする方式

```scss
.gradation {
  position: relative;
  &:after {
    content: "";
    width: 100%;
    height: 8px;
    position: absolute;
    left: 0;
    bottom: -8px;
    background: linear-gradient(0deg, rgba(255, 255, 255, 0) 0%, rgba(0, 0, 0, 0.1) 100%);
  }
}
```
[小ネタ]appEngine(nodejs)のdeployが急に失敗しだしたら、package.lock.jsonを消すと治るかも

# 起こったこと

appEngine(nodejs)で開発中にdeployが失敗するようになった。deployを再実行しても同じように失敗する。


```js:エラーログ
Updating service [default]...failed.
ERROR: (gcloud.app.deploy) Error Response: [9] Cloud build hogehoge-hoge-hoge-hoge-hogehoge status: FAILURE.
Build error details: {"message": "`npm_install` had stderr output:\nnpm WARN tar ENOENT: no such file or directory,
```

# 解決

package-lock.jsonとnode_modulesを削除して再デプロイすると通った。

deployする際に、node_modulesを取得し直しているので、おそらくpackage-lock.jsonが原因だが
ローカルで、再度 `npm i` をしてpackage-lock.jsonを生成しても正常に動作した。
そして、それ以降package-lock.jsonが入った状態でdeployも正常に走るため、エラーが起こった原因はわからなかった。

以上です。
LXDコンテナでDockerが起動しない（起動に失敗する）問題への対応方法

2019/2/7:こちらに最新の対応方法を記述しました。
https://qiita.com/tabimoba/items/e14ad812a148afc10b13

## はじめに
Dockerの仕様変更により、LXDコンテナ上にDocker 18.09にインストールしてDockerを起動しようとすると、Dockerサービスが立ち上がらないという問題が発生しています。

## 現象
LXDコンテナ上でdockerサービスを起動しようとすると、サービスの起動に失敗します。
```journalctl -xe``` を実行すると、以下のログが出力されます。

```
Nov 27 07:05:23 *********** modprobe[2576]: modprobe: ERROR: ../libkmod/libkmod.c:586 kmod_search_moddep() could not open moddep file '/lib/modules/4.4.0-1072-aws/modules.dep.bin'
Nov 27 07:05:23 *********** modprobe[2576]: modprobe: FATAL: Module overlay not found in directory /lib/modules/4.4.0-1072-aws
```

## 対応方法
```/lib/systemd/system/containerd.service``` ファイルを次の通り変更してから、```systemctl start docker``` を実行すると、現象が解消されます。（ExecStartPreをコメントアウトします。）


```/lib/systemd/system/containerd.service
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target

[Service]
# ExecStartPre=/sbin/modprobe overlay
ExecStart=/usr/bin/containerd
KillMode=process
Delegate=yes
LimitNOFILE=1048576
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity

```

上記対応でとりあえず問題なく動いています。問題がある場合は追って記載します。

## 参考
- Containerd Issue - Can't start Docker service
 - https://discuss.linuxcontainers.org/t/ubuntu-18-04-18-09-0-docker-on-lxd-3-0-2-3-6-is-broken/3202/2https://www.reddit.com/r/Crostini/comments/9z4dam/containerd_issue_cant_start_docker_service/
- ExecStartPre=/sbin/modprobe fails inside LXC
 - https://github.com/containerd/containerd/issues/2772
- 18.09: containerd depends on overlay
 - https://github.com/docker/for-linux/issues/475
新春　FileMaker なんでも黙々と　語ろう会は　API 　連携の　みなさんの　初夢を　語り合いたい


いよいよ　外部連携　の　語り合いを　本格化　したいな　と思う　このごろ。
FileMaker の　レポジトリ　からの　みんなが　普通に　可視化したい　ダッシュボード　を　１０パターン　は　本格的に　確立　したいものです。
Yellowfin と　連携　して　ほんとうに　現場　が　役に立つ　可視化　を　必ず　実現しよう　させましょう

さぽらぼ は、15:00 から 18:00に FileMaker に関連するお題のよもやまばなし、【 ラボトーク 】を参加者のみなさまといっしょに展開しております。
AWS Transfer for SFTPを触ってみました

久しぶりの投稿です。

[AWS Transfer for SFTP](https://aws.amazon.com/jp/blogs/news/new-aws-transfer-for-sftp-fully-managed-sftp-service-for-amazon-s3/)が発表されたので、早速触ってみました。

***  
実際には以下のようなステップで作成できます。

##### 事前準備
- sftpサーバ用のLogging roleとユーザ用roleの作成 
- sftp用の秘密鍵/公開鍵の準備(既存のものでも新規作成したものでも可)  


##### Server作成
- AWSのマネジメントコンソールから "AWS Transfer for SFTP"をクリック
「Create server」をクリックした後、以下を設定して「Create server」をクリックして作成

  - Create server  
      - DNS configration：「None」を選択
      - Identity provider：「Service Managed」を選択(sftpサーバとユーザの管理をAWS側で実施してくれる)  
　　 　　　　　　「Custom」はAPI Gatewayとの連携が必要なようなので未検証
      - Logging role：事前準備で作成したIAMロールを選択
      - Tags：必要に応じて設定

##### User作成
- 対象のsftpサーバのチェックボックスをチェックして「Add User」をクリック
  - Add User
      - User configration  
          - Username：任意    
          - Access：事前準備で作成したIAMロールを選択  
          - Policy：「None」を選択(「Select a policy from IAM」で別途ポリシーを追加付与可能)  
          - Home directory：データをアップロードしたいバケットを選択(フォルダは任意)  
          - SSH Public keys：別途用意しておいた公開鍵を登録  

***  
##### 注意事項や気づいた点 
- IAM設定
  - ロール  
    アクセス権限：ロギングCloudWatchLogsへのフルアクセス権限をもったポリシーを付与(権限は別途調整)  
　　　　　　　S3は指定したバケットへのListBukectとPutObject,GetObject,DeleteObject権限をもったポリシーを付与  
　　　　　　　またはS3へのフルアクセス用ポリシーを付与して、必要に応じて別途ユーザに付与するポリシーを作成・付与する  
信頼関係：エンティティを **"transfer.amazonaws.com"** にする(一番重要！)  

- Create server
  - DNS configration：  
     - Amazon Route53 DNS aliasを選択すると、指定したFQDNに紐付いたDNSレコードセットが"新規で"作成される  
→既存ドメインでレコードを設定したい場合は「Other DNS」を選択して、FQDNを入力する  
DNS側には作成したsftpサーバのEndpointを **CNAME** で登録する(Aliasレコードは使えない→使えるようになってほしい！)  
     - Custom hostnameを設定すると、serverのTagsに"Key:aws:transfer:customHostname","Value:設定したFQDN"が追加される  

※参考：
https://docs.aws.amazon.com/transfer/latest/userguide/requirements-roles.html
https://docs.aws.amazon.com/transfer/latest/userguide/users-policies-all-access.html


- Logについて
  - Logging roleを設定しておくと、CloudWatch Logsに自動的にログが反映される  
サーバ単位でロググループが作成されて、ユーザ単位のログストリームが反映される  
サーバの詳細画面から「View Logs」をクリックするとロググループ内のログストリーム一覧が表示される  
ユーザの詳細画面から「View Logs」をクリックするとユーザ単位のログストリーム一覧が表示される  


***  

API Gateway経由での設定など、まだまだ他にも面白そうな設定がありますが、とりあえず設定してみました。 
少しでも誰かのお役に立てば幸いです！

***  
追記：
すでにクラスメソッドさんで記事になっていました！
このスピード感、本当にすごいなぁ。
https://dev.classmethod.jp/cloud/aws/try-aws-transfer-for-sftp/
API設計 - APIを汎用的に公開するか特定の用途のためのAPIを作るか


##課題意識
クライアントとバックエンドを分離したアプリケーションを構築する時に、APIの設計で迷うことがあります。
一般的に公開しているAPIは汎用的に作られていて、例えばユーザー情報であればget users で id, name, updated_at, .... と全てのキーが取れます。

しかし、実際にクライアントが利用するキーはそのうちの一部です。

ブラウザからのアクセスを前提にするサービスの場合、不必要にデータを公開するとで情報が漏れてしまうきっかけになってしまはないだろうか？

自分でAPIを作る場合、どのようなAPIを作るべきだろうか？

このような課題について僕なりに考えてみたので記述します。

##選択肢
APIを汎用的にするか、APIを特定の用途のために作成するかを考えることになります。

##トレードオフ

###1.汎用的に多くのキーを公開した場合
####メリット
APIが汎用的になる。
####デメリット
クライアント側で実際に利用する形式にデータを加工する必要がある。
不必要に余計なデータを見せてしまう事になる。

###2.APIをクライアントが利用するデータ形式に加工する場合
####メリット
クライアント側のデータ処理のロジックを最小限に抑えられる。
####デメリット
サーバー側のAPIの汎用性が下がりロジックが複雑化する


##ではどうするか？

###TwitterやSlackのようなAPIからの利用を前提とするアプリ
APIは可能な限り汎用的に設計し、サーバー側にアグリゲーションやサマリなどの処理はあまり記述しなくて良いでしょう。この場合はあまり問題になりません。

###SPAなどCLientアプリからのAPI利用が前提となる場合

このケースが問題になります。
TwitterやSlackなどの便利なAPIのイメージとは違い、データを公開しすぎないようにAPI毎に特定のデータを返す事になります。

なので、クライアント側とサーバー側の両方にデータ処理のロジックを持つ事になります。

ここをうまく処理するとサーバー側のロジックの汎用性を高めつつView側の処理を最低限に抑えられます。

以下、どのようなロジックをどの場所で処理すべきかに関して記述します。

####Modelに相当するレイヤーに定義すべきロジック
データ構造の定義はModelに持つ事になります。
ここは特に問題ないでしょう。

####コントローラーに相当するレイヤーに定義すべきロジック
データから計算を行うなどAPI特有のロジックはここに入れる事になるかと思います。
例えば、フォロワーとフォローしているユーザーの差がx人以上離れているユーザーの取得というようなケースです。
このようなデータ加工のロジックはAPIの利用を直接的に強く意識しておりコントローラーに入る事になるかと思います。
ユーザー全体のサマリの計算などもコントローラーに持つ事になるでしょう。

####コントローラーとモデルの間のレイヤーに定義すべきロジック
データ取得の範囲を限定するロジックがここになるかと思います。
例えば、ユーザー全体のうち18歳以上かつ男性のユーザーを取得するというようなケース。
このような処理はデータ構造の定義とデータ加工・計算の間に位置しま。ORMを利用しているとscopeの定義などで一部モデルにこの処理を埋め込むことができますが、概念的にはコントローラーとモデルの間のレイヤーの処理となると思います。
このレイヤーを意識することで、複数のAPIに利用するための汎用的な処理を切り出すことができます。

####クライアント側に相当するレイヤーに定義すべきロジック
並べ替えの処理などがここに入ります。
クエリでソートをかけてデータを取得できるのでそちらで並べ替えたくなるかもしれませんが、降順昇順などでデータの並びが動的にViewによって変えられます。
なので、データの範囲も値も変わらないような処理はクライアントに持ちましょう。
また、個別データとサマリデータの両方を表示する、といった場合は動的にサマリが変更するのでサマリ計算はクライアント側で行った方が良い場合が多いでしょう。

まとめると
1. データ構造の定義はモデルに
2. データの加工・計算はコントローラーに
3. データの範囲のロジックはモデルとコントローラーの間に(ここが意識されずらく重要なPoint)
4. データの並べ替えや一部サマリ計算はコントローラーに

###おさらい
■APIからのサービス利用を前提とする場合は汎用的に
■SPAなどのクライアントアプリからのアクセスを前提とする場合はAPIは限定的にアクセスさせ、処理を汎用化するにはサーバー側のロジックを以下を意識して整理する。
1. データ構造の定義はモデルに
2. データの加工・計算はコントローラーに
3. データの範囲のロジックはモデルとコントローラーの間に(ここが意識されずらく重要なPoint)
4. データの並べ替えや一部サマリ計算はコントローラーに
FileMaker の　みんなが　おかわり　したくなる　自動化を　自分の仕事で　実践してみる

その１　必要なデータを　集計する

その２　必要なデータを　集計した　レイアウト画面を　完成させる

その３　必要なデータを　集計した　レイアウト画面を　画面ショット　で保存する

その４　必要なデータを　集計した　レイアウト画面を　画面ショット　で保存した画像を　関係者に　メール送信する

その５　喜んでもらったら　かならず　【こんなレポートも出してくれないかしらん？】　と　おかわり　を　もらえる
＜初心者向け＞アプリケーションの精度を上げる効率的な学習方法

[プログラミング教室ITWORKS](http://listenmaker.1strentalserver.info/itworks/)のayakaです。

プログラムを組むこと自体は小学生くらいから行っていましたが、アプリケーションの精度を上げて製品レベルで書けるようになったのはつい最近であまりにも時間がかかりすぎました:joy:

これから開発を始める学生や初心者プログラマーに向けて、効率的なプログラミング学習方法をまとめたいと思います。また、これから学習する方々が「意図した動作ができた」にとどまらず、自作したアプリケーションの精度を上げるきっかけになればうれしいです。

# 一つのプログラミング言語を深く学習する
COBOLやC言語が出始めた頃と違い、現在はプログラミング言語が数多くあります。プログラミングを学習する上では専攻する言語をまず一つ決めてその言語による開発を繰り返すことが大切です。もちろんアプリケーションを作る上で複数の言語を使用することは多々ありますが、自分の基礎となる言語を決めてその言語を使った開発を数多く行うことをおすすめします。初めから様々な言語に触れて学習するのは各言語がもつ記述作法に振り回されがちです。
プログラミング言語は数多くありますが、元をただせばすべて同じ機械を動かすために作られたものです。一つのプログラミング言語を深く学習する事で各言語の記述作法に振り回されず他のプログラミング言語の取得も容易になります。

# コメントを記述する
私もそうでしたがプログラミング初心者であればあるほどコメントを疎かにしがちです。"理解する"よりも"動作する"に重きを置いてしまうためです。しかし実際には"動作する"事は大して重要な事ではありません。なぜ動作したのか？自身が書いたプログラムが"最適解"なのかそれが説明できるかが大切です。
###一行一行コメントを記述する
こう書くと玄人さんにはコメントも精査しろと言われそうですが、初心者に限って、なぜこの場所にこの記述をしたのかについてコメントをなるべく詳細に書くべきです。曖昧な理由(なんとなくやネットの記事で書いてあったから等)で記述している箇所を発見し、見直すという事が必ず必要です。

```java:HelloWorld.java
public class HelloWorld {
	public static void main(String[] args) {
		//コンソールに出力する
		System.out.println("Hello World");
	}
}
```
初心者に限り上記のようなコメントでは少ないです。
私がレビュアーであれば下記のような質問をします。

 - mainのメソッドの仕様書の定義は？
 - argsで受け取る内容は何か？
 - 何故新規のメソッドを作らすmainで実行しているのか？
 - staticで実行する意味があるのか？

コメントを書く事で曖昧にしている箇所を発見することができます。
また加えて下記のような質問もします。

 - このクラスは何をするためのクラスなのか？

クラスの役割をコメントで書くと同時に自分が決められる名称に理由をつけることも大切です。コメントをつけると同時に名称に関しても見直してみてください。

# 最小を考える
自分で書いたプログラムが"最適"であるかを判断するのは非常に難しい事です。
初心者であればなおさら難しいですし、意図した動きが出来てしまうとそのプログラムの考察をやめてしまうことが多々あります。
ですが、今一度"そのプログラムが最小であるか？"という観点で考察してみてください。冗長なプログラムはバグを生むことになり改変も困難です。

 - 重複を無くす(メソッド化する)
 - 処理自体がいるか検討する
 - 複数の処理をするメソッドをなくす
 
上記を守り、クラス毎の役割を明確にすることが大切です。そうすることで他のアプリケーションで再利用可能なクラスができ、自己資産を増やすことに繋がります。また処理を単体で実行できるとテストを容易にできます。

#まとめ
今回は自己開発したアプリケーションの精度を上げるために効果的な学習方法として下記３つの方法を紹介しました。あなたのアプリケーションや学習方法を見直すきっかけになったら幸いです。

 - 一つのプログラミング言語を深く学習する
 - コメントを記述する
 - 最小を考える