OmniAICreator/Qiita-1.07M huggingface dataset:
【PHP】対話モードに入る方法と注意点。サクッとコードを確認する方法。

PHPでコードを簡単に確認したいときに、phpの対話モードが使える。

コマンド`php -a`を実行するだけ。

```
$php -a
Interactive shell

php >
```


<br>
###Dockerのコンテナ内でphp対話モードに入る場合

```
#PHPのサーバーが起動していることを確認
$docker ps
CONTAINER ID   IMAGE                   COMMAND                  CREATED        STATUS        PORTS                                            NAMES
1b52690b15e1   php_server_dev:latest   "/docker/development…"   20 hours ago   Up 18 hours   9000/tcp, 0.0.0.0:13001->80/tcp                  php_server_dev
```

コンテナ名は`php_server_dev`

```
#コンテナに入る
$ docker exec -it php_server_dev bash

#対話モード起動
root@1b52690b15e1:/app# php -a
Interactive shell

php >
```


##対話モード実行時の注意点
コードの終わりに`;`必須。セミコロンがない場合改行してもコードが続いているとみなされる。

```
php > echo "a";
a

#;があるまで式が終わりとみなされない
php > echo "a"
php >
php >
php >
php > ;
a
```
鬼滅の刃に見るエンジニアタイプ

[Ateam Finergy Inc. Advent Calendar 2020](https://qiita.com/advent-calendar/2020/ateam-finergy) の24日目は
株式会社エイチームフィナジー 金融メディア事業部の@NMura3が担当します。
バックエンドの開発をメインでやっています。
[Ateam Group Manager ＆ Specialist Advent Calendar 2020](https://qiita.com/advent-calendar/2020/ateam) の[6日目](https://qiita.com/NMura3/items/e94e4cf788f8263b06ed)にも書かせていただきました。

今回はプログラミングの内容ではないため、noteの記事をシェアさせていただきます。

記事はこちら↓
[鬼滅の刃に見るエンジニアタイプ](https://note.com/nmura003/n/n4932484dbdf1)
Heroku openで503エラーがでた話

初投稿です。長すぎても私が疲れてしまうのでざっくりとした文章で書いてます。読みにくいかもしれませんがご了承ください。
本記事は<a href= "https://qiita.com/shimajiri/items/cf7ccf69d184fdb2fb26">こちら</a>の記事を参考にさせていただきました。

#　環境
WSL2（Ubuntu-20.04 LTS）
Docker
Heroku 
Line-bot-sdk=1.18.0
Flask=1.1.2

# Heroku にデプロイ
前提として、

- line developersの登録
- Flaskとline-bot-sdkをインストール
- Herokuに登録
- アプリケーションの登録
- 環境変数の設定
- webhookの設定
- 設定ファイルの作成

は終わっているものとして話を進めたいと思います。

## 変更内容を反映・デプロイ

    # git add .
    # git commit -am "make it better"
    # git push heroku main

## デプロイの確認

     # heroku open
      ▸    Error opening web browser.
      ▸    Error: Exited with code 3
      ▸
      ▸    Manually visit https://あなたのアプリケーション名.herokuapp.com/ in your browser.

chromeで「https://あなたのアプリケーション名.herokuapp.com/」を開くと、以下のような画面でアプリケーションエラーになった。
※本来ならば Hello World が表示される。
![84308945cc9dcd981c2d383e42478eb7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682477/21f641a0-372a-6b8b-4374-9e0714b4bc52.png)

heroku logs --tailをしてみて！と言われているので確認する。

    # heroku logs --tail

    2020-12-22T11:49:11.712077+00:00 heroku[router]: at=error code=H14 desc="No web processes running" method=GET 
    path="/" host=あなたのアプリケーション名.herokuapp.com ...
    2020-12-22T11:49:12.443226+00:00 heroku[router]: at=error code=H14 desc="No web processes running" method=GET p 
    ath="/favicon.ico" host=あなたのアプリケーション名.herokuapp.com ...

Code＝H14 、status=503とでたので対策を考える。ネットで調べると以下の方法が見つかった。
### 方法1

     # heroku ps:scale web=1
### 方法2
Herokuを再起動する

     # heroku restart --app application_name
     # heroku stack:set container

等の方法があったが失敗。その後、色々調べた結果。
  
     # cd `your-app-dir`
     echo "web: $(basename `pwd`)" > Procfile


を行った結果、エラー文が変わった。どうやら、「Procfile」を「Profile」としていたスペルミスのようだった:sweat_smile:。
Procfile変更後のエラー文が以下である。

    2020-12-22T12:38:17.494371+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=あな 
    たのアプリケーション名.herokuapp.com ...
    2020-12-22T12:38:18.016959+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=あ 
    なたのアプリケーション名.herokuapp.com ...
    2020-12-22T12:38:18.602766+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET 
    path="/favicon.ico" host=あなたのアプリケーション名.herokuapp.com ...

Code=H10,status=503となっているため、再び方法１，２等を試してみたが失敗。
試行錯誤すること数時間...main.pyを眺めていた時、原因が判明。

原因は環境変数でのスペルミスだった:joy:。
「SECRET」→「SELECT」

#### 誤りのコード：

    $ heroku config:set YOUR_CHANNEL_SELECT="Channel Secretの文字列" --app 自分のアプリケーション名

#### 正しいコード：

    $ heroku config:set YOUR_CHANNEL_SECRET="Channel Secretの文字列" --app 自分のアプリケーション名

環境変数が間違っていたことが判明したので、main.pyのコードの該当箇所を「SECRET」に訂正し、
Heroku.comから、
アプリケーション→Settings→Config Varsにて環境変数を手動で設定しなおすことで解決した。

![スクリーンショット (322).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682477/9f5f3a98-5e25-6910-7b81-10f90fa35dc3.png)

無事、ブラウザ上で「Hello　World」が表示された。

# 参考文献
https://qiita.com/shimajiri/items/cf7ccf69d184fdb2fb26
https://qiita.com/yagi_eng/items/9308b680e6ee41ab1d6d
【Android】WiFi経由で実機デバッグするには

Android端末にWiFi経由で実機デバッグする方法です。

#前提条件
* Android端末とPCが同じアクセスポイントに接続されている。
* 有線で接続されている。

#adbコマンドでリモート接続する方法
step1: まずは、端末をtcpモードに切り替えます（※ポート番号は自由に設定できる）

```
adb tcpip 5555
```
step2: 端末のIPアドレスを確認します

``` 
adb shell ip addr show wlan0
```
step3: 確認したIPアドレスに対して、接続します（※5555は省略可能）

```
adb connect xxx.xx.xx.xx:5555
```

#最後に
AndroidStudioで確認すると、無線で実機デバッグすることができます。
また、机上から有線ケーブルを減らせるので快適です。
端末を再起動するとIPアドレスが変わってしまうので、固定IPに設定することをお勧めします。
【設定方法】
https://www.buffalo.jp/support/faq/detail/15994.html
既存ネットワークに後から作成したコンテナを接続する方法

## したいこと

* 1つの`docker-compose.yml`に複数コンテナの記述をするのではなく、既存ネットワークに後から作成したコンテナを接続したい。

## 参考

* [network コマンドを使う — Docker-docs-ja 17.06 ドキュメント](http://docs.docker.jp/v17.06/engine/userguide/networking/work-with-networks.html)

## 作成

```sh:net1というネットワークを作成
docker create network net1
```

## 接続

```yaml:docker-compose.yml
version: "3"
services:

  potmum:
    image: tukiyo3/potmum:20170807
    restart: always
    volumes:
     - /etc/localtime:/etc/localtime
     - ./db/production.sqlite3:/srv/potmum/db/production.sqlite3
     - ./attachment_files/:/srv/potmum/public/attachment_files/
    environment:
      PRIVATE_MODE: 0
      USE_ATTACHMENT_FILE: 1
      COLOR_THEME: "green"
      #
      USE_GITHUB: 0
      USE_DEVELOPER: 1

networks:
  default:
    external:
      name: net1
```

```yaml:docker-compose.yml
version: "3"
services:

  nginx:
    image: nginx:alpine
    restart: always
    volumes:
      - ./nginx/htpasswd:/etc/nginx/htpasswd
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    ports:
      - 80:80

networks:
  default:
    external:
      name: net1
```
Autifyを導入しました

#Autifyを導入しました

弊社はE2Eテストを一部導入しておりましたが、この度Autifyに切り替えていくことになりました。
ここでは(Webフロントの)E2Eテストツールの簡単な変遷とAutifyの利点について話していきます。

## E2Eテストツールについて

まず脚光を浴びたのはSeleniumかと思います。WebDriverを介してブラウザを操作するわけですが、テストコードのコーディングや日々HTMLも変わっていくので、メンテナンスコストも常にかかってしまいます。またSPAに強くない点も近年ではデメリットで挙げられていました。
Seleniumを扱うこと自体にスキルを求められるのがとくに小さな開発組織では難しいところでした。
弊社では一部Pupeteerを使っておりましたが、上記の課題を解決できていませんでした。

## Autifyについて
サーバー構築不要なAufifyのサーバー上で全てが完結するQA自動化プラットフォームになっており、AIによりメンテナンスもある程度不要となっているサービスです。

2020年12月現在ですと料金のスタートは5万円からとなっています。
https://autify.com/ja/pricing

有料サービスということもあり、サポートもあります。弊社でも始まる際に色々と相談に乗っていくださり柔軟に対応していただき助かりました。

### Autifyは習得が早い。というか学習コストほぼいらない
ブラウザを操作していけば自動的に記録されていくので、非エンジニアの人でも簡単なものならすぐに構築可能です。
JavaScriptも組めるので、フォーム入力でランダム性が必要なところはJavaScriptで数値を出して取得しています。

### Microプランだと月の実行回数が200回(2020年12月現在)
E2Eテストの回数は各社の方針やサービスにとってまちまちだと思いますが、柔軟にいろいろなケースで利用していくことを考えると弊社では厳しい数値です。
プランアップや利用を制限するといったことが考えていかなければいけないところです。

### まとめ
環境構築不要、メンテナンスも限りなく0に近づける、シナリオを作成するにも特別なスキルがほぼいらないなど、極力シンプルにできるのがメリットかと思います。
有料のサービスになりますが、E２Eテストに関わる工数等を考えれば逆に安くなるはずです。
これからE2Eテストツールを考えている人にとっては有力な選択肢だと思います。
装着したまま食事ができるスマートフェイスシールド

#1.できること
###箸を口元に持って行く動作を検知して、自動でフェイスシールドの口部分が開きます。
###食べ物を口に入れる瞬間だけフェイスシールドが開くので、コロナ対策に発展させられるかもしれません。
###今回は基本的な仕組みをプロトアウトしただけなので、コロナ対策の効果そのものは評価していません。あくまでも、ITネタとして見て下さいね。


#2.仕組み
####手に装着したmicro:bitの加速度センサーで食事の動作を検知して、フェイスシールドのmicro:bitに無線でシールドの開閉(サーボモータ回転)を指令します。

#3.こんな感じで動きます ～祝微バズ～
###考え抜いたものより思い付き5分の方が受けがちなのは何の法則？

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/microbit?src=hash&amp;ref_src=twsrc%5Etfw">#microbit</a> 箸を口元にもっていくと、フェイスシールドが自動で開くやつ。これで会食も少しは安心(かも)。ビジュア的にヤバイので視聴注意。 <a href="https://t.co/IS0csIz2Gx">pic.twitter.com/IS0csIz2Gx</a></p>&mdash; Google Homer (@google_homer_) <a href="https://twitter.com/google_homer_/status/1340847469517701120?ref_src=twsrc%5Etfw">December 21, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#4.フェイスシールド部分の加工方法
①口の周り(赤線)をハサミで切り取り、サーボのツバ部分(青丸)とフェイスシールドをネジ止めします。
②切り取った部分をサーボホーンに両面テープで貼り付けます。サーボのカモフラージュとして、お好みで赤っ鼻をトッピングします。
③ヘッドバンドあたりに、いい感じにmicro:bitを両面テープで貼り付けます。
④裏側に電池BOXを両面テープで貼り付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234533/e2810908-da8c-ef5b-f76f-c265d7632d8e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234533/e19c2670-b8c3-11ce-0871-a2c2b74a9e5a.png)

#5.手の部分のmicro:bitの装着方法
手の甲にmicro:bitを貼り付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234533/f351a989-81d7-d166-7638-78d1b1e820da.png)

#6.micro:bitプログラム
###■手の部分のmicro:bitのプログラム
上記の写真のように手に装着したmicro:bitの加速度センサーのX軸の値が800より大きくなったことをもって、箸を口のそばに持って行ったと判断しています。判断結果を、無線でフェイスシールドのmicro:bitに送っています。***検知はかなり微妙なので、物を口に運ぶ動作に呼応する軸や値を根気よく探して実装して下さい。***
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234533/739f47d9-cabe-1ad0-b9f8-32e3985942b6.png)
###■フェイスシールド側のmicro:bitのプログラム
無線で通知された内容に従ってサーボを回しているだけです。
***角度はサーボホーンの取り付け位置に応じて調整して下さい。***
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234533/2255141e-1754-c737-8f05-e45978bf683b.png)

#7.まとめ
###結構レスポンスよく動作してくれたので、食事動作と開閉の同期は行けるかもと感じました。ただ、衆人環視の学食などで試す勇気がなく、まだ実食試験できてません。それから、たぶんお茶を飲む動作とかには対応できないはずです。
###今回はネタレベルの投稿になってしまいましたが、皆様の様々なアイディアで化けるやもしれません。自由にパクってもらって大丈夫なので、進化させてもらえたら嬉しいです。
githubのssh認証と2段階認証

githubからコマンドラインでcommit&pushしていたら
Deprecation Mailが通知された。

メールのリンク先
[Token authentication requirements for Git operations](https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/)
要は、githubはtokenベースの認証に移行するようで
BASIC認証ベースのアクセスは非推奨になる模様。

ログイン認証も2要素認証を推奨
コマンドラインでpush&commitしたいのならはSSH認証
とのこと。

## SSH認証
SSH認証だとログインユーザー毎でSSHキーを発行しないと
ユーザーが識別できないのでメンドイ。

### push&commitする環境
sshの公開鍵を生成

```bash
$ mkdir ~/.ssh
$ cd ./ssh
$ ssh-keygen -t rsa -C <emailアドレス>
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
$ ls
id_rsa  id_rsa.pub
```

`id_rsa.pub`の中身をクリップボードなどにコピーする

### github側の設定
1. ログインしたら右上のアイコンよりDropdownメニューから「Settings」を選択
2. 左のサイドメニューより「SSH and GPG Keys」を選択
3. SSH Keysの左の「New SSH Key」ボタンを選択
4. Title欄は端末名など、Key欄にid_ras.pubのコピーした内容をペーストし、Add SSH Keyボタンをクリック 

### gitの設定
プロジェクト内の`.git/config`を開いて編集

```bash
[remote "origin"]
url = <レポジトリまでのパス> #例:git@github.com:aaaa/bbb.git
```

## 2段階認証
スマホアプリにて認証を行うとのことだが
QRコードを読み取るのにどのアプリかわからず、
googleレンズなどでで反応しなかったが
「Google認証システム」というアプリでQRコード認識した。
FreeBSDで聞くWWOZ

ニューオリンズのご機嫌なFMステーション[WWOZ](https://www.wwoz.org/)をFreeBSDで聞いてみます。

[FreeBSDをインストールしたVALUESTAR](https://qiita.com/yamori813/items/2cdc2f8164e3973eb240)を使います。このマシンには内蔵のサウンドインターフェースがありますが、こんな使っていないUSBスピーカー(ELECOM MS-P05UWH)があったんで、つないでみます。

![ms-p05u_wh.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/5c305620-4ab4-5d6e-8074-745e8df6a87a.jpeg)

USBのオーディオクラスのデバイスになり、必要なカーネルモジュールがロードされます。

```
uaudio0 on uhub0
uaudio0: <vendor 0x0c76 USB Speaker, class 0/0, rev 1.10/1.00, addr 4> on usbus0
uaudio0: Play[0]: 48000 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
uaudio0: No recording.
uaudio0: No MIDI sequencer.
pcm1: <USB audio> on uaudio0
uaudio0: HID volume keys found.
```

[Solid State System](http://www.3system.com.tw/)という会社のチップを使っているようです。接着してあるので分解できず確認できてませんがSSS1603ではないかと思われます。

デフォルトのサウンド出力は内蔵インターフェースになっているので変更します。

% sysctl hw.snd.default_unit=1

[mpg123](https://www.mpg123.de/)をpkgでインストールします。

[WWOZのストリーミング](https://www.wwoz.org/programs/streams)のページでURLを確認して試してみます。

```
 % mpg123 https://wwoz-sc.streamguys1.com/wwoz-hi.mp3
High Performance MPEG 1.0/2.0/2.5 Audio Player for Layers 1, 2 and 3
        version 1.26.3; written and copyright by Michael Hipp and others
        free software (LGPL) without any warranty but with best wishes
[src/libmpg123/readers.c:1204] error: Cannot open file https://wwoz-sc.streamguys1.com/wwoz-hi.mp3: No such file or directory
main: [src/mpg123.c:738] error: Cannot open https://wwoz-sc.streamguys1.com/wwoz-hi.mp3: File access error. (code 22)
```

開けません。mpg123はhttpsに対応してないのかもしれません。httpで試してみます。

```
% mpg123 http://wwoz-sc.streamguys1.com/wwoz-hi.mp3
High Performance MPEG 1.0/2.0/2.5 Audio Player for Layers 1, 2 and 3
        version 1.26.3; written and copyright by Michael Hipp and others
        free software (LGPL) without any warranty but with best wishes

Directory: http://wwoz-sc.streamguys1.com/

Terminal control enabled, press 'h' for listing of keys and functions.

Playing MPEG stream 1 of 1: wwoz-hi.mp3 ...
ICY-NAME: WWOZ
ICY-URL: http://www.wwoz.org

MPEG 1.0 L III cbr128 44100 stereo

ICY-META: StreamTitle='';
```

聞けました。

時節柄クリスマスの曲が流れていてとっても良い雰囲気です。

インターネットラジオのサイトは著作権や収益の問題か無くなったりしているケースあり、有料化されているところもあります。また古い情報のページもたくさんありました。そのため参考にならない記事が多く、いろいろ調べました。

このスピーカーはWindowsで試したときはあまり音良くないと思ったのですが、FreeBSDで試したらけっこういい感じで鳴っています。気のせいかな。

スピーカーにはボリュームのup/downとミュートのボタンが付いていて、ちゃんと機能します。up/downは+5/-5するようです。

mp3なんって昔のものと思ってましたが、こうして使ってみると良い気がしてきました。

パブリックな放送をhttpsで流すのは帯域やCPUの無駄遣いになるので、httpでよいと思います。

インターネットラジオはmp3の他にwmaなどの形式もありますが、mpg123で再生できるのはmp3だけです。

mpg123は依存ライブラリなどがなく単体で動作するので、大変手軽です。

以下のサイトで世界中の放送局からmp3のストリームを探して聞くこともできます。

http://fmstream.org/index.php

~~日本のコミュニティーFMでmusicbird系の局はmp3で配信しているようです。~~(2022/04に廃止されたようです)

インターネットラジオをブラウザで聞ける[radio.garden](http://radio.garden/)も便利ですが、ブラウザを閉じてしまうと止まってしまうので、自分はmpg123の方が使い勝手が良いです。

これがおいらのスマートスピーカーだって事でアドベントカレンダーが空いてたので放り込んでみました。
FlutterでSafeAreaじゃないとこの高さを取得して色々使う

```safe_area_util.dart
class SafeAreaUtil {
  factory SafeAreaUtil() => _cache;
  SafeAreaUtil._internal();
  static final SafeAreaUtil _cache = SafeAreaUtil._internal();

  static double unSafeAreaBottomHeight;
  bool get hasUnSafeAreaBottomHeight => unSafeAreaBottomHeight != 0.0;
}
```

シングルトン的な何かを作る。

```app.dart
class App extends StatelessWidget {
  const App();

  @override
  Widget build(BuildContext context) => MaterialApp(
        title: 'title',
        home: Home(),
        builder: _builder,
        ...(themeとか色々),
      );

  Widget _builder(BuildContext context, Widget child) {
    SafeAreaUtil.unSafeAreaBottomHeight = MediaQuery.of(context).padding.bottom;
    return child;
  }
}
```

アプリ起動時に計算して挿入。
（shared preferenceに入れても良さそうだけど、OSのアップデートとかでSafe Areaの仕組み変わるとかあると怖い。）

```simple_footer.dart
class SimpleFooter extends StatelessWidget {
  const SimpleFooter({@required this.child});

  final Widget child;

  @override
  Widget build(BuildContext context) => Container(
        color: Theme.of(context).footerColor,
        height: _height(context),
        child: _column(context),
      );

  double _height(BuildContext context) => simpleFooterHeight(
        hasSafeAreaHeight: _hasSafeArea,
      );

  double simpleFooterHeight({@required bool hasSafeAreaHeight}) =>
    hasSafeAreaHeight ? 83 : 72;

  bool get _hasSafeArea =>
      SafeAreaUtil().hasUnSafeAreaBottomHeight;

  Column _column(BuildContext context) => Column(
        children: <Widget>[
          _divider(context),
          _padding,
          if (_hasSafeArea) const SizedBox(height: 11),
        ],
      );

  Divider _divider(BuildContext context) => Divider(
        height: 0.5,
        color: Theme.of(context).borderColor,
      );

  Padding get _padding => Padding(
        padding:
            const EdgeInsets.only(left: 12, top: 11.5, right: 12, bottom: 12),
        child: child,
      );
}
```

こんな感じで呼び出します。

基本はSafeArea Widgetを使うのが正解だと思いますが、
小回り利かせたい時には参考にして頂けると👍
複数のネットワークをバッチで簡単に切り替える（ipv4/ipv6兼用）

はじめての記事なので、書き方が変でも許してください。

今回はDNSを切り替える際にいちいちコントロールパネルまで行かずともデスクトップから一発で変えられる、そんなバッチファイルをつくっていこうと思います。

と言ってもすでに[やってる方](https://qiita.com/mindwood/items/9c36ff0eb7f126ff6db2)がいましたので、それをIPv6に対応させてパブリックDNSの切り替えを主として書き換えていこうと思います。

[先人](https://qiita.com/mindwood/items/9c36ff0eb7f126ff6db2)のコードと変わっているところは、各切り替え先のDNSアドレス、IPv6要素の追加、文字コードの変更などです。

ちなみに、IPアドレスは自動取得のみ。設定したい場合は該当する行のDHCPというところを適当なアドレスに書き換えます。
DNSサーバーアドレスは自動・Google・Cloudflareの3種類用意してあります。
IPアドレス/DNSサーバーはいくらでも追加できます。

とりあえず、コマンドプロンプトはShift-JISなのでUTF-8に切り替えてあげないと文字化けします。

```bat:
chcp 65001
```
これで切り替えられます。

これを踏まえて、以下が実行ファイルです。

```bat:DNS.bat
@echo off
chcp 65001
echo 1："自動"
echo 2："Google Public DNS"
echo 3："Cloudflare"
echo.
choice /C:123 /M:"どのネットワークに接続しますか"
echo.

set NAME=イーサネット

if %ERRORLEVEL% equ 1 (
  netsh interface ipv4 set address "%NAME%" dhcp
  netsh interface ipv4 set dns "%NAME%" dhcp
  netsh interface ipv6 set dns "%NAME%" dhcp
  echo 自動設定に切り替えました！
) else if %ERRORLEVEL% equ 2 (
  netsh interface ipv4 set address "%NAME%" dhcp
  netsh interface ipv4 set dns "%NAME%" static 8.8.8.8 primary
  netsh interface ipv4 add dns "%NAME%" 8.8.4.4
  netsh interface ipv6 set dns "%NAME%" static 2001:4860:4860::8888 primary
  netsh interface ipv6 add dns "%NAME%" 2001:4860:4860::8844
  echo Google Public DNSに切り替えました！
) else if %ERRORLEVEL% equ 3 (
  netsh interface ipv4 set address "%NAME%" dhcp
  netsh interface ipv4 set dns "%NAME%" static 1.1.1.1 primary
  netsh interface ipv4 add dns "%NAME%" 1.0.0.1
  netsh interface ipv6 set dns "%NAME%" static 2606:4700:4700::1111 primary
  netsh interface ipv6 add dns "%NAME%" 2606:4700:4700::1001
  echo Cloudflareに切り替えました！
)

pause
```
このままでは、管理者権限が付与されていないので、
同じディレクトリにもう一つ起動用のバッチファイルをつくり、

```bat:DNS-Change.bat
powershell start-process DNS.bat -verb runas
```
としてあげます。
こちらを起動することで、管理者として起動をいちいち選ばなくてよくなります。

似たファイルが2つあってややこしいという方は、DNS.batの方のショートカットを作成して、そちらの起動権限を管理者にしてあげましょう。

ということで、以上DNSを切り替えるだけのバッチファイルでした！
オブジェクトストレージ Cloudian/S3 にあるJSON形式のデータから特定のデータを抽出してみます


## はじめに
AWS SDK for Python(boto3) を使って、プログラムをほぼ変更せずに Cloudian と S3 へのアクセスが可能となります。オブジェクトストレージをハイブリッド（オンプレミス：Cloudian、AWS：S3）で使いたい方への参考になればと、、、

## 概要
オブジェクトストレージ Cloudian/S3 上のバケット名「boto3-cloudian」にあるJSON形式のデータファイルから特定のデータを抽出する Python プログラムです。

JSON形式のデータファイルは、[これ](https://qiita.com/turupon/items/e16789a959fc92068c68) で生成した「test-iot-dummy.json」となり、10万件のデータが存在しています。そのデータから、項目「section」=「R」のものを抽出し、そのデータ件数と抽出に掛かった時間を表示します。

抽出項目「section」はパラメータとして定義することも可能です（アルファベット大文字１文字）。プログラム実行時に、パラメータ「-h」を指定することにより表示されるヘルプも参照ください。

## 実行環境
macOS Big Sur 11.1 
python 3.8.3

## クレデンシャル情報の定義
今回はクレデンシャル情報を .zshenv に定義してプログラムを実行しています。接続先に合わせて定義ください。

```
# AWS S3
export AWS_ACCESS_KEY_ID=xxxxxxxxxxxxx
export AWS_SECRET_ACCESS_KEY=yyyyyyyyyyyyyyyyy
export AWS_DEFAULT_REGION=ap-northeast-1

# Cloudian
#export AWS_ACCESS_KEY_ID=aaaaaaaaaaaaaaaaaa
#export AWS_SECRET_ACCESS_KEY=bbbbbbbbbbbbbbbbbbbb
#export AWS_DEFAULT_REGION=pic
```

## 実行プログラム
Cloudianへアクセスする場合は endpoint_url を記載ください（プログラム内を参照ください）。

```python:IoTSample-read.py

import json
import time
import argparse
import boto3

BUCKET_NAME = 'boto3-cloudian'
OBJECT_KEY = 'test-iot-dummy.json'


# S3-APIで全データ取得してロジックでフィルタ(項目：Section)
def section_main(section):

    # client = boto3.client('s3', endpoint_url='http://s3-pic.networld.local')    # Cloudianへのアクセス時
    client = boto3.client('s3')                                                 # S3へのアクセス時
    response = client.get_object(
        Bucket=BUCKET_NAME,
        Key=OBJECT_KEY
    )

    target = []
    if 'Body' in response:
        body = response['Body'].read()
        text = body.decode('utf-8')
        items = json.loads(text)
        items = items['items']
        target = list(filter(lambda x: x['section'] == section, items))
    # print(target)
    return len(target)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='IoT機器のなんちゃってダミーデータの抽出')
    parser.add_argument('--section', type=str, default='R', help='抽出するセクションの指定（アルファベット大文字１文字）')
    args = parser.parse_args()

    start = time.time()
    
    num = section_main(args.section)

    select_time = time.time() - start

    print("")
    print(f"データ抽出件数:{num}")
    print("抽出処理時間(通常_API):{0}".format(select_time) + " [sec]")
    print("")

```


## プログラムの実行
 
最初にヘルプを表示してみます。

```
$ python IoTSample-read.py -h             
usage: IoTSample-read.py [-h] [--section SECTION]

IoT機器のなんちゃってダミーデータの抽出

optional arguments:
  -h, --help         show this help message and exit
  --section SECTION  抽出するセクションの指定（アルファベット大文字一文字）
```


では、デフォルトの抽出項目でデータ抽出を実行してみます。

```
$ python IoTSample-read.py

データ抽出件数:3929
抽出処理時間(通常_API):3.6708199977874756 [sec]
```


次に、抽出項目を指定した場合の実行です。

```
$ python IoTSample-read.py --section Z

データ抽出件数:3792
抽出処理時間(通常_API):3.5160200595855713 [sec]
```

## まとめ

今回は、AWS SDK for Python(boto3) を使って、オブジェクトストレージ Cloudian / S3 からデータを抽出することを確認できました（10万件のデータから数秒で目的のデータを抽出完了（もちろん環境に依存します））。

Cloudianについては、[ここ](https://qiita.com/yamahiro/items/7b8a11c773106b641795) を確認ください。
dockerでmysqlが立ち上がらなくなった。

# 問題点

dockerで開発しようと、docker compose up -dしようとしたら、こんなのが出た。

```
failed to solve: rpc error: code = Unknown desc = failed to solve with frontend dockerfile.v0: failed to create LLB definition: failed to authorize: failed to fetch anonymous token: Get https://auth.docker.io/token?scope=repository%3Alibrary%2Fmysql%3Apull&service=registry.docker.io: net/http: TLS handshake timeout
```

## 解決方法

こちらで直りました。

```
docker-compose build --no-cache
docker compose up -d
```
【Rails】'simple_calendar'を用いて予定表を作成

#はじめに
お店のサイトで、イベントをカレンダーを用いて一覧表示にしました。
当初はfullcalendarを使用する予定でしたが、スクールで成果物の提出期限もあり学習コストがあまりかからない方法を考えた末simlpe_calendarを使用することに至りました。
数ヶ月後の自分の為にも、勇気を出してQiitaの初投稿とさせていただきます。
#完成イメージ
![スクリーンショット 2020-12-23 9.37.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/973512/a994df8a-11df-17c0-0413-9cf2700e9892.png)

#前提
・予定投稿機能実装済(記事内ではScheduleモデル)
・言語はi18nによって日本語化済。本来であれば、曜日、月は英語表記になっていると思います。(エラーメッセージを日本語化したかっただけなのですが、意図せずこちらも変わっていました)

#simple_calendarインストール

```ruby:Gemfile
gem "simple_calendar", "~> 2.0"
```
```
$ bundle install
```

#カレンダーのview作成
前提に書かせていただいているScheduleモデルのマイグレーションファイルはこちらです。
t.string :content は予定のタイトル、詳細画面で予定の詳細を表示したかったので t.text :plan で予定の詳しい文章を入れています。
開始日時のデータも欲しいので t.datetime :start_time が必要です。

```ruby:db/migrate/..._create_schedules.rb
class CreateSchedules < ActiveRecord::Migration[5.2]
  def change
    create_table :schedules do |t|
      t.string :content
      t.text :plan
      t.datetime :start_time

      t.timestamps
    end
  end
end

```

カレンダーの見た目を整える為、下記を実行しviewファイルを作成します。

```
$ rails g simple_calendar:views
```

```erb:app/views/schedules/index.html.erb
<h1>Schedule</h1>
<%= month_calendar events: @schedules do |date, schedules| %>
　<%= date.day %>
　　<% schedules.each do |schedule| %><br />
　　　<%= schedule.start_time.strftime('%H:%M') %>　#スケジュールの開始時間を表示
　　　<%= link_to schedule.content,schedule_path(schedule) %>
　　<% end %>
<% end %>
```

スケジュールのタイトルからスケジュール詳細にリンクする仕様です。

simple_calendarのCSSを適用させるために、application.scssに追記します。

```ruby:app/assets/stylesheets/application.scss
 *
 *= require simple_calendar #←ここに追記します
 *= require_tree .
 *= require_self
 */
```

月、曜日を日本語化にしているので不自然だった為少し修正を加えました。

```erb:app/views/simple_calender/_month_calendar.html.erb
 <div class="simple-calendar">
  <div class="calendar-heading">
    <%= link_to t('simple_calendar.previous', default: '<<先月'),  calendar.url_for_previous_view %>　#Previousを先月に変更
    <font size="5"><span class="calendar-title"><%= start_date.year %> <%= t('date.month_names')[start_date.month] %></span></font>
    <%= link_to t('simple_calendar.next', default: '次月>>'), calendar.url_for_next_view %>　#Nextを次月に変更
  </div>

  <table class="table table-striped">
    <thead>
      <tr>
        <% date_range.slice(0, 7).each do |day| %>
          <th><%= t('date.abbr_day_names')[day.wday] %></th>
        <% end %>
      </tr>
    </thead>
・
・
・
```

以上でsimple_calendarの導入が完了しました！

#参考
https://qiita.com/isaatsu0131/items/ad1d0a6130fe4fd339d0
https://github.com/excid3/simple_calendar

参考にさせていただきました。ありがとうございます。

#最後に
ここまでご覧くださった方、ありがとうございます。
初の投稿となりましたが、おかしな表現などあれば失礼致しました！
ではまた投稿させて頂きます！
モデルをオプショナル型で宣言する

## はじめに
MVCアーキテクチャについて勉強していたらインスタンス変数をオプショナル型で定義しているコードがありました。その理由と挙動について書きます。コメント歓迎してます。
## モデルクラスの用意

```swift
class Model {
    func model() {
        print("model")
    }
}
```
`model`というメソッドを定義しています。想定としては、コントローラークラスから参照され、用いられます。

## コントローラークラスの用意

インスタンス変数`model`を`Model?`型で定義しています。
`methodOfModel`は`Model`クラスの`model`メソッドを行うメソッドです。

```swift
class Controller {
    var model: Model? {
        didSet {
            print("変更された")
        }
    }
    func methodOfModel() {
        model?.model()
    }
}
```

## 挙動

```swift
let controller = Controller()
print("modelは\(controller.model)")//modelはnil
controller.methodOfModel()//この時点では実行されない
controller.model = Model() //変更された
print("modelは\(controller.model)")//modelはOptional(Page_Contents.Model)
controller.methodOfModel()//model
```

1行目では`Controller`をインスタンス化しています。
2行目では`controller.model`がnilであることを確認しています。
3行目では`controller.method`が実行されないことを確認しています。
4行目では`controller.model`に`Model()`を入れています。ここで`model`は値が変更されたので`didSet`が実行されます。
5行目では2行目と同じことが書かれています。が、`model`がnilでないことが確認できます。
6行目も3行目と同じことが書かれています。が、`Model`クラスの`model`が実行されます。

##なぜモデルをオプショナル型で宣言するのか
ここからは書いている人の予想という色が強いことをはじめに宣言しておきます。

```swift
let model = Model()
```
としてしまうとクラスとクラスの結合が強くなってしまいます。クラス同士を疎結合にするために、外からインスタンス化を行わせているというのが狙いの一つではないでしょうか。
bashのtestコマンドの整理

# 概要
Bashで条件文を書く時に以下のように括弧を使うけど、きちんと仕組みを整理しておく。

```bash
if [ -f ${FILENAME} ];  then
  ...
fi
```

# testコマンド
括弧は実はtestコマンドの省略形。以下の記述と上記は同じもの。
testコマンドは条件が真なら0、偽なら1を返すのでコマンドの戻り値をifで判定している。

```bash
if test -f ${FILENAME}; then
  ...
fi
```

## ファイル系
| 式 | 説明 |
|:-:|:-:|
| -e ファイル名 | ファイルが存在するか  |
| -f ファイル名 | ファイルが通常のファイルか  |
| -d ファイル名 | ファイルがディレクトリか  |
| -s ファイル名 | ファイルサイズがゼロでないか  |
| -x ファイル名 | ファイルが実行可能か |

## 条件系

| 式 | 説明 |
|:-:|:-:|
| 文字列1 = 文字列2 | 文字列1と文字列2が等しい場合  |
| 文字列1 != 文字列2 | 文字列1と文字列2が等しくない場合  |
| -z 文字列1 | 文字列1のサイズがゼロの場合 |
| -n 文字列1 | 文字列1のサイズがゼロでない場合。-nを省略しても同じ。|
| 数値1 -eq 数値2 | 数値1と数値2が等しい場合 |
| 数値1 -ne 数値2 | 数値1と数値2が等しくない場合 |
| 数値1 -gt 数値2 | 数値1と数値2より大きい場合 |
| 数値1 -ge 数値2 | 数値1と数値2以上の場合 |
| 数値1 -lt 数値2 | 数値1と数値2未満の場合 |
| 数値1 -le 数値2 | 数値1と数値2以下の場合 |

## 条件式系

| 式 | 説明 |
|:-:|:-:|
| 条件式1 -a 条件式2 | 条件式1と条件式2のAND条件  |
| 条件式1 -o 条件式2 | 条件式1と条件式2のOR条件  |

```bash
if [ $A -eq 1 -a $B -eq 0 ]; then
  ...
fi
```
これと以下は同値。以下はそれぞれのtestコマンドを&&でつないで判定させている。

```bash
if [ $A -eq 1 ] && [ $B -eq 0 ]; then
  ...
fi
```

# Bash拡張２重括弧
Bash拡張で２重括弧をつかうと、条件のグループ化や&&などを使うようにできる。

| 式 | 説明 |
|:-:|:-:|
| (条件式) | 条件式のグループ化  |
| 条件式1 && 条件式2 | 条件式1と条件式2のAND条件。-aは使えない。 |
| 条件式1 || 条件式2 | 条件式1と条件式2のOR条件。-oは使えない。 |
| !条件式1 | 条件式1の否定条件。 |
| 文字列1 == 文字列2 | 文字列1と文字列2が等しい場合 |
| 文字列1 = 文字列2 | ==と同じ |
| 文字列1 != 文字列2 | 文字列1と文字列2が等しくない場合 |
| 文字列1 =~ 文字列パターン | 拡張正規表現によるマッチ |

Bash拡張の2重括弧を使うと以下のようにもかける

```bash
if [[ ( $A -eq 1 ) && ( $B -eq 0 ) ]]; then
  ...
fi
```


# コマンドの存在チェックによる条件判定
testコマンドを使う場合は以下のような感じで判定できます。

```bash
which bash > /dev/null 2>&1
RES=$?
if [ $? -eq 0 ]; then
  echo "bash found"
else
  echo "bash not found"
fi
```

testコマンドを使わず直接witchコマンドの結果を見て判定することもできます。

```bash
if which bash > /dev/null 2>&1; then
  echo "bash found"
else
  echo "bash not found"
fi
```
【Python, Excel】 セル結合を駆逐する

# 嘆き
**なぜ、この世には「セル結合」なるものが存在するのでしょうか...**
見た目がいいから？同じ数値をまとめられるから？印刷のときにずれるから？

**別ファイルで作って下さい！データ処理を目的としたファイルでそんなことされても困ります！**
総務省だって「**e-Statに掲載する統計表にはセル結合しないこと**」って言ってます！

（ソース）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269013/216ca55f-6c0b-0f5a-c550-54deeebccec0.png)
（統計表における機械判読可能なデータ作成に関する表記方法：https://www.soumu.go.jp/main_content/000723626.pdf）

「前処理やるぞー」と思った矢先にセル結合の嵐だともうやる気が90%減です。
空行や空白列は後で削除すればいいですが一個一個結合されたセルを探して解除するのはしんどい。
そこでpythonでセル結合を駆逐する関数を実装しました。
~~本当は無用なセル結合した人間を地の果てまで追跡するプログラムを書きたい~~

```{unmerge.py}
import openpyxl
import sys

class excel_operate:
   def __init__(self, excel_dir):
      self.excel_dir = excel_dir
      self.workbook = openpyxl.load_workbook(self.excel_dir)
      self.sheet_number = len(self.workbook.get_sheet_names())
      self.sheet_contains =  [self.workbook.worksheets[i] for i in range(self.sheet_number)]
      self.merged_cells_list = [self.sheet_contains[i].merged_cells.ranges for i in range(self.sheet_number)]

   def get_merged_cells_location(self):
      self.merged_cells_location_list = [""]*self.sheet_number
      for i in range(self.sheet_number):
         self.merged_cells_location_list[i] = [format(self.merged_cells_list[i][j]) for j in range(len(self.merged_cells_list[i]))]
      else:
         print("The merged cells location was got!")

   def break_merged_cells(self):
      for i in range(self.sheet_number):
         for j in range(len(self.merged_cells_list[i])):
            self.sheet_contains[i].unmerge_cells(self.merged_cells_location_list[i][j])
         else:
            pass
      else:
         print('The all merged cells were unmerged!')

Excel = excel_operate(r"セル結合を駆逐したいExcelのpath")
Excel.get_merged_cells_location()
Excel.break_merged_cells()
Excel.workbook.save("名前.xlsx")

```
本当にお願いですからデータ集計を目的としたExcelファイルでセル結合はやめて下さい...
matplotlibの2dhistgramに第二軸を入れる

## 例：y軸に第二軸を追加


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221968/b3841664-1a8e-10db-2808-5e986419a933.png)

上図のy軸の第二軸に、A,B,Cが追加されている。

以下では、(x,y)にランダムな配列を入れて、2dhistogramを描画する。

```python
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm

N_numbers = 100000
N_bins = 100

np.random.seed(0)
x, y = np.random.multivariate_normal(
        mean=[400.0, 1000.0], 
        cov=[[1000,500],
             [400,700]],  
        size=N_numbers
        ).T          


fig, ax = plt.subplots(figsize =(6, 6))
H=ax.hist2d(x, y, bins=N_bins, cmap='nipy_spectral',norm=LogNorm())
plt.xlim([0,1100])
plt.ylim([0,2100])

cb = fig.colorbar(H[3],ax=ax)
cb.set_label('Number')

plt.title('The title')
plt.xlabel('x axis')
plt.ylabel('y axis')

ax2 = ax.twinx()
ax2.set_ylim(0,2100)
plt.yticks([1100,1200,1500], ["A","B","C"])

plt.show()
```

第二軸の追加は、後ろから4行目を追加するだけ。
`ax.twinx()`として、`ax2`のx軸を`ax`と共通化させる。
Swiper.js(Ver6系)でタブの横スクロールを実現する

### デモ

https://codepen.io/qwe001/pen/JjRrWqm

なんか知らないうちにSwiperのバージョンめっちゃ上がりましたね…
私の知っている時はVer3ぐらいだったと思いますが、いつの間にかVer6に…
WEBの進化はやすぎわろた。

オプション名とか引数の並び順とかも結構変わってたので、
改めて実装しました。

### ミソ

```javascript
  var tabSwiper = new Swiper('.tabs-box', tabSwiperOptions);
  var boardSwiper = new Swiper('.board-box', boardSwiperOptions);

  tabSwiper.slides.each(function(event, index){
    $(this).on("click", function(){
      $(".tabs .tab").removeClass("selected"); // init
      $(this).addClass("selected");

      boardSwiper.slideTo(index, 500, false);
    });
  });
```

タブ要素はページネーションを使うのではなく、スライダーとして生成します。
コンテンツも同じくスライダーとして生成します。

この時、これら二つのスライダー要素の数は同じである必要があります。

任意のタブ要素(スライダー)をクリックすると、
タブ要素(スライダー)のインデックス番号が取得できます。

このインデックス番号を利用して、
タブ要素のクリック時に、コンテンツも同じインデックス番号のスライダーに移動させることで、
タブ移動が実現します。

また、ボード側のスワイプで移動しないように `noSwiping:true` を設定しています。
動かしたくないスライダーに `swiper-no-swiping` クラスをつけることで、動かないようにできます

```html
<div class="swiper-container board-box">
  <div class="swiper-wrapper boards swiper-no-swiping">
    <div class="swiper-slide board">内容 1</div>
    <div class="swiper-slide board">内容 2</div>
    ...
  </div>
</div>
```

ボード側のスワイプでも動くようにしたければ、以下のページの実装を参考にしてください(別作者)

https://codepen.io/pangmr/pen/OXvaEk

### 実装上の注意

CSSで、内容部分の背景色に白色を明示的に設定していますが、
これは消さないでください。
背景色がないと、透過扱いになるのか、
タブを変更した際に後ろにあるコンテンツと被ります

```css
.boards .board {
  background: #FFF;
  text-align: center;
}
```

### 依存するライブラリ

* jQuery
* Swiper.js
* Swiper.css

### 参考サイト

* https://codepen.io/marcelo-ribeiro/pen/XKwOWr
* https://codepen.io/pangmr/pen/OXvaEk
このアイコン何？

皆さんは、このマークをご存じでしょうか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267148/32de4a7a-17e5-ba4e-692d-0360d01ca0e7.png)

こちらにも。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267148/fe3805dd-5afa-4086-5918-4f4826b8fa7d.png)

はい、保存のアイコンですね。

では、何故保存のアイコンはこれなのでしょうか？


これは、「フロッピーディスク」というものです。

ちなみに、実物はコレ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267148/5aa653d1-0788-0d08-be04-af45bacb8a62.png)


その昔、保存と言えば、フロッピーでした。

容量は1.44MBで略称はFD。

そんな小さい容量で、何を保存するの？と思うかもしれませんが、文書を保存するには十分でした。

昔はパソコンの周辺機器を買うと、ドライバが入ったフロッピーが同梱されておりましたし、

OSのインストールには数枚のフロッピーディスクを順番に入れ替えながら設定が必要でした。

まさに、フロッピー全盛期でしたね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267148/e2e14fb8-fd8d-6a12-ee21-496c7369ae36.png)


ソフトウェアもフロッピーで提供されていた時代もあるので、フロッピーディスクドライブが2基搭載されていて、片方をアプリケーション用、もう一方を保存用を入れるなんてこともありました。

当時パソコンを買うと、フロッピーはAドライブ、Bドライブで、Cドライブがハードディスクでした。その名残で、未だにCドライブにハードディスクが割当たっているパソコンが多いと思います。


CD-R等の光ディスクの普及とともに、徐々にその姿を消していきます。

フロッピーがあまり使われなくなって久しいですが、未だに保存のアイコンと言えばフロッピー。

光ディスクも衰退し、オンラインでファイルを管理する時代になっても、その姿を保存のアイコンとして目にすることができます。

今まで知らなかった保存アイコンのストーリーを知ることで、ちょっぴりフロッピーのことを気にしてみてほしいと思います。

ありがとう、フロッピー。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267148/89031640-9d84-f84e-2338-ce7bbc66a1f9.png)
Make sure you configure your ‘user.name’ and ‘user.email’ in git.が出てcommitが出来ない

###困ったこと
VScodeを使用してcommitをしようとした時にこのような文章が出てきて、commit ができなかった。

###解決方法
Gitの「ユーザーネーム」と「メールアドレス」をそれぞれ設定する。

```
git config --global user.name "ユーザー名" 
git config --global user.email "メールアドレス"
```
コマンドを実行すると無事commitできるようになりました。
データの仮想化とは

# データの仮想化とは

- 既存のデータベースに格納されているデータの仮想ビューを作成する。
- データを物理的に移動せず、新たな仮想データレイヤーで複数ソースからのデータを統合ビューとして表現する。  
→この手法はしばしば「データフェデレーション」（または「仮想データベース」）と呼ばれる。  
→基となる複数のデータベースがフェデレーションの対象（「フェデレート」と呼ばれる）
- データの仮想化では、基となっているデータベースに対してクエリが実行される。  
→新しいデータの仮想化技術の多くでは、データの読み取りだけでなく書き込みもできる。
- データの仮想化は、主にデータ分析用途で利用される。

# メリット
- データを物理的に移動しないため、データへのクエリ前にやらなくてはならない作業やコストが少なく、既存のインフラへの影響も抑えることができる。
- 非構造化データソースと構造化データソースの両方に対してアドホックな（特定の目的の）SQLクエリを実行できる。  
→データの仮想化ではこれが主なユースケース

# デメリット
- 仮想データベースではデータがインデックス付けされず、インデックス格納用の独立したデータストレージもない。  
→基となるソースシステムで付けられたインデックスに依存する。
- 仮想データベースでは、すべてのリクエストを、個々のソースシステム用の別のリクエストにマッピングしてから、すべてのソースシステムに対して実行する。  
→ネットワーク全体でパフォーマンスの問題が発生する可能性があり、システムは常にネットワーク容量の問題に悩まされる。
- データのリネージや履歴をトラッキングできる場所がない。  
→「single source of truth」（信頼できる唯一の情報源）は得られない。
- 一般に、仮想データベースではセキュリティ制御に制約がある（少なくとも実装が複雑）。  
→例えば、仮想データベースでは、レコード単位ではなくテーブル単位でのみデータを保護できる。
- 仮想データベースの容量は、常に基となるソースシステムのデータ量に制限される。

## 参考
https://jp.marklogic.com/product/comparisons/data-hub-vs-data-lake/
Rails：find,find_by,whereについて簡単にまとめた

# 最初に

**カレンダー企画2020の23日目**
プログラミングの勉強を始めて3ヵ月程経ったので学んだことのメモをアウトプットとして記事に残します。
これからプログラミングの世界に入る人の手助けになれたら嬉しい限りです。
間違っていたり、言葉が違っていたり、誤解されるような言葉があったら教えてください^^
言葉を長々と読みづらかったら申し訳ありません。少しずつなれてがんばります。

## find,find_by,whereについて

個人的に訳わからず調べて自分なりに解釈した内容です。
他にも細かく載っている記事はたくさんあると思うのでここでは大枠、捉え方ぐらいに思って貰えればいいかと^^;（詳しく書いてもどっかの受け売りでコピペになるのでね^^;）

find,find_by,whereこれらはDB（データベース）から必要な情報だけを取り出す為に必要な理解です。
WEBアプリケーションを作成するなら絶対どれかは使う。


## これだけ覚える

（検索というのは私なりの解釈です。ご了承ください）

|メソッド|検索範囲|取得するデータ|
|:-:|:-:|:-:|
| find    | id | 1つ
| find_by | 指定したカラム | 最初の1つ
| where   | 指定したカラム | すべて




## find

これだけ覚える
↓
**id（主キー）を指定して、見つけた1レコードを取得する。**


見つけられないと`ActiveRecord::RecordNotFound`というエラーが出る。


```ruby
# インスタンス変数 = モデル名.find（主キー）

@post = Post.find(params[:id])

```

こんな感じで記述をします。

idに部分が1や2や3,,,nが入ってそれに関連しているものを取得してくる。
1だったら=> post.find(1)となってpostのid:1のデータを取得する。


## find_by

これだけ覚える
↓
**findの役割に+αでid以外のカラムも指定できる**

findは指定できる（検索できる）カラムがid限定でした。
find_byは指定できる（検索できる）カラムがid以外もOKになる。

検索結果とは同じ見つかった1レコードを取得してきます。
文字とかも指定できるが、1番最初に見つけたものだけが適応される。


```ruby

#モデル名.find_by(任意のカラム名: 格納されている値)

@post = Post.find_by(title: "Qiita")

```

Postのtitleカラム内で「Qiita」と格納されているものを1つ取得する。


idで見つけるならfindを使う
それ以外ならfind_byを使う

## where

これだけ覚える
↓
**find_byの役割に+αで取得するレコードが複数になる。**

whereはfind_by同様に指定できる（検索できる）カラムがid以外もOK

検索結果が1つではなく該当するものすべてになる。

```ruby

#モデル名.where(任意のカラム名: 格納されている値)

@post = Post.where(title: "Qiita")

```

find_byではtitleに「Qiita」とあるもの1つでしたが、
whereではtitleに「Qiita」とあるものすべてを取得します。


## 最後に

解釈の仕方が間違っていたらごめんなさい。
DBからデータを取得するので個人的には図書館で検索する機械とか漫喫にある本の検索機をイメージしましたね。
そうしたら理解できた気がしたので載せました^^
typescriptでnumberが自然数かどうか、booleanで返す関数

# typescriptで自然数を判別したい
調べると、型でなんとかしようとする記事が目立った。
でもなんかむずそうだから、普通に関数でやろうと思った。

```typescript
// 自然数だったらtrueを返す
const isNatureNum = (num: number): boolean => num > 0 && isInteger(num);
```

# 使い所
cssのプロパティって、自然数しか使えない場面ってある。
自分の場合、grid使うときにrowを制限したいときとか使った。
この実装だと`limitRow` が `null` , `undefined` , `0` , `''` らへんは全部`grid-auto-rows`になるはず（間違ってたらごめんね）
そもそも型で`number`に絞ってるけどね。

```typescript
isNatureNum(prop.limitRow)
    ? {
        overflow: 'hidden',
        gridTemplateRows: `${prop.gridHeight}`,
        height: 'auto',
        maxHeight: `calc(${prop.gridHeight} * ${prop.limitRow})`,
      }
    : { gridAutoRows: `${prop.gridHeight}` };
```



もっといい方法あったら教えてください
Flutter入門者がアプリ開発をするにあたって参考にしているサイト一覧

１２月からFlutterアプリを開発中で、参考になった記事や参考にしてるサイトの備忘録としてまとめます。
都度更新していきます。


# 公式リファレンス

##[**Flutter Codelab**](https://flutter.dev/docs/get-started/codelab)
 - https://flutter.dev/docs/get-started/codelab
 
Googleの提供しているCodelabsで、Flutterのチュートリアルがあったので学習当初にやってました。
英語ではありますが翻訳記事もあったり、ボリュームもpart2まで合わせて２〜３時間でサンプルアプリを作れるのでオススメ。

![スクリーンショット 2020-12-23 10.47.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329865/494548b5-1b10-48b9-768a-6efbad18a185.png)

##[**Flutter documentation - Flutter**](https://flutter.dev/docs)
 - https://flutter.dev/docs

Flutterの公式ドキュメント。
CookBookから基本的なレイアウトの実装例をコピペして使用したり、Widgetについてもかなり詳しく記載があるのでよく参考にしていました。
日本語版もありますが所々翻訳途中の部分があります。英語に抵抗がある方はこちらもオススメ。

[**Flutter Doc JP**](https://flutter.ctrnost.com/)
https://flutter.ctrnost.com


##[**Puv.Dev**](https://pub.dev/)
- https://pub.dev

Dartの公式パッケージリポジトリ。
外部のライブラリを使用して機能を追加したい時に役に立つと思います。
いくつかの評価軸でパッケージがスコアリングされており、自分の場合はライブラリ選定の際に、とりあえずLikesの多さとPuv Pointの高さで選定してました。
gitから特定のファイルだけのパッチファイル、diffファイルを作りたい

記事が見つからなかったため備忘録。

#gitで特定のファイルの差分の確認
```
$ git diff --FileName
```
#特定のファイルだけのパッチファイル作成
```
$ git diff --FileName > name.patch
```
#特定のファイルだけのdiffファイル作成
diffファイルだとファイル名などに依存しないためパッチを当てやすくて便利。

```
$ git diff --FileName > name.diff
```
#パッチを当てる
```
$ patch -p1 < name.diff
```
書籍「プログラミングレスデータ分析のすすめ」告知

[Dataiku DSS](https://www.dataiku.com/)を扱った記事をちまちま書いておりましたが、編纂・加筆したものを書籍化しましたのでこの場を借りてお知らせです！


<b>「プログラミングレスデータ分析のすすめ」</b>、本日2020/12/23発売です。
無償での公開となりますので、ちょっとでも気になった方、ぜひお手にとってみてください。この書籍はDataiku社公認であり、Dataiku社との共同出版物となります。


|<img width="400" alt="cover.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106215/dcfda8b2-2511-60f5-1592-b1180acd07fd.png">|
|:--:|


#本の紹介
本書は、Dataiku 社（https://www.dataiku.com/）が提供する分析ツールDataiku Data Science Studio（Dataiku DSS）を使って、実際の現場でデータ分析を進めるための第⼀歩を踏み出すための⼊⾨書です。
本書では、T シャツショップの売上向上というユースケースを通じて、実際のデータ分析の現場で必要となる分析プロセスを体験することができます。具体的には、データ加⼯やデータの傾向を把握するためのデータの可視化、たくさん商品を購⼊してくれる顧客を判断するための機械学習モデルの作成、およびその評価⽅法までの⼀連の分析作業を体験することができます。初⼼者の⽅でもデータ分析のことを知っていただけるように、Python やR などの分析⾔語の知識がなくても、Dataiku のGUI を使ってデータ分析を体験できるようになっています。
そのため、現場でのデータ分析をどのように進めていけばよいか知りたい⽅には、きっと役⽴てていただける内容となっていると思っております。本書を通じて、実際のビジネス現場でのデータ分析で活⽤いただれば幸いです。

#目次
目次はこんな感じになっています。基本的な使い方から、機械学習の実行までチュートリアル形式で記載されています。

|<img width="450" alt="サンプルページ_ページ_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106215/d679354f-7f77-3974-8779-b2fe3e7cb94a.png"><img width="450" alt="サンプルページ_ページ_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106215/98e2744b-b55e-3e6f-0c15-ee98f6c00f25.png">|
|:--:|


#ダウンロード元
以下からダウンロードできます。
Google Play books　完全版
https://play.google.com/store/books/details?id=gvwEEAAAQBAJ

Google Play books　軽量版
https://play.google.com/store/books/details?id=lAUHEAAAQBAJ
※中身は完全版と同じですが、ちょっと軽いです。その分、画像が小汚くなっています。


技術書典10へも出展してます！こちらは、2020/12/26以降、購入可能になります。
https://techbookfest.org/product/5117838303952896

#執筆メンバー
さいごに、書籍執筆計画に巻き込まれ、この半年ほど業務の間に地獄を見せてしまったかもしれない方々です。ありがとうございます、本当にありがとうございます。これからもよろしくお願いいたします。

 - [@goya1021](https://qiita.com/goya1021)
 - [@ponnchi](https://qiita.com/ponnchi)
 - [@hktonton](https://qiita.com/hktonton)
 - [@ningendamono](https://qiita.com/ningendamono)
Ibus-mozc 最速コマンド


Mozcフォルダと、download.lstファイルを作成

```
# mkdir ~/Mozc
# cd Mozc/
# vi download.lst
```

download.lstファイルの中身

```
ftp://ftp.pbone.net/mirror/archive.fedoraproject.org/fedora/linux/releases/19/Everything/x86_64/os/Packages/i/ibus-mozc-1.10.1390.102-1.fc19.x86_64.rpm							
ftp://ftp.pbone.net/mirror/archive.fedoraproject.org/fedora/linux/releases/19/Everything/x86_64/os/Packages/m/mozc-1.10.1390.102-1.fc19.x86_64.rpm							
ftp://ftp.pbone.net/mirror/archive.fedoraproject.org/fedora/linux/releases/19/Everything/x86_64/os/Packages/p/protobuf-2.5.0-4.fc19.x86_64.rpm							
ftp://ftp.pbone.net/mirror/archive.fedoraproject.org/fedora/linux/releases/19/Everything/x86_64/os/Packages/z/zinnia-0.06-16.fc19.x86_64.rpm							
ftp://ftp.pbone.net/mirror/archive.fedoraproject.org/fedora/linux/releases/19/Everything/x86_64/os/Packages/z/zinnia-tomoe-0.06-16.fc19.x86_64.rpm							
```

download.lstファイルの中身を取得

```
# wget -i download.lst
# sudo yum localinstall -y protobuf-2.5.0-4.fc19.x86_64.rpm zinnia-0.06-16.fc19.x86_64.rpm zinnia-tomoe-0.06-16.fc19.x86_64.rpm mozc-1.10.1390.102-1.fc19.x86_64.rpm ibus-mozc-1.10.1390.102-1.fc19.x86_64.rpm
```

後は再起動！
すべてのレイヤーを破壊する。それらは再生できない。

[ばーちゃるえんじにあ の 星野ニア](https://twitter.com/HoshinoNieR) です。

みなさんはレイヤーを吹き飛ばしたくなったことはありますか？
ない？例えばこういう時です。（動画リンク）
[![1ミリも作業が進まない星野源](http://img.youtube.com/vi/cNtHUVJt1yo/0.jpg)](https://www.youtube.com/watch?v=cNtHUVJt1yo)


じゃあ早速レイヤーを吹き飛ばしましょう。
今回はPhotoshopです。

## 実装された運用
Photoshop上で実行するとUIパネルが出るので(2)(白)(白)を支払って唱えます。
すべてのレイヤーを破壊し上書き保存、すべてのヒストリーを削除（再生できない要素）します。
![1223a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703685/90cb24e9-f38c-ae0e-b805-dcd62a29c5fd.gif)


## 想定した運用
GUIにPSDをドラッグ&ドロップしたらレイヤーを全削除して上書き保存するやつ。

## 手法選定
* GoかPythonかJavascriptでPSDの上書きできるやろ  
　->読み込み用のPSDパーサーはあるけど書き込み用が無い。
* バイナリから直接レイヤーデータ消去しよ  
　->めんどくさ
* Psスクリプトにしよ

## 実装
UIは省略します。

``` javascript:すべてのレイヤーを破壊する。それらは再生できない。.jsx
var doc = app.activeDocument;
//全レイヤー結合
doc.mergeVisibleLayers();
//統合レイヤー削除
doc.layers[0].allLocked = false;
doc.layers[0].remove();
//保存
doc.save();
//履歴削除のためブリンク
var _path = doc.fullName.fullName;
doc.close();
app.open(new File(_path), OpenDocumentType.PHOTOSHOP);
```

[HoshinoNia/wrathofgod: すべてのレイヤーを破壊する。それらは再生できない。](https://github.com/HoshinoNia/wrathofgod)

## 感想
誰かGoかPythonでPSDの上書き操作できる手段を教えてください。
伊坂幸太郎「モダンタイムス」に出てくる出会い系サイトのアーキテクチャと技術選定をしてみた

こんにちは！

**この記事は[ユアマイスターアドベントカレンダー](https://adventar.org/calendars/5455)の23日目の記事です。**

## 記事のテーマ
伊坂幸太郎さんの「モダンタイムス」という小説に出てくる[出会い系サイト](https://ja.wikipedia.org/wiki/%E5%87%BA%E4%BC%9A%E3%81%84%E7%B3%BB%E3%82%B5%E3%82%A4%E3%83%88)のアーキテクチャと技術選定をエンジニア目線でやってみた、というものになります。
いつかこの小説に出てくる出会い系サイトとちゃんと向き合いたいと思ってたので嬉しいです。
**そして、「ここはこうだと思うよ」「こういう機能も必要なんじゃない？」などご意見あればコメントお願いします！！！**

## 簡単に自己紹介
エンジニア３年目・社会人３年目
好きな言語：Java
興味のある技術：Go
好きな作家（一番重要）：村上春樹、伊坂幸太郎
（おすすめの小説とか作家があればコメント大歓迎です）


## 「モダンタイムス」を知らない人のために簡単に説明します
主人公の**渡辺**はエンジニアとして働いており、ある日業務から逃げ行方不明になった**五反田**（同僚）の代わりに**株式会社ゴッシュ**という会社の出会い系サイトの**改修**を行う。その改修自体はユーザーの使用する登録画面に新しい項目を5つ追加するというシンプルなもの。**「こんな簡単な案件から五反田が逃げ出すなんておかしい！」**と思った渡辺はその出会い系サイトについて調べ、ある事実が判明した。
その出会い系サイトはある**特定の文言**で調べないと到達することのできない特殊な出会い系サイトであった。（その**特定の文言**はソースコード上で暗号化されており、独自のコンパイラがないと解析することができない。）そして、その特定の文言で検索を行い出会い系サイトに到達した人間は次々に殺されていくのであった。。


というのが大まかなストーリーであります。

以下、アーキテクチャと技術選定は完全に**独断と偏見**です

## アーキテクチャ（予想）
![ゴッシュ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495707/1e6fcb7b-6c5e-69d1-f636-56ca49166b29.png)

## アーキテクチャの説明

マイクロサービスアーキテクチャです。理由は下記です。
①機能によって別コンパイルが必要
②管理のしやすさを重視
この結果マイクロサービスアーキテクチャが妥当という結論になりました。

*補足*
この物語で肝になる、「特定の文言で検索エンジンで検索を行い出会い系サイトに到達した人」の解析を行っているのが**アクセス解析バッチ**になります。

## 技術選定
まず前提にこの本が出版されたのが２００８年なのでこの時代に適した？技術を選んだつもりなのですがお手柔らかにお願いします。。。

- 自社サーバー
    - AWSでもなく自社で作ったサーバーです。なぜかと言うと、小説内ではこの出会い系サイトが**Web上のどこにあるのかわかっていないからです**。自社サーバーと聞くと脆弱性の問題や攻撃を受けやすい印象がありますが、、、そこはすご腕のエンジニアがゴッシュにはいたという設定で自分の中で解決しました。

- サーバーサイド
    - Javaです。この時代？のWebサービスはJavaという印象がありました。PHPも候補に入れてたんですが、ゴッシュという会社は自社サーバー作っちゃうくらいなのでPHPだとエンジニアのコスト抑えすぎ＆そんな軽い言語ゴッシュが選ぶはずないと思ったのでJavaにしました。フレームワークはSpringです。

- 解析系バッチ
    - Pythonです。解析と言ったらPythonかなと思いました。（安直）


- 暗号化されてないデータベース
    - ユーザー情報やログ情報を格納するのはMySQLです。ゴッシュにとってこのDBに格納される情報自体あまり重要ではないかなと思ったのでMySQLにしました。

- 暗号化されたデータベース
    - 検索エンジンで特定の文言で検索をかけて出会い系サイトに到達した人の情報（年齢・職業・名前）やどの検索エンジンを使ったのかなどの情報を格納するのがこのデータベースです。なぜCassandraかと言うとゴッシュにとって**一番重要なデータ**を格納するからです。改竄されてはいけない、抜け落ちてはいけない、この条件を満たしてくれるのは分散処理に適したCassandraかなと思いました。上記の画像では１ノードしか用意してないですがおそらく５ノードくらい実際にはあると思います、リッチな会社なので。

- 独自のコンパイラ
    - ソースコード上で暗号化されている箇所が散見されています。その暗号を解析するのが独自のコンパイラです。実際にはどの言語で実装すればいいのか悩んだ結果Pythonです。これも暗号とか解析と言ったらPythonかな・・・と思い選定しました（安直）

- フロント・画面
    - タイムリーフです。サーバーからもらったデータを表示させるのはタイムリーフで、簡単な動的な処理はJSにやってもらおうと思いました。Javaといったらタイムリーフかなって思いました（安直）


## 感想
実際に作ってみたいと思いました。（でもタイムリーフは使いたくない。Vue.js使いたい）
独自のコンパイラとか作るの大変そうだがいい勉強になりそうだと思いました。
一番大変だったのは小説を読み直すことです。読んだ人は知ってると思いますが結構長いです。
ミドルウェアとかもっと考えたかったです。
技術選定って楽しいなと思いました！！
[PowerShell]フォルダ内のファイル一覧を出力


事前に対象フォルダをPowerShellで開いておき、下記コマンドを実行する

```powershell
Get-ChildItem -Recurse -Name -File
```

[Get-ChildItem (Microsoft.PowerShell.Management) - PowerShell | Microsoft Docs](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.management/get-childitem?view=powershell-7.1&viewFallbackFrom=powershell-6)
Pathlibで半角スペースを含むフォルダにアクセスできなかった話

Pythonのお勉強でPathlibを扱っていた時に詰まったので解決策を示しておきます。（Mac)
# 注意
- @shiracamus　さんより指摘
    - Windows環境ではパスの区切り文字が違うのでこの解決策では正常に動作しません
        - `re.sub(r'\\ ',' ',str(x))`とすることでWindowsに対応


# 問題内容
例) 以下のコードで ~/test blank folder/ の存在を確認する

```python:test.py
import pathlib
x = input('')
fpath = pathlib.Path(x)
print(fpath.exists())

```

```shell
python blankCharPathlib.py
path >>> ~/test\ blank\ folder 
~/test\ blank\ folder  False
```

バックスラッシュで半角スペースがエスケープされているので、上手く動作しない
シングルクォーテーションやダブルクォーテーションで囲んでみたが意味無し

```shell
python blankCharPathlib.py
path >>> '~/test\ blank\ folder'
'~/test\ blank\ folder' False

python blankCharPathlib.py
path >>> "~/test\ blank\ folder"
"~/test\ blank\ folder" False
```


#解決策
エスケープのバックスラッシュを消す。解決
※2020/12/23 12:22 変更

```python:test2.py
import pathlib
import re
x = input('path >>> ')
fpath = pathlib.Path(re.sub(r'\\ ',' ',str(x)))
print(str(fpath) ,fpath.exists())
```

```shell
python blankCharPathlib.py
path >>> ~/test\ blank\ folder  
~/test blank folder True
```
serverless framework でローカルPCの環境変数を参照するやり方

[公式の説明](https://www.serverless.com/framework/docs/providers/aws/guide/variables#referencing-environment-variables)に書いてある様にローカルPCの環境変数を使うには`${env:SOME_VAR}`を使うらしいです。

自分の場合、cloudfrontに事前に取得したACMのARNを設定するために環境変数を使用したい。

```yaml
  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Aliases:
          - ${self:custom.siteName}
        Origins:
          - DomainName: ${self:custom.siteName}.s3-website-${self:provider.region}.amazonaws.com
            Id: S3Origin
            CustomOriginConfig:
              HTTPPort: 80
              HTTPSPort: 443
              OriginProtocolPolicy: http-only
        Enabled: true
        DefaultRootObject: index.html
        DefaultCacheBehavior:
          AllowedMethods:
            - GET
            - HEAD
          TargetOriginId: S3Origin
          ForwardedValues:
            QueryString: true
            Cookies:
              Forward: none
          ViewerProtocolPolicy: redirect-to-https
        ViewerCertificate:
          AcmCertificateArn: ${env:ACM_ARN} # こんな感じで使いたい
          SslSupportMethod: sni-only

```

### どうやって設定するのか
macOSの場合

```terminal
#設定方法
$ export ACM_ARN=arn:aws:acm:us-east-1:xxxxxxxxxx:certificate/xxxxxxxxxxxxxxx

#確認
$ echo $ACM_ARN
=> arn:aws:acm:us-east-1:xxxxxxxxxx:certificate/xxxxxxxxxxxxxxx

#全ての環境変数を確認する
$ set

#削除
$ unset ACM_ARN

$ echo $ACM_ARN
=> 何も表示されない
```

以上で設定ができます
ServiceNow - 国際化対応UIを考える

#概要
利用者が全員日本語ができるユーザのみでしたら国際化対応を考えなくてもよいかも知れませんが、最近では海外からの人を採用している企業も多くなりました。その時に考える必要があるのはユーザインターフェースです。

#課題
ServiceNowでは標準でユーザ名などマスタデータを言語毎に設定することは出来ないのでフォームのユーザ選択をする場合は日本語でも英語でも同じ内容が表示する。そのため、プルダウンリストに漢字名の名前だけを表示すると英語キーボードを利用されている日本語が出来ないユーザは選択するのに困る。
このような問題を解決するためには日本語が出来ないユーザでも分かるユーザ選択にメールアドレスも含めるようにする。

以上