OmniAICreator/Qiita-1.07M huggingface dataset:
React-Grid-LayoutでサクッとDrag & Dropできるコンポーネントを作る

React-Grid-Layoutを使用して、Drag & Dropで移動でき、サイズの変更も可能なコンポーネントの実装を試してみます。
完成形は以下のようになります。

![react-grid-test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503026/9809d4f0-254b-4489-e64c-c8a06ee3c8fe.gif)

#React-Grid-Layoutって？
React-Grid-Layout(以下RGL)はReact用のグリッドレイアウトです（まんま）。
上の画像のように、D&Dでコンポーネントの移動ができるようになります。
また、RGLのインストールにはreact-resizableというパッケージも含まれており、コンポーネントのサイズの変更も可能になります。


多分GitHubのREADME見れば実装するのも簡単だと思いますが、
React初めて一週間くらいなので、練習がてらまとめておきたいと思います。


####GitHub
https://github.com/STRML/react-grid-layout


#インストール
まずはパッケージをインストールします。

```
npm install react-grid-layout
```

インストール後、以下のCSSのインポートをどこかに追加しましょう。
今回はindex.jsでインポートしました。

```
import '../node_modules/react-grid-layout/css/styles.css';
import '../node_modules/react-grid-layout/css/styles.css';
```

#実装
あとはコーディングしていくだけです。
今回は子コンポーネントを一つだけ用意して、propsだけ変えて何個か呼び出すような感じにしました。
先にコードを載せておきます。
React超初心者なので書き方間違ってるところとかあったらスミマセン。

```jsx:(親)App.js
import React from 'react';
import GridLayout from 'react-grid-layout';
import SampleComponent from './SampleComponent';

class App extends React.Component {

  constructor(){
    super();
    this.state = {
      cols : 12,
      rowHeight : 30,
      width :window.parent.screen.width
    }

    this.layouts = [
      {i: 'a', x: 0, y: 0, w: 2, h: 4},
      {i: 'b', x: 2, y: 0, w: 4, h: 4},
      {i: 'c', x: 6, y: 0, w: 2, h: 8},
      {i: 'd', x: 0, y: 4, w: 5, h: 5},
      {i: 'e', x: 0, y: 9, w: 5, h: 2},
      {i: 'f', x: 6, y: 11, w: 2, h: 2},
    ];
  }

  render(){
      return (
      <GridLayout className="layout" layout={this.layouts} cols={this.state.cols} rowHeight={this.state.rowHeight} width={this.state.width}>
        <div key="a" style={{border:"solid", backgroundColor:"#EEEEEE", textAlign:"center"}}><SampleComponent componentName="A" /></div>
        <div key="b" style={{border:"solid", backgroundColor:"#EEEEEE", textAlign:"center"}}><SampleComponent componentName="B" /></div>
        <div key="c" style={{border:"solid", backgroundColor:"#EEEEEE", textAlign:"center"}}><SampleComponent componentName="C" /></div>
        <div key="d" style={{border:"solid", backgroundColor:"#EEEEEE", textAlign:"center"}}><SampleComponent componentName="D" /></div>
        <div key="e" style={{border:"solid", backgroundColor:"#EEEEEE", textAlign:"center"}}><SampleComponent componentName="E" /></div>
        <div key="f" style={{border:"solid", backgroundColor:"#EEEEEE", textAlign:"center"}}><SampleComponent componentName="F" /></div>
      </GridLayout>
    );
  }
}

export default App;
```

```jsx:(子)SampleComponent.js
import React from 'react';
import './App.css';

class SampleComponent extends React.Component{

    render(){
        console.log(this.props);
        return (
            <div>
                <h3>Component {this.props.componentName}</h3>
            </div>
        );
    }

}

export default SampleComponent;
```

親のGridLayout要素で囲んだ部分がグリッドレイアウトになります。
layout属性にあらかじめ子コンポーネントの位置を指定しておくようにします。
これでなんとなく機能を試すことができます。


しかしこれ、ページ表示時やリフレッシュ時にコンポーネントを移動させようとすると、
全コンポーネントが一瞬だけ浮き上がったような挙動をするんですよね…
自分のやり方がどこか間違ってるのかなんなのか…

ちょっとここは後で調べておかないとですね。
Microsoft Teamsアプリで通知が来ない（Windows)

Teamsで通知が来ない！ということでトラブルシュート。備忘録兼ねてまとめてみた。


#ヒアリング
まずは、ヒアリング。

- Windows PCと、iPhoneと両方で使ってる。
- チャットやチームで発生する。
- iPhoneでは通知が来るけど、Windowsでは通知が一切来ない。

一切、というのが気になる。

通知は「バナー通知」のことらしい。
別のデバイスでTeamsがアクティブならそっちに通知がいくけど、iPhoneは普段はアクティブじゃないから普通ならWindowsのデスクトップアプリにも通知は来るはず。

#切り分け

アカウントの問題か、環境の問題か、切り分け。この手のトラブルではお約束でやってみる。

|PC|ユーザー|通知|
|:--|:--|:--|
|問題が起きているPC|通知が来ないアカウント|来ない|
|別ユーザーのPC（通知が来る）|別ユーザーのアカウント(通知が来る）|来る|
|||
|別ユーザーのPC（通知が来る）|通知が来ないアカウント|来る|
|問題が起きているPC|別ユーザーのアカウント(通知が来る）|来ない|

というわけでアカウントにはおそらく問題なし。
PCの環境の問題と言えそう。

#やってみる

Teamsアプリの問題があるんじゃないか？ってことで、いくつか試してみる。

|試したこと|解消|
|:--|:--|
|PC再起動|解消せず|
|サインアウトし、サインイン|解消せず（上記切り分けでもやってるけどね）|
|Teamsアプリの更新|解消せず|
|Teamsアプリのアンインストール・インストール|解消せず|

これでもないのか・・・。てことはWindowsの問題か？

#解消した

そういえば、「時刻がズレてるとSkype for Businessでサインインできない」ってなんかで読んだことがあるな。Teamsはサインインできてるけど、もしや？と確認してみたら・・・


時刻が5分ずれてました。


これを直して、解消！



#まとめ

コミュニケーションツールなのに、通知が来ないというのは致命的。

今回はイレギュラーな端末だったから、設定が漏れてたのかもしれない。
ちゃんと時刻同期設定を入れておけば回避できるので、同期設定入れてクローズ。







#参考資料

バナー通知
[通知について知っておくべき 6 つのこと](https://support.microsoft.com/ja-jp/office/%E9%80%9A%E7%9F%A5%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E7%9F%A5%E3%81%A3%E3%81%A6%E3%81%8A%E3%81%8F%E3%81%B9%E3%81%8D-6-%E3%81%A4%E3%81%AE%E3%81%93%E3%81%A8-abb62c60-3d15-4968-b86a-42fea9c22cf4)

Skype for Business のサインインエラー
[コンピューターの時刻、日付、ユーザー名、パスワードなどの設定が正しくない場合、Skype for Business Online サインインエラーが発生する]
(https://docs.microsoft.com/ja-jp/skypeforbusiness/troubleshoot/online-sign-in/sfb-online-sign-in-error)
Sassをgulpでコンパイルする方法をまとめてみた




```
npm init -y
```

package.json作成


```
npm install -D gulp gulp-sass
```

node_moduleができる

gulpfile.jsを作成してgulpfile.jsファイル内に以下のコードをコピペ


```
// gulpプラグインの読み込み
const gulp = require("gulp");
// Sassをコンパイルするプラグインの読み込み
const sass = require("gulp-sass");

// style.scssをタスクを作成する
gulp.task("default", function() {
  // style.scssファイルを取得
  return (
    gulp
      .src("css/style.scss")
      // Sassのコンパイルを実行
      .pipe(sass())
      // cssフォルダー以下に保存
      .pipe(gulp.dest("css"))
  );
});
```

sassファイルをcss/style.scssを作成し、を記述

```
// ネストのテスト
div {
  p {
    font-weight: bold;
  }
}

// 変数のテスト
$fontColor: #525252;

h1 {
  color: $fontColor;
}
```



```
npx gulp
```

でコンパイル。
無事下記のようにcss/style.cssにcssがコンパイルされる


```
div p {
  font-weight: bold; }

h1 {
  color: #525252; }

```




こちらの記事がわかりやすい。
https://ics.media/entry/3290/
【WSL2】インストールしたての時に開発環境構築時にハマったこと

WSL2をインストール時にすんなりとうまくいったらなにも問題ないのですが、
エラーが出力して原因を探ったり、一見うまくいったように見えても実は間違っていたりと、
使いこなすのがなかなか大変です。
ハマったことを色々書いていこうと思います。

Ubuntu 18.04.4 LTSを使用しています。

## phpをインストールしてみるとエラーが出力されて、インストールできない

```
Err:6 http://security.ubuntu.com/ubuntu bionic-updates/main amd64 apache2-bin amd64 2.4.29-1ubuntu4.6
  404  Not Found [IP: XX.XXX.XX.XXX 80]
Err:7 http://security.ubuntu.com/ubuntu bionic-updates/main amd64 apache2-utils amd64 2.4.29-1ubuntu4.6
  404  Not Found [IP: XX.XXX.XX.XXX 80]
Err:8 http://security.ubuntu.com/ubuntu bionic-updates/main amd64 apache2-data all 2.4.29-1ubuntu4.6
  404  Not Found [IP: XX.XXX.XX.XXX 80]
```

パッケージの更新とアップグレードをしていなかった

```
sudo apt update && sudo apt upgrade
```

この後に、もう一度phpをインストールする

参考：
https://docs.microsoft.com/ja-jp/windows/wsl/user-support


## この調子でnodeもインストールしたが、vue.jsの開発環境をうまく構築できない

エラーなどなにも出力されずに、インストールもうまくいったように見えました。

ところが、apt-getに登録されているnodeのバージョンが古いままになっているので、これだと失敗します。作りたい開発環境にあわせてnodeをインストールする。

参考：
https://docs.microsoft.com/ja-jp/windows/nodejs/setup-on-wsl2


## Ubutu日本語化／英語切り替える

https://www.atmarkit.co.jp/ait/articles/1806/28/news043.html


## まとめ
開発環境を作ろうとして調べると、いろんな情報が手に入ります。
そもそもWSL2やUbuntuを理解していないとハマってしまいがちでした。
TREASURE DATAさわってみた、まとめ

#TREASURE DATAとは
データやログを収集・分析し、ビジネスへ生かす、カスタマーデータプラットフォームである。（=CDP）

####データの収集 >>> 統合・分析・セグメンテーション >>> 施策への連携（レポート・広告配信・マーケティング）

TREASURE DATAは、Arm社に買収されたので、ソフトバンクグループの投資先の１つになっているのですね。
###参考
https://www.treasuredata.co.jp/learn/

#CDPとは
こちらを。。
###参考
https://www.treasuredata.co.jp/learn/cdp-vs-dmp/

#TreasureDataのWorkflowという機能について
SQL実行をスケジュール起動するサービスです。
タスクという単位でSQL等に依存関係を持たせることができます。（SQL①が動いてから、②が動くなど）

例えば、データのインポートやエクスポートのSQLを日次08:00で実行するなど。

Workflowというサービスは、内部的には、OSSで公開されているdigdagというソフトを使用しています。
そのため、digdagで調べたことは、だいていWorkflowに適用可能です。

###参考
ワークフロー定義　★digdagの公式サイトがわかりやすい！
https://docs.digdag.io/workflow_definition.html

treasuredata スタートガイド
https://support.treasuredata.com/hc/ja

Digdagのワークフロー定義について理解する
https://dev.classmethod.jp/articles/understanding-digdag-workflow-definition/

Treasure Workflow for ビギナー 環境構築編
https://blog.torut.tokyo/entry/2017/08/01/233655

Treasure Workflow for ビギナー ~digファイル書き方編~
https://blog.torut.tokyo/entry/2017/08/01/070000

digdagでエラーを無視して後続タスクを進める
https://qiita.com/fk8_jp/items/ef6871549d737ada7da2

#Workflowのサンプル（selectで取得したデータをcopyコマンドで別のデータベース＞テーブルにコピーする）
```sample.dig

#タイムゾーン
timezone: Asia/Tokyo

#スケジュール
schedule:
  cron>: 0 12 * * *

#タスク（+XXX　好きな名前を付けたらいい）
+task1
  #オペレータ（XXX> ココ参考→https://docs.digdag.io/operators.html）
  td>
  query: select * from [テーブル名]
  result_connection: [treasureに設定した、接続DBの名前]
  #すいません、ここから下自信なし。忘れ気味。。
  result_settings:
    database:[データベース名]
    schema:[スキーマ名]
    type:[truncate or replace or append or update]
    unique:[※update時のみ必須 何が重複したら更新するか。カンマ区切り]
    methodo:copy [copy or XXX ※copyはcopyコマンド]
```
参考
・tdオペレータの説明
https://docs.digdag.io/operators/td.html

#実体験メモ
- workflowのscheduleは、cron以外（daily）だと、workflow>run historyのsessionタイムが正しく表示されない。常に12時になるとか。
- workflow>run historyのsession timeはスケジュールの時間（スケジュール起動以外だと現在日時）、attempt timeは実際実行された時間
- sqlには使用しているDBの関数以外に、Treasureの独自定義関数が使用できる。
https://support.treasuredata.com/hc/ja/articles/115011438008-%E5%88%9D%E7%B4%9A%E3%83%8F%E3%83%B3%E3%82%BA%E3%82%AA%E3%83%B3-TD%E9%96%A2%E6%95%B0-%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%83%AD%E3%82%B0%E7%B7%A8-
　独自定義関数は、パフォーマンスもよく、SQLが簡潔になるらしい。
　関数TD_SCHEDULED_TIMEには、workflow>run historyのsession timeと同じ時間が設定される。
　Time Indexを設定しているデータベースの場合は、以下にTime Indexをきかせるかが大事らしい。
- workflow>run history>outputlog には、実行時のログが記録されている。どういう動きをしているかを確認しやすい。
　例えば、workflowでデータを登録するときに、"method:copy"を使用すると内部的にどう動くのだろうとoutputlogをみると、普通にcopyコマンド使っていることがわかる。
WPS非対応のMeraki GoでWPS接続済みの機器を接続しなおした。

#謝辞
こちらに「LGTM」をされた方はぜひ以下の記事にも「LGTM」をお願いします。
[WPS非対応の無線LAN端末(Meraki)に対してヘルシオホットクックから接続する方法](https://qiita.com/shimma/items/c443ac63006b1782de58)

#目的
最近Meraki Goを買って前に使っていたBuffaloの無線LAN アクセスポイント（以下無線LAN AP）につなげていたものをつなぎなおすところで、WPS接続していた機器をどう移そうか迷っていたので、検索して調べて実際につなげなおしたのでそのやり方を紹介する。

#準備
-WPS対応無線LAN AP（今回はBuffaloの[WHR-1166DHP](https://www.buffalo.jp/product/detail/whr-1166dhp.html)）
-WPS非対応無線LAN AP（今回はCiscoの[Meraki Go](https://www.cisco.com/c/m/ja_jp/meraki-go.html)）
-それぞれの電源・LANケーブル
#基本構成
```
準備段階：
ルータ > Buffalo無線LAN AP > Clients（エアコン・カメラなど）
目標：
ルータ > Meraki Go（無線LAN AP） > Clients（エアコン・カメラなど）
```

ちなみにMeraki Goに限らずWPS/AOSS非対応の無線LAN APでも同様に接続可能と思われる。この記事を参考に試してほしい。

#仕組み
WPSは接続が確立すると無線LAN APの接続情報を無線LAN子機（今回はエアコン）に情報を送っている、その情報をMeraki Goにも設定してあげると無線LAN子機はその情報をもとに接続するのでMeraki Go経由に通信経路が変わっていく。

#やり方
1. （無線LAN子機をつなげていない場合は）WPSで無線LAN親機に1度接続する。
1. 無線LAN親機のSSID情報と暗号キーをメモする。
情報をメモする箇所はSSIDと暗号キー[^3]
![SSIDと暗号キーをメモする](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101343/f97cf341-83e6-2925-ba21-cb4a72f9bbc4.png)
1. Meraki Goに無線LAN親機のAP情報（SSID、暗号キー）を登録する。
![Meraki Goに新たにAPを作る](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101343/44bb4411-f027-7378-91cf-052bef909dac.jpeg)

1. 無線LAN親機を抜く。
1. （場合によっては）無線LAN子機を再起動する。 [^1]

#注意点
- 新規にWPS接続/AOSS接続する場合には、前もってWPS/AOSS対応無線アクセスポイントが必要となる。（無線LANを使う機械（カメラなど）の仕様による）
- 無線LAN子機を再起動（または電源OFF/ON）する目的は以下の通り。

 2. 同じIPアドレスを持っていても無線LAN子機で前の無線LAN AP接続ルートを保持している場合があるのでその情報をクリアするため。[^2]
 2. 無線LAN APポイント経由で取得するIPアドレス（ネットワークアドレス）が違う場合は、IPアドレス情報を取り直すため。
   
#参考文献
[WPS非対応の無線LAN端末(Meraki)に対してヘルシオホットクックから接続する方法](https://qiita.com/shimma/items/c443ac63006b1782de58)
※本当に助かりました。これをリスペクトして記載しています。

[Wi-Fi Protected Setup(WPSのこと)](https://ja.wikipedia.org/wiki/Wi-Fi_Protected_Setup)
※最後はESSIDと暗号キーをClientに送っているところがポイントです。

[AOSS接続で設定した暗号を確認する方法](http://buffalo.jp/download/manual/html/air851/router/whrg54s/chapter110y.html)
※昔の機器でAOSSしかない人向け

[ネットワーク名（SSID）と暗号化キーは、どこに記載されていますか？(Aterm)](https://www.aterm.jp/support/qa/qa/00003.html)
※Atermを利用している方向け

[無線LAN接続アダプターの設定について（日立）]
(https://kadenfan.hitachi.co.jp/ra/app/setting_lan.html)
※今回自宅ではSP-WL2を使ってました。

[Frequently Asked Questions regarding Cisco Meraki AP Devices]
(https://documentation.meraki.com/MR/Other_Topics/Frequently_Asked_Questions_regarding_Cisco_Meraki_AP_Devices)
※​​​​​​​Does my AP support Wi-Fi Protected Setup (WPS)?に答えがあり、現時点ではサポートしないと記載してます。

[^1]: 注意点を参照
[^2]: 時間が経てば接続できるようになると考えられるが、さまざまな機器の仕様によるためと考えている。（端末からアクセスがないときにMACアドレス情報をクリアするまでの時間）
[^3]: 通常は2つSSIDがあるが片側だけでよい。
早見表: Linux ディスク関連コマンド集


時々、ど忘れしちゃうので。自分用にまとめたコマンド集。

# ディスク容量

## ディスクドライブの容量を確認

```
$ df -h
```

- -h オプションで、バイトではなく、MB やGB 表示

## ディレクトリの容量を確認

```
$ du -d 1 -h
```

- -d + 階層、で現在の位置からのディレクトリのディスク容量
- -h オプションで、バイトではなく、MB やGB 表示

## 現在のディレクトリの中にある各ディレクトリの容量

```
du -h --max-depth=1 
```


# ファイルカウント

## ディレクトリ内のみのファイル数

```
find . -type f -depth 1 | wc -l
```


## サブディレクトリを含めたファイル数

```
find . -type f | wc -l
```


# 設定

## ディスク & パーティション情報

ディスク & パーティション情報を表示

```
lsblk
```

## SWAP ファイルを作る

別の記事にまとめました
https://qiita.com/katzueno/items/0a63b46c69602ecdeae5

## ディスクを増量する

AWS EC2 の EBS などでディスク容量後に設定する方法 (Amazon Linux & Amazon Linux 2)
https://qiita.com/katzueno/items/4ceb93cc14bbab4e3064
GolangのWebAPIをsupervisorでデーモン化して公開する。

GolangのWebAPIをデーモン化して公開する際に役立った情報の備忘録です。

##使用環境

Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type (無料使用枠)

##デーモン化とは

そもそもGolangのWebAPIを公開する方法を知らず、Linux上で"GO RUN main.go"を実行すればよいのかと考えていた。この方法だと、RLoginなどで接続を閉じたタイミングで処理も終了してしまって上手く行かなかった。

調べるうちに、デーモン(UNIX系OSにおいて、常時待機しているプログラムを指す)というものに行きついた。[Golang デーモン]で検索すると多数ヒットしたので、Golangのmain.goを常駐化させる方針を立てた。

##supervisor
Golangのバイナリを常駐化させる為のツール。
Nginx同様にconfファイルで設定を行う必要がある。

##supervisor.confの編集
```vim
sudo vi /etc/supervisord.conf
```

##supervisor.confの中身

設定項目は複数あるが、基本的に[program:XX]の設定のみで動くはず。

```vim
[program:XX]
command=/home/ec2-user/hoge/main
```

hogeフォルダにバイナリ化したgoプログラムを配置した場合の例。
編集したら、下記の手順で再起動を行えば反映される。

##supervisord.confを変更した場合の再読み込み手順

```vim
sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl restart XX
```


##プログラム内で環境変数を利用している場合の注意
筆者の環境だと、supervisorでデーモン化したプログラムから、環境変数がうまく読み込まれなかった。

デーモンが起動しているプロセス上の環境変数を確認する方法としては以下の通り。
①デーモンが起動しているプロセスを確認

```vim
ps ax | grep main
```
```vim
20591 ?        Sl     0:00 /home/ec2-user/hoge/main
20632 pts/1    S+     0:00 grep --color=auto main
```

②プロセス20591上での環境変数を確認

```vim
sudo strings /proc/20591/environ
```


出てこない場合、環境変数への追加が必要。

##環境変数追加方法
.bashrcなどのファイルに直接書き込む方法
OR
supervisord.confに書き込む方法
の2通り存在する。

①~/.bashrcなどに直接書き込み

```vim
export DB_USER="sa"
export DB_Name="..."
```

②supervisord.confに書き込む方法
[program:XX]のenvironmentにカンマ区切りで環境変数をセットする。

```vim
[program:XX]
...
environment=DB_USER="sa",DB_Name="..."
```

supervisord.confを変更した場合の再読み込み手順を実行すれば、環境変数が反映されるはず。
Splunk 起動時間と終了時間を調べる

小ネタ

```sql:start_shutdown.spl
index=_internal TERM("ShutdownHandler") OR  (TERM("Splunkd")  TERM("starting")) sourcetype=splunkd
```

_Shutdown_は`Shutdown complete`でもいいかなと思ったけど、一応、エラーが出ることも想定して、この文字で検索している。

https://docs.splunk.com/Documentation/Splunk/latest/Troubleshooting/WhatSplunklogsaboutitself
に

| splunkd.log | The primary log for the Splunk server. The log is often requested by Splunk Support for troubleshooting purposes. In addition, any stderr messages generated by scripted inputs, scripted search commands, and similar are logged here. |
|:--|:--|

ということで、Splunk自体の基本的なログとなっている。

[Splunk Admin編 〜 _internal ログ - metrics.log の種類とその利活用 〜](https://qiita.com/kessa/items/c039591f8811dc838583)にも書いてましたね。:sweat:

https://docs.splunk.com/Documentation/Splunk/latest/Forwarding/Receiverconnection
をみると、フォワーダー関連のエラーもこれに表示されることがある。らしい

個人でやっていると、あんまり気にしないけど、システム管理とかしていると気になりますね。
JsonからC#のクラスモデルの作成

C#でJsonをパースする際にクラスモデルを作成すると楽なのですが、
この時にJsonからC#のクラスへ変換してくれるサイトがあります。

よく出てくるのは
http://json2csharp.com/
なのですが、どうも今は閉まっているみたいです。

代わりを探してみたら以下のサイトが使えました。
https://jsonutils.com/

!追記!
コメントいただきました。VisualStudio上の機能でも変換できるとのこと。
https://qiita.com/tsgkdt/items/3e108b2b6c7f2a7e0b21
LightGBMでVerboseがオフにならない件

#解決策

`train関数`に、`verbose_eval=False`を加えましょう。

```
gbm = lgb.train(params,
                lgb_train,,
                valid_sets=lgb_eval,
                verbose_eval=False,)<<<<<<<<<<<<<
```

#ダメだった方法1

ドキュメントのParametersのページを読むと

>verbosity, default = 1, type = int, aliases: verbose
controls the level of LightGBM’s verbosity
< 0: Fatal, = 0: Error (Warning), = 1: Info, > 1: Debug

このように書いてありますが、`verbose=-1`などとしても効きません。



#ダメだった方法2

また、ネットで調べると
`gb_train = lgb.Dataset(X_train, y_train, params={'verbose': -1}, free_raw_data=False)`
も見かけますが、これもダメです。

#理由
LightGBMのVerboseは学習の状況の出力ではなく、エラーなどの出力を制御しているのではないでしょうか。
誰か教えてください。
about.rb

<header>
  <div class="header-logo">
    <!--トップページへのリンクにしてください-->
    <a href="/">TweetApp</a>
  </div>
  <ul class="header-menus">
    <li>
      <!--サービス紹介ページへのリンクにしてください-->
      <a href="/about">TweetAppとは</a>
    </li>
  </ul>
</header>
<div class="about-main">
  <h2>TweetAppとは</h2>
  <p>
    SNSサービスです。
    近況やつぶやきを投稿し、他のユーザーと楽しくコミュニケーションできます。
  </p>
  <img class="about-img" src="/tweets.png">
</div>
top.html.erb

<header>
  <div class="header-logo">
    <!--トップページへのリンクにしてください-->
    <a href="/">TweetApp</a>
  </div>
  <ul class="header-menus">
    <li>
      <!--サービス紹介ページへのリンクにしてください-->
      <a href="/about">TweetAppとは</a>
    </li>
  </ul>
</header>

<div class="main top-main">
  <div class="top-message">
    <h2>つぶやきで、世界はつながる</h2>
    <p>今の気持ちをつぶやいてみよう！</p>
  </div>
</div>
【Golang】ゴルーチン②チャネル

#【Golang】ゴルーチン②チャネル

Golangの基礎学習〜Webアプリケーション作成までの学習を終えたので、復習を兼ねてまとめていく。 基礎〜応用まで。

```
package main

//channel
//スレッド同士のデータのやり取り

//複数チャネルを作って、処理することも可能

import (
	"fmt"
)

//sからcへ送信する処理
func goroutin1(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
		//都度、計算結果を出力
		fmt.Println(sum)

	}
	//全て処理が終わったら、channelに送信
	c <- sum
}

func main() {

	/*
		//var 変数 chan データ型
		var ch chan int

		//送信専用と受信専用の型を指定すると厳密になり、異なる場合、コンパイルエラーになる。
		//送受信に制限を設けない方がオススメ。
		//受信専用チャネル
		var ch1 <-chan int
		//送信専用チャネル
		var ch2 chan<- int
	*/

	/*
		チャネルの特徴

		キュー（待ち行列）の性質を持つ。
		バッファサイズは格納できる領域。
		キューにはFIFO（先入先出し）という性質がある。

		チャネルに送信
		ch <- 1
		チャネルから受信
		i := <- ch
	*/

	//スライス作成
	s := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	//channelを作成
	c := make(chan int)

	//並行で走らせる
	go goroutin1(s, c)
	go goroutin1(s, c)

	//channelからデータを受け取る
	//データが入るまで待ってくれる。
	//goroutine1でsumにデータが入ったらcに入り、xに送る
	x := <-c
	fmt.Println(x)
	y := <-c
	fmt.Println(y)
}

```
JavaScriptHack Hackフォルダ　オブジェクト指向編/Dom編

#JavaScript Hackとは
##前提
弱いなりにサバイバルしていくためのもの。きちんと学ぶことも必要だが
英語のようにお客さんに単語を並べて乗り切られ、残念な結果は避けたい。
経験としてDomとFormを押さえればいけるのではないかという見込みで
Hackを行っていく。オブジェクト指向は今回はさわりだけしか取り上げないことにする。

##概要
なぜJavaScriptをやるか？
→　今でも使ってるところは使っている。
→　裏ニーズとしておしゃれなフレームワークを学ぶためにもやっておいたほうがいい。
##事前知識
テンプレートリテラル
バッククォート
console.log(``名前: ${animal.name}``);
参考書籍　
JavaScript本格入門
https://www.amazon.co.jp/dp/B01LYO6C1N/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

##JavaScriptHack Hackフォルダ オブジェクト指向編
###コンテンツ
オブジェクト指向を学ぶ。
シラバスを作成する。
TakeAway
###オブジェクト指向を学ぶ。
Progate JavaScript Ⅳ
https://prog-8.com/languages/es6
###シラバスを作成する。
・オブジェクト
・クラス
・継承

##JavaScriptHack Hackフォルダ Dom編

###コンテンツ
Domを学ぶ。
ゲームを作成する。
最低限のCSSの知識を確認する
シラバスを作成する。

### DOMを学ぶ。
詳解JavaScript DOM編 (ドットインストール)　有料会員
https://dotinstall.com/lessons/basic_javascript_dom_v2
###  ゲームを作成する。
JavaScriptでスロットマシンを作ろう　(ドットインストール)　有料会員 
https://dotinstall.com/lessons/slot_js_v6
上記が難しい人のために旧を紹介しておきます。
https://dotinstall.com/lessons/slot_js_v3　有料会員 
https://dotinstall.com/lessons/slot_js　有料会員

###最低限のCSSの知識を確認する。
class = color
id = yamada
.color
'#yamada



### シラバスを作成する。
querySelector()
getElementById()
querySelectorAll()
addEventListener()
className
classList.add()
classList.remove()
classList.contains()
classList.toggle()
createElement()
appendChild()

関連ページ
JavaScriptHack Hackフォルダ　Form編
https://qiita.com/gina/items/3aa0174eda82532d68ea
Developerツールについて
https://developers.google.com/web/tools/chrome-devtools/javascript
https://ics.media/entry/190517/
【JavaScript】ネコ泣いちゃったゲーム作ってみた（遊び）

##ネコ泣いちゃったゲーム
MDNサイトの学習に沿って、オリジナルの簡単な動作物を作成しました。

※MDNサイト↓
https://developer.mozilla.org/ja/docs/Learn/JavaScript/First_steps/What_is_JavaScript

##HTML

```
<body>
  <h1>ネコの鳴き声</h1>
  <button id = btn1>ネコの鳴き声1</button>
  <button id = btn2>ネコの鳴き声2</button>
  <button id = btn3>削除</button>
</body>
```


##JavaScript
```
<script>
//①DOM操作
const btn1 = document.getElementById("btn1");
const btn2 = document.getElementById("btn2");
const btn3 = document.getElementById("btn3");

//②メソッドの作成。
//HTML内に要素を生成して、その中に"にゃん"を追加する機能
function createPara1(){
  const Para = document.createElement("p");
  Para.textContent = "にゃん";
  document.body.appendChild(Para);
}

//HTML内に要素を生成して、その中に"にゃ〜〜ん"を追加する機能
function createPara2(){
  const Para = document.createElement("p");
  Para.textContent = "にゃ〜〜ん";
  document.body.appendChild(Para);
}

//追加したParaを一つずつ削除する機能
function deletePara(){
  const element = document.querySelector("p");
  element.remove();
}

//③クリックした時にイベント発生
btn1.addEventListener("click",createPara1);
btn2.addEventListener("click",createPara2);
btn3.addEventListener("click",deletePara);

</script>
```
Splunk ドリルダウンでの条件分岐

小ネタ。作ったので。

```xml:drilldown_condition.xml
<form>
  <label>drilldown condition test</label>
  <fieldset submitButton="true" autoRun="true">
    <input type="time" token="field1" searchWhenChanged="true">
      <label></label>
      <default>
        <earliest>0</earliest>
        <latest></latest>
      </default>
    </input>
  </fieldset>
  <row>
    <panel>
      <table>
        <search>
          <query>| makeresults
| eval fieldA=md5(_time), fieldB=sha1(_time)</query>
          <earliest>$field1.earliest$</earliest>
          <latest>$field1.latest$</latest>
          <sampleRatio>1</sampleRatio>
        </search>
        <option name="count">20</option>
        <option name="dataOverlayMode">none</option>
        <option name="drilldown">cell</option>
        <option name="percentagesRow">false</option>
        <option name="refresh.display">progressbar</option>
        <option name="rowNumbers">false</option>
        <option name="totalsRow">false</option>
        <option name="wrap">true</option>
        <drilldown>
          <condition match="match(substr($click.value2$,1,3),&quot;^[0-9]&quot;">
            <set token="selected_sourcetype">$click.value2$</set>
            <link target="_blank">https://www.google.com/?q=$click.value2$</link>
          </condition>
          <condition match="match(substr($click.value2$,1,3),&quot;^[a-z]&quot;">
            <set token="selected_sourcetype">$click.value2$</set>
            <link target="_blank">https://www.virustotal.com/gui/search/$click.value2$</link>
          </condition>
        </drilldown>
      </table>
    </panel>
  </row>
</form>
```

- 中身は、テーブル表示で、`md5`と`sha1`の値で頭が`数字`か`アルファベット`かでリンク先を変更している。
- `<condition match="match(substr($click.value2$,1,3),&quot;^[0-9]&quot;">`
が条件式。
- `&quot;`は`"`なので、`if`でよく使う`match()`の構文そのもの。
- _else_　が使えるわけではないので、`case()`と同じく、一つ一つ条件を書いてあげる。
- なお、条件に漏れがあると、通常のドリルダウンの動作（クリックされた値で検索）になる。
- 最後あたり `<condition match="1==1">`を作ってデバッグというのもありかも
- 下記のrefのなかで`match="`の中が `$`　ではなくて　`'`で囲っていたけどどちらでもよかった。

reference: https://docs.splunk.com/Documentation/Splunk/latest/Viz/tokens
【Python】TypeError: 'WebElement' object is not iterable エラーが発生した時の対処法

#環境
macOS Catalina 10.15.3
Python 3.6.5 
selenium 3.141.0

#概要
pythonのseleniumで、Google検索結果のスクレイピングを行い
取り出した要素をforループで更にリストに抽出

#発生した課題
'WebElement' object is not iterable
訳：'WebElement'オブジェクトは反復可能ではありません

ここではforループを行った時に発生したエラーでしたので、要は
for i in xxx で参照元として指定している’xxx’は、繰り返し要素を取り出すことができませんよ。ということですね。

#サンプルコード
この際、seleniumuを使った前処理は割愛します。

```
title_list = []
link_list = []
i = 1
i_max = 2

while i <= i_max:
    w = driver.find_element_by_class_name(“x”)
    for elem in x:
         title_list.append(elem.find_element_by_class_name(‘y’).text)           
         link_list.append(elem.find_element_by_tag_name(‘a’).get_attribute('href')) 
```

上記のコードでエラー発生

```
TypeError: 'WebElement' object is not iterable
```

#原因
```
# 7行目のココ
w = driver.find_element_by_class_name(“x”)
```

.find_element では単一要素しか抽出されませんので、反復不可能というわけですね。

#解決法
```
# .find_elements…にしてください
w = driver.find_elements_by_class_name(“x”)
```

単一の要素抽出なのか、それとも複数必要なのかということは注意しながら書かなければいけませんね。
勉強になりました。

#参照
「PythonでGoogle検索タイトルとURL一覧を抽出してみた」
https://watlab-blog.com/2019/08/15/python-google-searchlist/
progate food.rb

require "./menu"

class Food < Menu
  attr_accessor :calorie
  
  def initialize(name:, price:, calorie:)
    super(name: name, price: price)
    self.calorie = calorie
  end
  
  def info
    return "#{self.name} #{self.price}円 (#{self.calorie}kcal)"
  end
  
  def calorie_info
    return "#{self.name}は#{self.calorie}kcalです"
  end
end
progate index.rb

require "./food"
require "./drink"

puts "日曜限定100円割引セール実施中！"

food1 = Food.new(name: "ピザ", price: 800, calorie: 700)
food2 = Food.new(name: "すし", price: 1000, calorie: 600)
drink1 = Drink.new(name: "コーラ", price: 300, amount: 500)
drink2 = Drink.new(name: "お茶", price: 200, amount: 400)

menus = [food1, food2, drink1, drink2]

index = 0
menus.each do |menu|
  puts "#{index}. #{menu.info}"
  index += 1
end

puts "--------------"
puts "メニューの番号を選択してください"
order = gets.chomp.to_i

selected_menu = menus[order]
puts "選択されたメニュー: #{selected_menu.name}"

puts "個数を入力してください(3つ以上で100円割引)"
count = gets.chomp.to_i

puts "お会計は#{selected_menu.get_total_price(count)}円です"
menu.rb

require "date"

class Menu
  attr_accessor :name
  attr_accessor :price

  def initialize(name:, price:)
    self.name = name
    self.price = price
  end
  
  def info
    return "#{self.name} #{self.price}円"
  end
  
  def get_total_price(count)
    total_price = self.price * count
    if count >= 3
      total_price -= 100
    end
    
    # if文を作成してください
    if count >= 1 && Menu.is_discount_day?
      total_price -= 100
    end
    
    return total_price
  end
  
  def Menu.is_discount_day?
    today = Date.today
    return today.sunday?
  end
end
C言語 POSIX ThreadでSleep Sort

ネタ的なソートアルゴリズムとして知られるSleep Sort。Qiitaでも様々な言語で実装した記事が公開されています。ということでマルチスレッドの練習も兼ねて、C言語のPOSIX Threadライブラリを使って実装してみました。

```sleepSort.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define N 10

void *sort(void *t){
	int n = *(int *)t;
	sleep(n);
	printf("%d\n", n);
	pthread_exit(NULL);
}

int main(void){
	int arr[N] = {2,7,10,6,4,5,8,3,9,1};
	pthread_t tid[N];
	for(int i=0; i<N; i++){
		if(pthread_create(&tid[i], NULL, sort, &arr[i])){
			fprintf(stderr, "error: pthread_create\n");
			exit(1);
		}
	}
	for(int i=0; i<N; i++){
		if(pthread_join(tid[i], NULL)){
			fprintf(stderr, "error: pthread_join\n");
			exit(1);
		}
	}
	return 0;
}
```
以下のようにコンパイル、実行できます。

```
$ gcc -pthread -Wall sleepSort.c 
$ ./a.out 
1
2
3
4
5
6
7
8
9
10
```
10秒かかりますが無事にソートされました。
Reactで{}(curly bracket or 中括弧 or 波括弧)をimportで使う理由

# 結論
ES6のexportには

1. Default Export
2. Named Export

の2種類が有り、Named Exportには{ } を付けないとimportできない。

に追加して 

1. ファイルからオブジェクト全体をimport 
2.  ファイルから**特定の**オブジェクトをimport

の2種類が有り、**特定の**オブジェクトをimportする際は{ }をつける。

# 内容
最近 reactを勉強し始めて、よく{ }(中括弧）でimportしたりしなかったりする状況が散見され、「どんな基準で付けたり付けなかったりするの。。。？」となった。

なので調べてみたらReactの話ではなく、まずES6の話だった。

通常、他のファイルで何か関数か変数を使いたい時は

```
export default App;
```
とexportするが、この場合はdefault exportされているので

```
import App from './path/to/App';
```
とimportできる。

一方でnamed exportは

```
export const A = 25;
```
とdefaultを使わずにexportされ、importする際には

```
import {A} from './path/to/A';
```
のようにする。

「ふむふむ、なるほどexportにdefault付けるか付けないかで違うのか～」となっている所に、ふと自分のコードを見ると、default付けているcomponentにも{ }を付けてimportをしているではないか。

~~「Why Japanese People!?　規則性ないじゃないか！」~~

更に調べると、どうやら
>Curly Braces are used to import single(specific) property, whereas the word without braces is import entire object form that file.

これは例えば

```
import React, { Component } from 'react';
```
てな感じで、

特定のオブジェクトをimportしたいときはそのオブジェクトに{ }をつけてやるとのこと。

なるほどね、解決！
めでたしめでたし

---
参考文献
[stackoverflow](https://stackoverflow.com/questions/41337709/what-is-use-of-curly-braces-in-es6-import-statement/41338672)
同じ名前の namespace とクラスを共存させる [Typescript]

# こんなときに

- {クラス名}.{なんとか} で呼び出したいけど、クラスのプロパティには直接含めたくない

# 実装

## クラス定義

```ts
export class User {
  constructor(
    private id: string,
    private name: string,
    private status: User.StatusMappings,
  ) {}
}
export namespace User {
  export enum StatusMappings {
    active = 1,
    inactive = 0,
  }
}
```

## 使ってみる

```ts
new User("deadbeaf", "test", User.StatusMappings.active)
```
【Day74】積み上げ日記

##学習内容
■カウントアプリ作成
■おみくじアプリ作成
・ランダムメソッド
■WebAPIを叩く

##学習ポイント
■ランダムメソッド
■HTML要素を取得するメソッド
・getElementById()
・getElementsByClassName()
・querySelector()
■WebAPIを叩く流れ
APIデータをfetchする→fetchしたデータをJSONにする

##参考記事
https://www.sejuku.net/blog/70581
私がこれからのMac miniに期待すること


[夢の記事](https://qiita.com/AKKYM/items/a4b094230f3e3afeb52c)の最後にも書きましたが、私がこれからのMac miniに期待することを書きたいと思います。

### ARM化反対

まず、ARM化は絶対にやめてほしい。Macのいいとことの一つであるbrewによる環境構築の楽さが消えてしまうと思います。省電力とかどうでも良いからARM化はやめて欲しいです。Ryzen化ならいいけど。

### M.2スロット

M.2 SSDを追加可能にしてほしい。パソコンってのは使ってくうちに大事なデータが増えていって追加の容量が必要になるものなのよ。買ってから2年後ぐらいにM.2 SSDを追加したいよ。

### オンボードグラフィックの追加

MacBookPro 16インチモデルみたいなオンボードグラフィックを追加したモデルをMac miniにも追加して欲しい。iMacみたいな分解も出来ないデスクトップパソコンは買わないし、Mac Proみたいな高すぎるパソコンは買えないのよ。GPU欲しかったらHackintoshしか選択肢ないのよ。

## 最後に

Mac miniは自分で分解して掃除が出来る最高のMacだと思っています。これからもみんなに愛される最高のMacのままでいて欲しいなぁ。

まあ、Mac miniを一度も所持したことないんだけど...
AWS SDKの戻り値をDynamoDBに格納する

```ruby
require 'aws-sdk'
sts = Aws::STS::Client.new
ddb = Aws::DynamoDB::Client.new
ddb.put_item({
  table_name: "anytable",
  item: sts.get_caller_identity.to_h.transform_keys(&:to_s).transform_values(&:to_s)
})
```
AWS SDKの戻り値は（ほぼ全て？）Struct型なので、そのままではテーブルに格納できません。ハッシュ化し、さらにハッシュのキーと値を文字列化することで格納できます。
[Swift]Admobの「ポリシー違反（インタースティシャル広告の導入における禁止事項）」に対応した

背景
---
初めて[Google Admob](https://admob.google.com/home/)を導入したアプリのリリースから約１ヶ月後、ポリシー違反のメールを受信した。
メール本文内に記載のポリシーセンターへのリンクを参照すると、「ユーザーが予期しないタイミングでの広告表示」のため対応するようにとのこと。
[ガイドライン](https://support.google.com/admob/answer/6066980)を確認すると、なるほど、確かに記載されている。
![ポリシー違反.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530745/1a6061a5-ec6c-ec41-3deb-24d1b64ef1e2.png)

違反内容の確認
---
ポリシーセンターでは、具体的にどの画面のどの操作のどの動きが違反しているとまでは記載されていない。
案内されるガイドラインを読み進めて違反ケースを一つ一つ確認し、該当するケースを自分で見極める必要がある。

今回のケースは[インタースティシャル広告の導入における禁止事項](https://support.google.com/admob/answer/6201362)の`予期しないタイミングでの表示`が該当した。
![予期しないタイミング.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530745/245a0d3c-6daf-1e7f-182c-6a269d554291.png)

対応
---
ガイドラインで解説されている通り
`アクション　→ 画面遷移　→ 広告表示`、から、`アクション　→ 広告表示　→ 画面遷移`
の動きに変更した。

再審査
---
アプリを修正しリリースを行った後、Google Admobに審査を行ってもらう必要がある。
Admobのポリシーセンター上で変更点を記載し、審査リクエストを送信する。

１週間以内には再審査を行う旨の自動応答メールを受信し、待つことになる。
が、今回は半日と待たずに再審査で問題がなかった旨のメールを受信し、違反ステータスが解除された。
numpy.ndarrayのforのスピードテスト

#1.概要
ndarrayをforするのはどの方法が速度が出るのか確認。
※ 何故かググっても出てこなかったのでとりあえずやってみた。

#2.結論
* to_listしてforが最速。
 * forよりto_listがボトルネック
 * to_listはやった時点でメモリコピーが走るんでその辺の考慮は必要。
* インデックスでの参照は遅い。

#3.詳細
## 3.1 測定内容と結果
np.zeros(50000000)に「測定項目」の方法で各値を取得し、かかった総時間を測定。
ndarrayをforすると遅いってさんざん言われてるけどインデックスが更に遅いのは知りませんでした。

|測定項目|関数名|結果[sec]|
|:-----------------|-----|------------------:|
|インデックス|test1|6.716|
|普通にfor|test2|3.723|
|to_listしてfor|test3|1.601|

## 3.2 使用したソースコード
```python
import numpy as np

import io
import cProfile
import pstats
from pstats import SortKey


def test1(target):
    # インデックスで取り出し
    for i in range(len(target)):
        target[i]

def test2(target):
    # 普通にfor
    for v in target:
        pass

def test3(target):
    # tolistで取り出し
    target = target.tolist()
    for n in target:
        pass

def run_all_test():
    target = np.zeros(50000000)
    test1(target)
    test2(target)
    test3(target)

def profile_it(func, *args, **kwargs):
    # funcをプロファイリングする

    pr = cProfile.Profile()

    pr.enable()
    func(*args, **kwargs)
    pr.disable()
    
    s = io.StringIO() 
    ps = pstats.Stats(pr, stream=s).strip_dirs().sort_stats(SortKey.CUMULATIVE) # 累積時刻でソート
    ps.print_stats(10) # 上位n件のみ
    print(s.getvalue()) # コンソール出力


if __name__ == "__main__":
    profile_it(run_all_test)


```

#3.3 プロファイル結果
* cumtimeが関数の実行時間です。
* to_listを使用してるtest3が高速。
 *  test3の1.601秒のうち、1.012秒がto_list。つまりforの時間は0.6秒程度。listのfor自体はndarrayの約6倍高速。

```
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.643    0.643   12.683   12.683 speed_test_ndarray_for.py:27(run_all_test)
        1    6.716    6.716    6.716    6.716 speed_test_ndarray_for.py:9(test1)
        1    3.723    3.723    3.723    3.723 speed_test_ndarray_for.py:14(test2)
        1    0.590    0.590    1.601    1.601 speed_test_ndarray_for.py:20(test3)
        1    1.012    1.012    1.012    1.012 {method 'tolist' of 'numpy.ndarray' objects}
        1    0.001    0.001    0.001    0.001 {built-in method numpy.zeros}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 {built-in method builtins.len}
```

# 4. 測定環境
* python: 3.7.4
* numpy: 1.17.4
LibreOffice で LaTeX を使えるようにする方法（Windows10）

![ant28.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646713/39b1c1df-7cc5-af8a-40bc-a16b732f3ee1.jpeg)
オープンソースの Office ソフトに、[LibreOffice](https://ja.libreoffice.org/) というものがあります。
Windows でも MacOS でも、Linux でも動く便利なやつです。

今回は Windows 環境にて、LibreOffice 上で LaTeX を使い、数式を入れ込めるようになる方法をまとめます。

## この記事を参考にできる方の対象

初心者すぎる内容だと思いますし、私も同環境での方法しか説明ができないので、
筆者と同じような状況の方はご参考にしてみてください。

1. OS は Windows10
2. 文書のレポートに、数式を入れてみたい
3. LaTeX をとりあえず触ってみたい

## まず、LibreOffice をダウンロード

下記のリンクからダウンロードとインストールをしてください。

LibreOffice
https://ja.libreoffice.org/

## TeXMaths の導入

SourceForge からダウンロードしました。

TeXMaths
https://sourceforge.net/projects/texmaths/files/
いろいろあるフォルダの一番最新のもの。
（わたしは、0.48.2　2020-04-12　を落としました。）
この落としたファイルはまだ動かすことができません。

## MiKTeX で TeX 環境を作る

これは、TeX の環境を構築するものみたいです。
Windows の場合は MiKTeX を使用します。

MiKTeX
https://miktex.org/2.9/setup
一番上の Basic Installer をダウンロードしました。
ダウンロード後、インストールしてください。

次に、dvisvgm をダウンロード
https://dvisvgm.de/
zipファイルが落とせます。
中の実行ファイルを起動すると勝手になにか動いてくれたような…（うろ覚えです）

## LibreOffice を起動

てきとうに文書ドキュメントを新規作成してみてください。
メニューバーに π やらのアイコンが出てきているので、
それをポチッとすると TeXMaths が実行できます。

**やったー！ TeX で数式がかけるようになったよ！**

# 参考
LibreOffice拡張機能　TeXMathsの紹介
https://www.slideshare.net/hibagonsan/20141124a-te-xmaths-42285088

hibagonsan さん、ありがとうございました。
[Swift]R.swiftで生成するViewControllerのinitにパラメータを渡す

背景
---
例によって、個人開発した[ScoreBox](https://apps.apple.com/jp/app/scorebox/id1489805521)という麻雀成績管理アプリからのネタ。

[iOS13ではStoryboardでもDIができる件について](https://qiita.com/shtnkgm/items/cad6f52c489612628fd4)を拝見し、せっかくなので[R.swift](https://github.com/mac-cain13/R.swift)を利用して実装しました。
リンク先でもメリットを記載されていますが、**プロパティのlet化**、この恩恵は非常に大きいです。


やったこと
---
- R.swiftの導入
- Storyboard上でViewControllerに`Storyboard ID`を登録
![IDを指定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530745/4156b729-91e5-a42f-2abe-eb15b3f66a77.png)

- 呼び出し元でViewControllerのインスタンス生成／表示

```swift
let gameDetailVC = R.storyboard.main().instantiateViewController(identifier: R.storyboard.main.gameDetail.identifier) { coder in
   // GameDetailViewControllerはプロパティに`let game`を持ち、initの引数に必須としている
    GameDetailViewController(coder: coder, game: game)
}
navigationController?.pushViewController(gameDetailVC, animated: true)
```
WSL2にしたらbrowsersyncが激重とおもったけど違った話

macと同じgulpプロジェクトは秒で表示されるのに、wsl2は10分かかる。
gulpfile.jsの書き方とかの問題じゃないような気がするのだが

# 【追記】
とおもっていたのだが、wsl2からlinuxネイティブになったのでlinuxローカルからのファイルへのアクセスは爆速だそうだ。そういえばwsl1のときはわざわざwindowsのディレクトリにシンボリックリンクを張っていたのを忘れていた。ドキュメントルートでgulpを実行したらマックと同じくらいのスピードで上がったなり
PHPで閲覧中のデバイスの画面サイズを返す。

下記サイトサンプルを修正、実行後リダイレクトしデバイスのwidthとheightを取得。
https://stackoverflow.com/questions/23239157/get-browser-width-using-php

````
get_screensize.php
<?php
session_start();
if(isset($_POST['width'])){
   $_SESSION['screen_size'] = array();
   $_SESSION['screen_size']['width'] = intval($_POST['width']);
   $_SESSION['screen_size']['height'] = intval($_POST['height']);
}


if(!isset($_SESSION['screen_size'])){
?>
<html>
<head>
<script>
function getSize(){
document.getElementById('inp_width').value=screen.width;
document.getElementById('inp_height').value=screen.height;
document.getElementById('form_size').submit();
}
</script>
</head>
<body onload='getSize()'>
<form method='post' id='form_size'>
<input type='hidden' name='width' id='inp_width'/>
<input type='hidden' name='height' id='inp_height'/>
</form>
</body>
</html>


<?php
}else{
//var_dump($_SESSION['screen_size']);
header('Location: http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/screensize_out.php');
}

?>

screensize_out.php
<?php
session_start();
echo "閲覧中のディスプレイサイズは下記の通りです！！<BR>";
   echo "width: ".$_SESSION['screen_size']['width']."<BR>";
   echo "hight: ".$_SESSION['screen_size']['height'];


?>
````
OpenCVSharpでマウスを使う

#概要
ちょっとした操作をマウスで行いたかった。さらに線や円などのプリミティブな図形も描きたかったので、OpenCVSharpを使ってみることにした。そこで引っ掛かったことを記す。
###不具合例
```C#:Program.cs
using OpenCvSharp;
  class Program
  {
    public static Mat img;
    static Point mousepos = new Point();
    static Scalar color = new Scalar(0, 255, 255);
    static void Main(string[] args)
    {
      img = new Mat(new Size(640, 480), MatType.CV_8UC3);
      using (Window win = new Window("OpenCV", img))
      {
        Cv2.SetMouseCallback("OpenCV", Win_OnMouseCallback);
        while(true)
        {
          Cv2.ImShow("OpenCV", img);
          int ret = Cv2.WaitKey(1);
          if (ret == 27) { break; }
        }
        Cv2.DestroyAllWindows();
      }
    }//End of Main

    private static void Win_OnMouseCallback(MouseEventTypes @event, int x, int y, MouseEventFlags flags, IntPtr userdata)
    {
      Console.WriteLine($"event: {@event}, (x, y)= ({x}, {y}), flags: {flags}");
      if (flags==MouseEventFlags.LButton)
      {
        mousepos.X = x; mousepos.Y = y;
        img.Circle(mousepos, 2, color);
      }
    }
  }
```
何の変哲もない。
しかしリリースモードでビルドして実行して、暫くすると
![20200531_err1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423419/9ae7d474-4b91-5eb1-8b55-38d6bcb631b7.png)
これは何のことだろう？デバッグモードでは出てこないけど・・・
ググると、C#のリリースモードはいろいろ最適化されてるから別コードと考えた方がよいとか、Releaseでもデバッグ用にログを取るとかいろいろ出てきた。でもこんな簡単なものなのに・・
しかもアンマネージってOpenCVのところ？？
###解決策
ようやく探し出せた
https://www.ipentec.com/document/csharp-error-delegate-must-be-kept-alive-by-the-managed-application
よく見るとWin_MouseCallBackはdelegate型になってない。staticで宣言されているけど、ガベージコレクタが回収してしまうようだ。ちゃんと確保して回収されないようにしてあげよう。差分だけ書かせてもらうと正しくは

```C#:Program.cs
    public static Mat img;
    static Point mousepos = new Point();
    static Scalar color = new Scalar(0, 255, 255);
    static MouseCallback mcb;  //追加
    static void Main(string[] args)
    {
      img = new Mat(new Size(640, 480), MatType.CV_8UC3);
      mcb=new MouseCallback(Win_OnMouseCallback); //追加
      using (Window win = new Window("OpenCV", img))
      {
        Cv2.SetMouseCallback("OpenCV", mcb);//変更 
        while(true)
        //以下略
```
この「ガベージコレクタが回収する」エラーは、IDEでデバッグしているときは出てこず、使い始めてしばらくすると出てくるのと、再現するのに時間がかかるので、だいぶ厄介だった。わかってみれば「型を合わせてメモリを確保する」をちゃんとするだけなのだが。C++のDLLを使うプログラムでは気を付けよう。
Node.jsでパスワードを暗号化 | mongoose , Express, MongoDB

`mongoose-bcrypt` をいれる

```Js
npm install mongoose-bcrypt --save
```

`mongoose.Promise` を読み込んだ

```js
mongoose.Promise = global.Promise;
mongoose.connect(config.database);
```

`.plugin(require('mongoose-bcrypt'),{ fields: ['password'] })` するだけでいい。

```js
// get mongoose.Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// make user model and export
module.exports = mongoose.model('User', 
  new Schema({
    firstName: String,
    lastName: String,
    password: String
  }).plugin(require('mongoose-bcrypt'),{ fields: ['password'] })
);

```

こんな感じで入ります

```
{
	"firstName" : "鈴木",
	"lastName" : "太郎",
	"password" : "$2a$10$RXa.tr.mKfCZ2AJuVPP4N.lbA9k7X/NRMcEjHnextX.ValzFVzMgi",
```

確認

```js
user.verifyPassword('入れたパスワードで確認')
```

## 備考

パスワードチェックではこうした。ダサすぎ！誰か改善案教えてください

```js
    app.post('/login', function(req, res) {
      User.findOne({email: req.body.mail}).then((user)=>{
        user.verifyPassword(req.body.pw).then(function(err){
          if(!err){
            console.log("パスワードが違います");
          }else{
            //email: パスワードは必ずユニークであること 
            // ***ダサい直したい
            User.findOne({email: req.body.mail}, function(err,obj) { 
                if(err){
                  console.log("エラーが発生しました");
                }
                res.json(obj);
            });
          }
        });
      });
    });
```

## 参考

http://ichi-bit.hateblo.jp/entry/2017/11/17/mongoose%E3%81%A7password%E3%82%92%E6%9A%97%E5%8F%B7%E5%8C%96%E3%81%97%E3%81%A6%E4%BF%9D%E5%AD%98%E3%81%97%E3%81%A6%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95
[Swift]複数のScrollViewのスクロールを同期する

背景
---

例によって、個人開発した[ScoreBox](https://apps.apple.com/jp/app/scorebox/id1489805521)という麻雀成績管理アプリからのネタ。

本アプリのコア機能となる成績管理の入力は表形式になります。
大きく分けると、**成績を蓄積する部分**、**合計値を表す部分**の2つ。
性質が異なるため１つの表での表現は難しく、今回は2つの表に分けることにしました。

なお、表のコントロールには[SpreadsheetView](https://github.com/kishikawakatsumi/SpreadsheetView)を利用させていただきました。
ありがとうございます。

悩んだ
---
表を分けるようにしたのはいいものの、
ScrollViewのスクロール検知はdelegateが紐づいている1つのViewでしか有効でないので、
AのViewをスクロールしたからといって、勝手にBのViewも一緒にスクロールはしてくれません。

そこで、AのViewのスクロールを検知したら、他のViewもスクロールを同期させる工夫が必要でした。

工夫した
---
- UIScrollViewDelegate
- NotificationCenter

を利用しました。

```swift
import UIKit
import SpreadsheetView

class GameDetailViewController: BaseViewController {
    // （A View）成績を蓄積する部分
    @IBOutlet weak var scoreSheetView: SpreadsheetView!
    // （B View）合計値を表す部
    @IBOutlet weak var sumSheetView: SpreadsheetView!

override func viewDidLoad() {
        super.viewDidLoad()

        // 表コントロールのScrollViewへ Delegate を紐付ける
        scoreSheetView.scrollView.delegate = self
        sumSheetView.scrollView.delegate = self

        // スクロール同期を実行する通知イベントを登録する
        NotificationCenter.default.addObserver(self, selector: #selector(receiveScrollNotification(notification:)), name: .tableScroll, object: nil)
    }

    // スクロール同期する
    @objc func receiveScrollNotification(notification: NSNotification) {
        guard let scrollView = notification.object as? UIScrollView else {
            return
        }
        
        // 先にスクロールしたViewのスクロール位置を、他のViewに追従させる
        if scrollView == scoreSheetView.scrollView {
            sumSheetView.setContentOffset(CGPoint(x: scrollView.contentOffset.x, y: sumSheetView.scrollView.contentOffset.y), animated: false)
        }else{
            scoreSheetView.setContentOffset(CGPoint(x: scrollView.contentOffset.x, y: sumSheetView.scrollView.contentOffset.y), animated: false)
        }
    }
}

extension GameDetailViewController : UIScrollViewDelegate {
    // あるViewのスクロールを検知したら、他のViewも一緒にスクロールするよう通知する
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        NotificationCenter.default.post(name: .tableScroll, object: scrollView)
    }
}
```

実際の画面
---
![20200531_022339.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530745/29e406d7-2100-e9bd-ef42-288fe27a0b75.gif)

その他
---
今回は横スクロールの同期だけでしたが、縦スクロールも同期可能です。
Googleドキュメントのダークテーマを作ってみた

# こんな人にオススメ
* 黒い背景じゃないと気がすまない
* 見出しをよく使う(使わない人は使ったほうがいいよ)
* かっこいいのがいい
* でもかわいさも欲しい
* 印刷はしない


# 本体
https://docs.google.com/document/d/1aFGgS_8nWL7ZPIHTso5IqyeUuCi7rQmbr3zx5r7T2y8/edit?usp=sharing
これ

# 使い方
コピーを作成して編集して使ってね
(ビジネス向けのG-suiteならテンプレート設定もできるよ)
OCPのBostion(踏み台)サーバーへ設定するFirewalldの設定

OCP 4.xを導入する際、面倒なFirewall設定をまとめてみた。

NICは以下の２つを想定
ens192,ens224

NICのZONE設定を変更
firewall-cmd --change-interface ens192 --zone=external --permanent
firewall-cmd --change-interface ens224 --zone=internal --permanent

ZONE変更の確認
firewall-cmd --get-active-zones


必要な穴あけを投入
firewall-cmd --add-port=80/tcp --zone=internal --permanent
firewall-cmd --add-port=443/tcp --zone=internal --permanent
firewall-cmd --add-port=6443/tcp --zone=internal --permanent
firewall-cmd --add-port=22/tcp --zone=internal --permanent
firewall-cmd --add-port=514/udp  --zone=internal --permanent
firewall-cmd --add-port=22623/tcp --zone=internal --permanent
firewall-cmd --add-service=dhcp --zone=internal --permanent
firewall-cmd --add-service=dns --zone=internal --permanent
firewall-cmd --add-port=80/tcp --zone=external --permanent
firewall-cmd --add-port=443/tcp --zone=external --permanent


isoやignファイルを設置するWebサーバーのポート番号
firewall-cmd --add-port=8008/tcp --zone=internal --permanent


投入の確認
firewall-cmd --list-all --zone=internal
firewall-cmd --list-all --zone=external


マスカレード設定を投入（すでに入っている場合あり）
firewall-cmd --zone=external --add-masquerade --permanent


設定の反映
firewall-cmd --reload


6443,22623,8008をhttpとしてselinuxへ登録
semanage port -a -t http_port_t -p tcp 6443
semanage port -a -t http_port_t -p tcp 22623
semanage port -a -t http_port_t -p tcp 8008


投入の確認
semanage port -l|grep http_port
dockerのインストールで「"C:\Program Files\Docker\Docker\installationmanifest.json" が見つからない」エラーが出たときの対処

# 発端
駆け出しのソフトウェアエンジニアだったころに埋めた爆弾の話です。

Dockerを興味本位でインストールし
↓
ちょっと触って適当にアンインストール
↓
その後、改めてDockerをインストールしようとしてエラー発生

という事象が起こりました。

この「適当にアンインストール」のやり方がまずかったので、自分の教訓として残します。

# 環境
* windows10

# 問題
「"C:\Program Files\Docker\Docker\installationmanifest.json" が見つからない」
といった内容のエラーが出ていた．
（エラー内容をちゃんと残していませんでした，ごめんなさい）

# 推測される原因
Dockerを正規の手段（アンインストーラー）以外でアンインストールをした．

# 対処方法
Dockerのサクセスセンターに対処法がありました．
以下説明はこちらのトラブルシューティングの日本語訳です、こちらのおかげで対処できました．

[Dockerサクセスセンター - Docker.For.Win - Install fails on installationmanifest.json](https://success.docker.com/article/dockerforwin-install-fails-on-installationmanifestjson
)

# 注意

この対処方法はレジストリを編集します．というかゴッソリ削除します．
実行は自己責任でお願いいたします．

# 対処方法

1. 実行中のDockerプロセスをKillする

2. レジストリエディター(Regedit)を実行します
 Win + r で検索窓を開き，「regedit」で開きましょう．

3. レジストリのバックアップを取ります

4. レジストリエディターの中で以下の階層へ移動します
`Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall`

5. 「Docker for Windows」や「Docker Desktop」のようなDockerに関するレジストリを全て削除します
**※目的以外の項目は削除しないように注意** 

6. Dockerのインストーラを起動します．これでインストールできたら成功です

# あとがき
生半可な知識でファイルやディレクトリの削除は行っちゃだめですね．反省．
Dockerを使った軽量なFastAPIの開発環境を構築

## はじめに
最近FastAPIを使う機会がよくあり，Dockerでサクッと構築して使い捨てしたかったので
メモとして軽量で構築する方法を残したいと思います．

## 準備
- Docker及びDocker Composeが使える環境

```bash:バージョン
$ docker --version
Docker version 19.03.8, build afacb8b7f0
```

- ファイル構成はこんな感じにします

```bash:ファイル構成
.
├── Dockerfile
├── docker-compose.yml
├── main.py
└── requirements.txt
```

## ソース
ここからcloneできます
https://github.com/sattosan/sample-fastapi-alpine

### Dockerfile
alpineベースで作っています

```dockerfile:Dockerfile
FROM python:3.8-alpine

WORKDIR /app

COPY requirements.txt .
# コンテナ内で必要なパッケージをインストール
RUN apk add --no-cache build-base \
 && pip install --no-cache-dir --trusted-host pypi.python.org -r requirements.txt \
 && apk del build-base

COPY main.py .
EXPOSE 8000
# FastAPIを8000ポートで待機
CMD ["uvicorn", "main:app", "--reload", "--host", "0.0.0.0", "--port", "8000"]
```

### Docker Compose

```yml:docker-compose.yml
version: "3.0"

services:
  # FastAPI
  api:
    container_name: "api"
    build: .
    restart: always
    tty: true
    ports:
      - 8000:8000
```

### 必要なパッケージをまとめています

```txt:requirements.txt
uvicorn
fastapi
```

### サンプルコード
FastAPIの[ドキュメント](https://fastapi.tiangolo.com/)にあるサンプルコードを用意しました

```python:main.py
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root():
    return {"Hello": "World"}
```

## 実行

```bash
$ docker-compose up -d --build
```

## Docker Imageサイズの確認

- alpineベースのImageサイズ

```bash
docker images | grep api
latest              bff0158b61ca        29 minutes ago      275MB
```

- 本家のImageサイズ

[本家様](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker)を参考に構築した結果です

```bash
$ docker images | grep api
latest              878110f2207f        11 seconds ago      1.02GB
```

本家に比べて3.6倍軽減出来たことがわかります

## 動作確認
FastAPIで生成したAPIはSwaggerで自動的にドキュメント化されています

### Swaggerで見てみる
`ドメイン/docs`にアクセスするとドキュメントを見ることが出来ます

http://localhost:8000/docs

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130670/6d4c1c40-5139-0707-209c-bf455867c490.png)


### API叩いてみる
curlで叩くとこんな感じで返って来ます

```bash:結果
$ curl localhost:8000
{"Hello":"World"}
```

## おわりに
今回はalpineベースで軽量な開発環境を構築してみました．

本家より3.6倍軽量になるので，使い捨てには十分な環境だとは思います．
最近ではNetflixを始め様々なプロジェクトでFastAPIが使われ始めているので，
まだ使っていない人は是非使って見てください！

- Netflix製OSS：https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072

## 参考サイト
- 本家様：https://fastapi.tiangolo.com/