OmniAICreator/Qiita-1.07M huggingface dataset:
Laravel環境構築時のエラー解決 Mac

# エラー内容
```
$ composer global require laravel/installer

Changed current directory to /Users/ooshiroippei/.composer
Using version ^3.1 for laravel/installer
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for laravel/installer ^3.1 -> satisfiable by laravel/installer[v3.1.0].
    - laravel/installer v3.1.0 requires ext-zip * -> the requested PHP extension zip is missing from your system.


Installation failed, deleting ./composer.json.
```

#ext-zipが必要

重要なエラー箇所を和訳すると、
「laravel/installer v3.1.0にはext-zipが必要です。リクエストされたPHP拡張zipがシステムにありません」と書かれている。

# 原因
Macに最初から入っているPHPにはzipのサポート機能がないためエラーが起こっていた。

# 解決策
これは改めてPHPを入れ直すことで解決できる。

①MacにPHPを再インストールするには「Homebrew」を使う。
こちらを参考。
https://awesome-linus.com/2019/08/17/mac-homebrew-install/

②PHPをインストールする

```
//HomeBrewのバージョン確認まで終わったらインストール
$ brew install php

//zipがサポートされているか確認
$ php --ri zip

//Laravelインストール
$composer global require laravel/installer
```
#各エラー対策

###Extension 'zip' not present.とエラーが出た場合

```
$ brew link php
```

### brew link phpでエラー
Linking /usr/local/Cellar/php/7.4.7... 
Error: Could not symlink sbin/php-fpm
/usr/local/sbin is not writable.

```
$brew doctor

Warning: The following directories do not exist:
/usr/local/Frameworks
/usr/local/sbin

You should create these directories and change their ownership to your account.
  sudo mkdir -p /usr/local/Frameworks /usr/local/sbin　//実行
  sudo chown -R $(whoami) /usr/local/Frameworks /usr/local/sbin　//実行

Warning: You have unlinked kegs in your Cellar.
Leaving kegs unlinked can lead to build-trouble and cause brews that depend on
those kegs to fail to run properly once built. Run `brew link` on these:
  php

Warning: /usr/bin occurs before /usr/local/bin
This means that system-provided programs will be used instead of those
provided by Homebrew. The following tools exist at both paths:

Consider setting your PATH so that /usr/local/bin
occurs before /usr/bin. Here is a one-liner:
  echo 'export PATH="/usr/local/bin:$PATH"' >> /Users/user/.bash_profile　
  rake
  bundle
  tidy
  sqlite3
  bundler
  rails

//各エラー項目に出ているコマンドを実行していく。

$sudo mkdir -p /usr/local/Frameworks /usr/local/sbin
$sudo chown -R $(whoami) /usr/local/Frameworks /usr/local/sbin
$echo 'export PATH="/usr/local/sbin:$PATH"' >> /Users/user/.bash_profile
//パスを通したあとは必ずsourceで際読み込み
$source ~/.bash_profile

//バージョンを確認
$php -v

//zipを確認
$ php --ri zip

zip

Zip => enabled
Zip version => 1.15.6
Libzip headers version => 1.7.0
Libzip library version => 1.7.1

//Laravelインストール
$composer global require laravel/installer
```
cudart64_101.dllが見つからない問題

#何の記事？
Windows10にtensorflow-gpu 2.2とCuda 10.2をインストールした後、tensorflowをインポートしたときにcudart64_101.dllが見つからないというエラーが出る問題に対する対策です。

```
W tensorflow/stream_executor/platform/default/dso_loader.cc:55] Could not load dynamic library 'cudart64_101.dll'; dlerror: cudart64_101.dll not found        
2020-06-23 19:58:39.209335: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.
```

#解決できた方法

Windows(C:) > Program Files > NVIDIA GPU Computing Toolkit > CUDA > v10.2 > binを開き、cudart32_102.dllとcudart64_102.dllの2つのファイルがあることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620139/6bacad76-2bf1-af85-f445-e7451b6c86e5.png)


この2つのファイルを、cudart32_101.dllとcudart64_101.dllに書き換えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620139/773120c0-7747-5b9c-30f0-01748af9f07f.png)

これだけです。

#参考サイト
https://blog.csdn.net/weixin_44271141/article/details/106200251
中国語のサイトですが、google翻訳のおかげで普通に読めました。便利な時代ですね！
Ruby Silverに合格(2020年6月)したので、まとめてみます。

# スペック
- 非ITエンジニア
- Rubyはプログラミングスクールで学習
- IT系の資格はITパスポートのみ  

　ITエンジニアになるためにプログラミングスクールに通い、二ヶ月半程RubyやRailsを学んでいたので、初学者ですが独学ではありません。


# 受験対策の教材
- ［改訂2版］Ruby技術者認定試験合格教本（Silver/Gold対応）
- [Rubyがミニツク/
 Ruby技術者認定試験（Silver）対策問題集](http://www.minituku.net/courses/1049510743/contents/775230600.html)
- [Ruby技術者認定試験一問一答](https://ruby1mon1tou.com/)
- [DIVE INTO EXAM](https://exam.diveintocode.jp/exam)
- [模擬問題集PDF(Silver試験用)](https://gist.github.com/sean2121/945035ef2341f0c39bf40762cd8531e0)
- [RubyExamination](https://rex.libertyfish.co.jp/)
- [Wandbox](https://wandbox.org/)（オンラインコンパイラ）


　Ruby2.1以下ではエラーになり、2.2以上ではエラーにならないコード出てくるので、手軽にバージョンを切り替えられるWandboxを使うといいかもしれません。

# 勉強方法
　Rubyをスクールで学んでいたので、ある程度の基礎知識はありました。そのため「Rubyがミニツク/入門コース」と「Ruby技術者認定試験合格教本（以下、教本）」を１回読んで基礎知識を広めてから、練習問題に取り掛かりました。

　練習問題のレベル感や解説は、以下のように感じました。

- やさしい／丁寧
 - 教本の練習問題
 - Rubyがミニツク
 - Ruby技術者認定試験一問一答
- ふつう
 - 模擬問題集PDF(Silver試験用)  
 - DIVE INTO EXAM
- むずかしい
 - RubyExamination

　やさしいは、解説が丁寧だったと感じたので、間違えたところの理解がしやすかったです。

　ふつうは、やさしいに比べて解説文が短かったので、教本の読み直しやぐぐったりコードを打つ回数が増えました。

　むずかしいは、５回やって１〜２回目は不合格、３〜５回目は合格でした。Goldの問題も含まれているらしいので難しく感じましたが、理解を深めるためにやって損はないと思います。

# 勉強の振り返りと反省
　コードの書き方やメソッドの種類等、スクールの学習以外で知識を吸収出来たのがとても良かったので、Ruby初学者の目標としてはSilverを取得するのはアリだと思いました。
　しかし、やるからには100点狙おうと思って勉強したのはよくなかったと思います。実務で使わない内容も多いらしいので、アプリを作る時に知っておくと便利だなと思ったのはきちんと理解し、使わなさそうなのは深掘りする必要はなかったかなと思いました。

# Ruby Silverについて
- 「[Ruby Association Certified Ruby Programmer Silver version 2.1](https://www.ruby.or.jp/ja/certification/examination/)」が正式名称らしいです。
- 終了後、即採点されてその場で「合格」の文字が出るので、履歴書にすぐに取得資格として書く事が出来る。
- [ここ](https://proengineer.internous.co.jp/content/columnfeature/11659)を読むとRuby SilverはITパスポートと同じレベル感なので、資格と考えるなら弱いのかもしれません。
- Rubyの知見は広がり深まりましたが、Rubyエンジニアの方曰く実務で使う内容は少ないとのことです。
【VBA🔰】文字を出そう

#はじめに
VBAをほとんど触ったことなかったが、コマンドボタンを押したら文字が出てくるマクロを、VBAで作成することにした。
完成系はこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/7b0291ef-3e85-ed5e-97c4-89f1c08bb101.png)

#作り方
そもそもの[開発タブを出すやり方。](https://office-hack.com/excel/development-tab/)

開発>挿入>フォームコントロールの一番左端を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/6f6a75ec-ffca-e8d3-0f86-5e814ac5e6b5.png)

ボタンを好きな大きさまでスクロールしたら、マクロ登録のポップアップが出てくる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/d1a0202c-1f4e-8e11-8d04-0ecc472b56d0.png)

好きなマクロ名にし、マクロの保存先を変更したければして、OKを押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/7ac3d4e1-a6a9-a2df-a49f-cae387c31288.png)


ボタンが出てくる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/c0a8b222-172a-892b-4b3c-696177bea4ac.png)

ボタン名を変えるため、テキストの編集を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/f58d491f-b966-5994-3d97-dc6d4a35a857.png)

ボタン１を消去して、ボタン名を入力。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/ee033c65-5a88-9f11-4207-f78c7eb33e8f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/299a079f-ecd4-3f8b-8f16-8870bfee4294.png)

マクロの登録を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/10c6358e-e273-ec15-72e4-4b7b36415f94.png)

ポップアップが出てきたら、新規作成をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/9bccdedf-a3de-4fff-81f2-191f85709023.png)

Microsoft Visual Basic for applicationが表示されるので、Sub　○○()とEnd Subの間にTabキーを押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/9b4883c2-5ef8-ceea-7311-8cbb1705d682.png)

ActiveCell.FormulaR1C1 = "○○"を入力する。（○○に入力したい文字を入れる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/1dcd6c5d-39fc-1e14-5bd0-89adbb7d5384.png)

エクセル画面に戻り入力したいセルを選択してボタンを押すと、文字がでる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/7b0291ef-3e85-ed5e-97c4-89f1c08bb101.png)

初心者のため、これよりもっとわかりやすい・効率的な方法があるかもしれませんm(_ _)m予めご了承ください。

参考
https://www.moug.net/vba/beginners/exvba016-1.html
GraphQLについてまとめてみた

# GraphQLとは
Facebookにより開発された、APIのためのクエリ言語であり、既存のデータを使用しクエリを実行するためのランタイム
GraphQLは、API内のデータの完全で理解可能な説明を提供し、クライアントに必要なものだけを正確に要求する力を与え、APIの長期的な発展を容易にし、強力な開発者ツールを有効にする (翻訳)
[GraphQL](https://graphql.org/)

### クエリ言語とスキーマ言語
GraphQLは、一般的にクエリ言語とスキーマ言語から構成される
クエリ言語(フロント側)は、GraphQL APIのリクエストのための言語であり、データ取得に関連するquery、データ更新に関連するmutation、サーバサイドからのイベント通知を行うsubscriptionの３種類がある
一般的にはqueryとmutationを利用する

スキーマ言語(サーバー側)は、GraphQL API の仕様を記述するための言語であり、記述したスキーマに従ってレスポンスを生成する

|  | REST | GraphQL |
| -------- | -------- | -------- |
| 取得     | GET    | Query   |
| 作成 | POST | Mutation |
| 更新| PUT | Mutation |
| 削除 | DELETE | Mutation |
(GraphQLはQueryもMutationもPostでやりとりをしているが、わかりやすいようにRESTに合わせている)

### フィールド

クエリで取得できるフィールドとして、スカラタイプとオブジェクトタイプの２種類が存在する
GraphQLでは、以下の５種類に対応している
- Int
- Float
- String
- Boolean
- ID (String)

また、オブジェクト対応は1つ以上のフィールドを含んだグループで、JSON
の入れ子として表現される

### エンドポイント

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434619/d60a65ef-7ad4-4f6a-d0bb-f83a207bdc34.png)

### GraphQLのサーバー側の処理の流れ
1. スキーマ等の設定
2.  query/mutationの判別
3. variables(input)が必要ならそれの判定
4. query/mutationの各リクエストに対するresolverの割り当て
5. resolverで、細かい処理、値の返却
6. 要求返却値に対しての処理

などなど、全て実装する必要がある
→  手動での実装は辛い　
→  gqlgenなど利用して、ボイラープレートコードを自動生成

### 簡単な例

```scheme:schema
type Query {
    docs: [Document!]!
}
type Document {
    id: ID!
    title: String!
    description: String!
    file: String!
}
```

このスキーマに対して、クエリを書くとすると、

```schema:query
query {
    docs {
        id
        title
    }
}
```

となる。これは、docsのidとtitleを取得するという意味になる。これにdescriptionやfileなどの情報が欲しい場合は、そのように記述することでデータを取得することができる。
また複数のschemaに対しては、

```scheme:schema
type Query {
    user(username: String!): User!
}
type User {
    id: ID!
    username: String!
    password: String!
    email: String!
}
```

```schema:query
query {
    user(username:"your name") {
        id
        username
        email
    }
    docs {
        id
        title
        description
    }
}
```

のように、複数のresolverに対してqueryを投げることができ、リクエストの回数を減らすこともできる

### メリット
- 必要な情報しか通信が行われない
- エンドポイントが1つですむ
- リクエストの回数を減らすことができるかも
- 型の検証を行いながらリクエストできる
- バックエンド側の調整なしに、フロント側で情報を選択し、取得することができる

### デメリット
- サーバー側の処理の実装が難しい
    - スキーマの全てのパターンの実装が必要とになってくる
    - スキーマを元に、自動で枠組みを生成してくれるライブラリなどを利用する場合もある
        - gqlgenやgraphql-goなど
- データのキャッシュがめんどくさい
    - RESTのキャッシュは、エンドポイントに応じてキャッシュの処理を行う
    - GraphQLの場合、一意のIDを定義し、正規化されたキャッシュを構築する。クライアントが構築されたオブジェクトを参照するクエリを発したら、キャッシュを返すという仕組みになっている

###備考
間違っている内容や追加指摘など、ございましたら教えていただけると幸いです。
AOJ 1350 There is No Alternative

##問題
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1350
##見た感じ
最初はループができたときにそのループに同じ重さの辺があれば、減らすっていうので行こうとしたけど、間に合わない（し、うまく実装できそうにない）。
求める辺は最小全域木に含まれるので、全体の最小全域木を求めて、その各辺について、それをとりのぞいたグラフの最小全域木を求めて、総重量が変われば、どの最小全域木にも含まれる辺に足していく。
辺を減らすと、最小の総重量は変わらんor増える。もし増えたとすると、その辺を含まない全域木は元の最小全域木にはなりえないので、これで行ける。
##解法
最小全域木を求めてその各辺を取り除いたグラフの最小全域木を求めて比較。
##ソースコード
```c++
struct uftree{
    int cou;
    vector<int> parent;
    vector<int> rank;
    vector<int> _size;
    uftree(int &n){
        init(n);
    }
    void init(const int &n){
        parent=vector<int>(n);
        rank=vector<int>(n,0);
        _size=vector<int>(n,1);
        cou=n;
        rep(i,n){
            parent[i]=i;
        }
    }
    int root(const int &i){
        return parent[i]==i?i:parent[i]=root(parent[i]);
    }
    bool same(const int &i,const int &j){
        return root(i)==root(j);
    }
    void merge(int i,int j){
        i=root(i);j=root(j);
        if(i==j)return;
        cou--;
        if(rank[i]>=rank[j]){
            parent[j]=i;
            _size[i]+=_size[j];
        }else{
            parent[i]=j;
            _size[j]+=_size[i];
        }
        if(rank[i]==rank[j])rank[i]++;
        return;
    }
    int count(){
        return cou;
    }
    int unitsize(int i){
        return _size[root(i)];
    }
};
const int N_MAX=500;
int n,m;
vint w;
vector<ppint> sd;

void Main(){
    int x=0,y=INF10,z=1;
    
    //入力
    auto comp=[](int &i,int &j){
        return sd[i]>sd[j];
    };
    cin>>n>>m;
    rep(i,m){
        cin>>x>>y>>z;
        sd.pb({z,{x-1,y-1}});
    }
    sort(sd.begin(),sd.end());
    //処理
    uftree tree(n);
    int count=0,res=0;
    ll score=0,opt=0,ans=0;
    rep(i,m){
        ppint now=sd[i];
        if(tree.same(now.second.first,now.second.second))continue;
        count++;
        tree.merge(now.second.first,now.second.second);
        opt+=now.first;
        w.pb(i);
        if(count==n-1)break;
    }
    rep(i,n-1){
        score=0;
        tree.init(n);
        count=0;
        rep(j,m){
            ppint now=sd[j];
            if(tree.same(now.second.first,now.second.second)||j==w[i])continue;
            count++;
            tree.merge(now.second.first,now.second.second);
            score+=now.first;
            if(count==n-1)break;
        }
        if(score!=opt){
            res++;
            ans+=sd[w[i]].first;
        }
    }
    //出力
    cout << res<<' '<<ans <<endl;
}

int main(){
    cin.tie(nullptr);
    cout<<fixed<<setprecision(12);
    Main();
}
```
ProgressiveGANの生成画像を自分好みで質の高いものに変える方法

#1.はじめに
　通常、**学習済みGANモデルの生成画像**は、**好みの画像、嫌いな画像、破綻した画像**が混在していて、そのままでは**鑑賞に耐えません。**そこで、今回は手軽にGANの生成画像を**自分好みで質の高いものに変える方法**をご紹介します。

　今回使うGANの学習済みモデルは、[**TF-Hub Progressive GAN**](https://www.tensorflow.org/hub/tutorials/tf_hub_generative_image_module) です。なお、コードは Google Colab で作成し Github に上げてありますので、自分でやってみたい方は、この[**「リンク」**](https://github.com/cedro3/ProgressiveGAN/blob/master/Find_your_favorite.ipynb)をクリックし表示されたシートの先頭にある**「Colab on Web」**ボタンをクリックすると動かせます。

#2.どうやるの？
　学習済みのGANモデルは、**入力するベクトルと出力画像は１対１で既に決まっている**ので、改造できません。ではどうするか。入力するベクトルの方を変えます。

　GANモデルにランダムベクトルを入力して画像生成した時に、**破綻した画像や自分が嫌いな画像**がある場合は該当するベクトルを**マイナスベクトル**に蓄積し、**自分の好みの画像**がある場合は該当するベクトルを**プラスベクトル**に蓄積します。

　そして、GANモデルに入力する次のベクトルは、**ランダムベクトル＋プラスベクトルの平均ーマイナスベクトルの平均**とします。これを繰り返すことで、あーら不思議、GANの生成画像は**自分好みで質の高いものに変身**して行きます。

#3.実装します
　最初に、ライブラリーのインストール及びインポート、関数定義、モデルのダウンロードを行います。詳細は、google colab を参照下さい。

　まず、初期化します。

```python
#　学習の初期化
tf.random.set_seed(80)  
vectors = tf.zeros([5,512])
plus_vector = tf.zeros([1,512])
minus_vector = tf.zeros([1,512])
```

　google colab の **Form機能**を使っていますので、初期状態ではコードが見えませんが、UIをクリックするとコードを見ることが出来ます。操作をするには、初期状態の方がやりやすいです。

```python
#@title please, you change the selected action if you need. 
vec_0 = 'nothing' #@param ['plus', 'nothing', 'minus']
vec_1 = 'nothing' #@param ['plus', 'nothing', 'minus']
vec_2 = 'nothing' #@param ['plus', 'nothing', 'minus']
vec_3 = 'nothing' #@param ['plus', 'nothing', 'minus']
vec_4 = 'nothing' #@param ['plus', 'nothing', 'minus']
vec = [vec_0, vec_1, vec_2, vec_3, vec_4]

for i in range(len(vectors)):
    if vec[i] == 'plus':
      plus_vector = tf.concat([plus_vector, tf.reshape(vectors[i],[1,512])],axis=0)

    if vec[i] == 'minus':
      minus_vector = tf.concat([minus_vector, tf.reshape(vectors[i],[1,512])], axis=0)

print('number of plus_vector = ', len(plus_vector)-1)
print('number of minus_vector = ', len(minus_vector)-1)

plus_vector_mean = tf.reduce_mean(plus_vector, axis=0) # plus_vectorの平均をとる
minus_vector_mean = tf.reduce_mean(minus_vector, axis=0)  # minus_vectorの平均をとる

vectors = tf.random.normal([5, 512])  # ランダムベクトル取得
vectors = vectors + plus_vector_mean - minus_vector_mean  # ベクトルの補正
display_images(vectors)
```
　**Form機能**によって、変数 **vec_0〜vec_4** には **UIで選択した文字列** ('plus', 'nothing', 'minus')が入ります。その文字列が **'plus'** ならば該当するベクトルを**plus_vector**に蓄積し、**'minus'** ならば該当するベクトルを **minus_vector** に蓄積します。後は、`tf.reduce_mean()`で平均を取り、ランダムベクトルに足したり引いたりするだけです。 

　**初回は何も設定をいじらずコードを実行します**。**２回目以降**、生成した５つの画像を見て、自分の判断で**マイナスベクトルに入れるのか**(minus)、**プラスベクトルに入れるのか**(plus)、**何もしないのか**(nothing)を決めて、**設定を変更**してから**コードを実行**します。これを何回も繰り返します。

![スクリーンショット 2020-06-23 18.29.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/6f317188-2d92-15cc-ded5-7ba5f372df42.png)

　表示しているのは、十数回ほどやってみた結果です。UIは初期状態のまま実行しています。プラスベクトルを５つ（自分の好みの女性）、マイナスベクトルを８つ（破綻した画像）選んだ結果の画像です。確かに、割りと自分好みの女性ばかりになっていますね(笑)。

#4.追加
　追加で、**StyleGAN2版**のコードをGoogle_colabで作成し、[**Github**](https://github.com/cedro3/StyleGAN2/blob/master/Find_your_favorite.ipynb) に上げてありますので、こちらの方も良かったら試してみて下さい。
TensorFlow2の動作確認用のコードサンプル（非チュートリアル）

# インストール直後にやるべき動作確認

TensorFlowをインストールしたあと、動作確認に使うコードのサンプルを紹介します。

- バージョン確認だけだと、学習させたときにエラーが出ないか、GPUを使っているかなどの確認ができない。
- チュートリアルだと長過ぎる(というかコピペできるように紹介してない)ことが多い。

ので、簡単な動作確認として、バージョンとGPU確認、最低限の学習をするコードを書いています。

```py
import numpy as np
import tensorflow as tf

print(tf.__version__)

gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
    logical_gpus = tf.config.experimental.list_logical_devices('GPU')
    print("Physical GPUs: {}, Logical GPUs: {}".format(len(gpus), len(logical_gpus)))
else:
    print("CPU only")

x = np.arange(-1, 1, 0.0001)
y = 0.8 * x + 0.2

model = tf.keras.Sequential([tf.keras.layers.Dense(1, activation=None)])
model.compile("sgd", "mse")
model.build(input_shape=(0,1))
model.summary()
model.fit(x, y, epochs=5)

print("ground truth: 0.8, 0.2")
print("estimated: ", model.variables[0][0,0].numpy(), model.variables[1][0].numpy())
```

バージョンやGPUの情報がTensorFlowのログに紛れて見にくいので、必要に応じて改行とかを入れてください。

dockerを使っていたりすると、GPUの設定を間違えやすいので、GPUが認識されているかはしっかり確認しましょう。
学習中に`nvidia-smi`でGPUが使われているかの確認もしておきましょう。
学習が始まるとGPU-UtilとMemory-Usageが増えて、学習が終わるとGPU-Utilだけ下がり、Memory-Usageはそのままになるはずです。

学習については、$y = ax + b$の$a(=0.8)$, $b=(0.2)$を線形回帰していて、`estimated`として近い値を求められていればOKです。
HackerRankのExceptional Server問題について(C++)

##Exceptional Server問題
を解いていたら、ハマったので備忘録として書きます。

##`cerr`でエラーを出力したら怒られた
標準出力の結果のみを確認しているみたい。
実際のコードは下記の通り。(ネタバレ注意)
`cerr`を`cout`にしたら正解になりました。
他のコンテストでも当てはまりそうだから、勉強になりました。

```cpp
try
        {
            auto temp = Server::compute(A, B);
            std::cout << temp << endl;
        }
        catch (const std::bad_alloc &e)
        {
            std::cerr << "Not enough memory" << '\n';
        }
        catch (const std::exception &e)
        {
            std::cerr << "Exception: " << e.what() << '\n';
        }
        catch (...)
        {
            std::cerr << "Other Exception" << endl;
        }
```

##mac環境だと、bad_alloc例外が出ずkillされる。
```
2
-8 5
1435434255433 5
```
問題のサンプル入力のような物を私の環境で入力すると、`bad_alloc`を返しませんでした。
オーバーコミットという仕組みが働いているらしく、`bad_alloc`ではなく`kill`されてしまう、、、。
(私の環境は、`visual stdio code 1.46.0,Mac OS 10.15.4,clang:Apple clang version 11.0.3 (clang-1103.0.32.29)`です)
windowsだと`bad_alloc`を返してくれるらしい。
参照:[大きなサイズの配列を確保する際にエラーがでないことと、macOS上でコードの挙動が変わること。](https://teratail.com/questions/271406)

私の調べた限りだと、`bad_allc`を出すためにはオーバコミット機能を止めるしかないみたいです。(自分では確かめてない)
[c++ bad_alloc exception not catched](https://stackoverflow.com/questions/51674575/c-bad-alloc-exception-not-catched)
git pushで毎回ユーザー名とパスワードを入力を回避する方法 - SSH接続

Cloud9から`git push`するのに
毎回ユーザー名とパスワードを要求されるをなんとかしたくて調べてみた
（以下記事作成者に感謝）

[git パスワード を毎回聞かれる問題の解決方法 - Qiita](https://qiita.com/rorensu2236/items/df7d4c2cf621eeddd468)

一度ローカル環境のターミナルで設定してみて
Cloud 9から`push`してみるも認証がうまく行かず

鍵の登録はデバイスごとにする必要があります

ローカル環境で設定済みでも、
同じ手続きを再度Cloud9上で行うとSSH接続可能になりました

認証鍵の仕組みは把握していましたが
鍵？という方はこちら

[GitHubでssh接続する手順~公開鍵・秘密鍵の生成から~ - Qiita](https://qiita.com/shizuma/items/2b2f873a0034839e47ce)

SSHの仕組みについては

[プログラマーがSSH周りで知っておくと良いこと - Qiita](https://qiita.com/syou007/items/9bbc1b50b9608651c390)
redashで日付をフォーマットするsql

redashを使用しているとき、「何分何秒」でSELECTされるのを「日付」でSELECTするときのフォーマットです

**sqlで日付フォーマット**

```
DATE_FORMAT(rec.created_at,'%Y-%m-%d') as created_date
```

*小文字のyだと2020ではなく、20とだけ出力されるので注意

redashに反映するときは,
[Execute Selected]を押した後で、X軸Y軸にasの後ろ(created_date)をプルダウンから選択する

使い方はこんな感じ
(sales(sl)テーブルから2020年2月4日〜2020年3月4日までの総売上(total)をグラフ化)

```
SELECT sl.total, DATE_FORMAT(sl.created_at,'%Y-%m-%d') as created_date, usr.age_type
FROM pos.sales as sl
JOIN pos.users as usr
ON usr.id = rec.customer_id
WHERE sl.shop_id = 1 
AND sl.created_at BETWEEN '2020-02-04' AND '2020-03-04'
```
効果検証入門 1章をPythonで書く

# はじめに

[効果検証入門 ～正しい比較のための因果推論／計量経済学の基礎](https://gihyo.jp/book/2020/978-4-297-11117-5)内のソースコードをPythonで再現します。

既に[素晴らしい先人の実装例](https://qiita.com/nekoumei/items/648726e89d05cba6f432)がありますが、自分の勉強用のメモとして残しておきます。

この記事では、1章について記載します。
コードは、[github](https://github.com/calderarie/cibook-python)にも掲載しています。
なお、変数名や処理内容は、基本的に書籍内に寄せて実装します。

# 

# 関連

- [「効果検証入門」をPythonで書いた](https://qiita.com/nekoumei/items/648726e89d05cba6f432)
【ERROR メッセージ表示】rails 部分テンプレートでいつでも使える　簡易版

##【ゴール】
errorメッセージの表示

![画面収録 2020-06-23 18.49.15.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620689/bdffee19-fbef-62f0-74a5-feb837976fb6.gif)


##【メリット】
■　UX向上
■　部分テンプレートの理解度向上


##【開発環境】
■ Mac OS catalina
■ Ruby on Rails (5.2.4.2)
■ Virtual Box:6.1
■ Vagrant: 2.2.7

##【実装】

###アプリケーション作成
※touch はカレントディレクトリ内でfile作成するコマンド

```mac.terminal
$ rails new error_test
$ cd error_test
$ rails g scaffold Item name:string texte:text amount:integer
$ rails db:migrate
$ cd app/views/layouts
$ touch _error_messages.html.erb
```

###モデル追記
※DB保存時の条件
※**バリデーション　=　保存時の制限**　を追加

```models/item.rb
class Item < ApplicationRecord
  validates :name, presence: true
  validates :text, presence: true
  validates :amount, presence: true
end

```

###ビュー追記
※パーシャル化し、凡庸性UP
※**「layputs/_error_messages.html.erb」に入れる事で
バリデーションを貼っていれば全てのモデルに使用可能に!!!!**

```layputs/_error_messages.html.erb
<% if model.errors.any? %>
  <div class="alert alert-warning">
    <ul>
      <% model.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div>
<% end %>
```

※追加する

```Items/_form.html.erb
<%= render 'layouts/error_messages', model: f.object %>
```



※**scaffold で作成の場合は上記は不要**
各　_form のviewにて下記コード記載の為（scaffold超便利ですね）

```/_form.....
<% if item.errors.any? %>
<div id="error_explanation">
  <h2><%= pluralize(item.errors.count, "error") %> prohibited this item from being saved:</h2>

  <ul>
    <% item.errors.full_messages.each do |message| %>
    <li><%= message %></li>
    <% end %>
  </ul>
</div>
<% end %>

```


※scaffoldの元々のやつ
![スクリーンショット 2020-06-23 18.46.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620689/1b4368c6-4cb2-d49b-3155-b0b5cf429a1c.png)

※パーシャルしたやつ
![スクリーンショット 2020-06-23 18.47.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620689/ac928fcf-1048-2149-d864-a0a908a8d6b7.png)

以上です。お好みでどうぞ！！！




##【合わせて読みたい】
■エラーメッセージに関して
https://qiita.com/ryuuuuuuuuuu/items/1a1e53d062bff774d88a

■hidden_field
https://qiita.com/tanaka-yu3/items/0d454c5ef80f8267f09d

■アプリケーション作成
https://qiita.com/tanaka-yu3/items/3fe1ed2852c6513d3583
[Swift] Storyboard プロトタイプセルの使い方

### プロトタイプセル

Storyboard上でUITableViewやUICollectionViewを設置した際、さらにプロトタイプセルも設置できる。（オブジェクトの追加ボタン（＋ボタン）から、table view cellや collection view cellを選ぶ）

セルそのものは、reuseIdentifierを使うことにより、コード上で識別できる。

### プロトタイプセルの中身

プロトタイプセル内に自分で設置した部品（例えばUIImageViewやUITextFieldなどなど）は、Story Board上でタグの数値を指定することで、コード上で識別できるようになる。ViewControllerの`viewWithTag()`メソッドを使う。

### 参考

[[iPhone] UITableView をストーリボードで作る](https://i-app-tec.com/ios/tableview.html)
Windows10の不要ファイルをコマンドプロンプトで強制的に削除する方法

#はじめに

Windows10でファイルを削除しようとすると、

「ディレクトリが空ではありません」、「別のプログラムがこのフォルダーまたはファイルを開いているので、操作を完了できません」などと表示され、うまく削除できないことがあります。それをサクッと削除する方法です。

ググると方法が多数出てきますが、そのうち一番うまくいった方法を、忘れないように書いておきます。


#手順

###1. 削除したいフォルダのパス名をチェックする
エクスプローラーで、フォルダを右クリック→プロパティからパス名を表示させ、コピーする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620139/d615b5ff-8bb6-91e0-0acc-591cae6f23c5.png)


###2. コマンドプロンプトを起動する
左下のボックスに'cmd'と入力し、コマンドプロンプトを起動する
![Clipboard.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620139/26d5219a-882f-0fd6-5c3b-6de296d60431.jpeg)

###3. 以下のコマンドを入力

```
C:\Users\ユーザー名>rd /s ファイルやフォルダのパス名（URL）
```

/sはフォルダ内が空でなくても強制削除するという意味です。
以上です。
javascript学習(2020/06/23)

###位置情報の取得

```JavaScript:sample.js
navigator.geolocation.getCurrentPosition(success, fail);
```
navigatorオブジェクトのgeolocationオブジェクトのgetCurrentPositionメソッド。
このメソッド内の()内には2つのパラメータを含める。1つ目には位置情報が取得できたときに呼び出すファンクション名を、2つ目には失敗したときに呼び出すファンクション名を指定する。

###エラーコード

```JavaScript:sample.js
error.code
```

| エラーコード  |       説明 |   
|:-----------------|------------------:|
|1|位置情報を取得する許可がない|
|2|何らかのエラーが発生して位置情報が取得できなかった|
|3|タイムアウト|

###Web API(Application Programming Interface)
Wec APIとは特定のデータを取得したり、画像をアップロードしたり、Webサイトが提供する何らかの機能をプログラムから利用する仕組みのこと。
一般的には機能ごとに専用のURLが用意されている。機能を使うときはJavaScriptのAjaxを使ってそのURLにアクセスする。
Powershell で Azure Table Storage から Timestamp でフィルタした行を取得する

## 前提
AzTable モジュールを使う
https://www.powershellgallery.com/packages/AzTable/2.0.1

## 実装
1. テーブルオブジェクトを取得する
2. -CustomFilter にクエリを書く
時刻は ```datetime'YYYY-MM-DDTHH:mm:ssZ' ``` の形式で書ける

```powershell
$table = Get-AzTableTable -resourceGroup "{resource group name}" -TableName "table name" -storageAccountName "storage account name"
# 2020/1/1 0:00 AM 以前のレコードを取得
Get-AzTableRow -Table $table -CustomFilter "Timestamp lt datetime'2020-01-01T00:00:00Z'"
```

## 参考
https://docs.microsoft.com/en-us/azure/storage/tables/table-storage-how-to-use-powershell
https://docs.microsoft.com/en-us/rest/api/storageservices/querying-tables-and-entities
https://github.com/paulomarquesc/AzureRmStorageTable
vuexでcomponentなform、親子相互bind

git 
https://github.com/kujiy/vuex-study/tree/a2049726e7e6a2c62c1a1ba1d0cef7940473c6b9

# やりたいこと
親子相互にbindしたい。

どのinput boxに入れても全部リアクティブに動く状態。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/f5ef9d77-3fa0-4bfd-53c3-a683737c632a.png)

## vuexのcomputedでやる場合はget/setが必要
vuex の modulesを使っています

main.js

```js
import Vue from 'vue'
import Vuex from 'vuex'
import App from './App.vue'
Vue.use(Vuex)

// import store from './store.js'
import store from './store_module.js'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  store,
}).$mount('#app')
```

store.js
他の勉強もしてたのでゴミだらけ

```js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
      moduleA: {
          namespaced: true,
          state: {
              count: 0,
              mymsgDict: "mAAAAAAAAAAAAAAAAAAA ymsgDict init",
              mymsg: " AAAAAAAAAAAAAAAAAAAAAAA mymsg init"
          },
          mutations: {
              increment(state) {
                  state.count++
              },
              setMsgDict(state, payload) {
                  state.mymsgDict = payload.message;
              },
              setMsg(state, payload) {
                  state.mymsg = payload;
              },
              updateMessage(state, message) {
                state.message = message;
              }
          }
      },
      moduleB: {
          namespaced: true,
          state: {
              count: 0,
          },
          mutations: {
              increment(state) {
                  state.count++
              },
          }
      }
  }
})
export default store
```


app.vue
copmonentでhelloworldを呼んでる

```vue
<template>
  <div id="app">
      Page app:
    <form>
        <input  v-model="compTitleVuex" >
        <input  v-model="compTitleVuex" >
        <HelloWorld/>
    </form>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  computed: {
    compTitleVuex: {
      get() {
        return this.$store.state.moduleA.mymsg
      },
      set(value) {
        console.log(value);
        this.$store.commit('moduleA/setMsg', value)
      }
    }
  }
}
</script>
```

呼び出されるcomponent側
HelloWorld.vue ひどい名前・・

```vue
<template>
    <div class="hello">
        <hr>
        Inside component
        <input v-model="compTitleVuex">
    </div>
</template>

<script>

    export default {
        name: 'insideComponent',
        computed: {
            compTitleVuex: {
                get() {
                    return this.$store.state.moduleA.mymsg
                },
                set(value) {
                    console.log(value);
                    this.$store.commit('moduleA/setMsg', value)
                }
            }
        }
    }
</script>


```


## 以下 mapStateは動かなかった
書き方違うか、対応してないか。

```js
export default {
  name: 'HelloWorld',
  computed: {
    // mix this into the outer object with the object spread operator
    ...mapState({
      message: state => state.moduleA.message;
  })
}}
```
Exception: Error: ;; Invalid morpheme ID: kata(25) kei(37)


# 環境

- OS : ubuntu16.04
- knp : 5.00
- jumanpp : 2.0.0-rc3
- juman : 7.01

# 概要

```
from pyknp import KNP
knp = KNP()
knp.parse("学校でしてね") 
```

こんな感じで普通にKNPを使っていたところ

```
Exception: Error: ;; Invalid morpheme ID: kata(25) kei(37)
```

こんなエラーが文字によって出たり出なかったりしていました
(『てして』は起こる例です)

本家のgithubに解決策が提示されているので、それを参考に個人的なベストソリューションを防備録代わりにメモします
https://github.com/ku-nlp/pyknp/issues/16
https://github.com/ku-nlp/jumanpp/issues/108

# 解決策


```
# 一回消す
$ which knp
-> /usr/local/bin/knp
$ sudo rm -r /usr/local/bin/knp
$ sudo rm -r /usr/local/bin/juman
$ sudo rm -r /usr/local/bin/jumanpp
```
jumanの辞書をKNPに内包されている辞書で更新します
jumanの辞書と、KNPの中にあるjumanの辞書、が一致していないからこのエラーが出るらしいですね
KNPは最新のものがほしいのでこちらから
https://github.com/ku-nlp/knp

```
# juman 7.01
$ wget http://nlp.ist.i.kyoto-u.ac.jp/nl-resource/juman/juman-7.01.tar.bz2
$ tar -jxvf juman-7.01.tar.bz2

# KNP 5.0
$ git clone https://github.com/ku-nlp/knp.git

# copy some files from knp to juman
$ cp knp/juman/makemat/makemat.c juman-7.01/makemat/
$ cp knp/juman/dic/JUMAN.grammar juman-7.01/dic/
$ cp knp/juman/dic/JUMAN.kankei juman-7.01/dic/
$ cp knp/juman/dic/JUMAN.katuyou juman-7.01/dic/

# install juman
$ cd juman-7.01/
$ ./configure
$ make
$ sudo make install
$ cd ..
```

jumanppとKNPはいつもどおりです

```
# jumanppの再インストール（v2で動作確認）
$ wget https://github.com/ku-nlp/jumanpp/releases/download/v2.0.0-rc3/jumanpp-2.0.0-rc3.tar.xz
$ tar xvf jumanpp-2.0.0-rc3.tar.xz
$ cd jumanpp-2.0.0-rc3/
$ mkdir build
$ cd build
$ cmake ..
$ make
$ sudo make install
$ cd ../..

# KNPのインストール
$ sudo apt-get install automake m4 libtool automake autoconf
$ cd knp
$ ./autogen.sh
$ wget http://lotus.kuee.kyoto-u.ac.jp/nl-resource/knp/dict/latest/knp-dict-latest-bin.zip
$ unzip knp-dict-latest-bin.zip
$ cp -ars `pwd`/dict-bin/* ./dict
$ ./configure
$ make
$ sudo make install
$ cd ..
```

configureがないとか出た場合はautogen.shの実行に失敗しているので、ログを見てください
必要なライブラリが足りていない感じです、多分

```
$ python
from pyknp import KNP
knp = KNP()
knp.parse("学校でしてね")
-> 成功
```

行けましたね
解決策を提示していただいた方に感謝です
これに加えて200文字以上の長文を加えないようにしたら、KNPのエラーはほぼなくなりました
CSVをリサイズして返す関数

意外と見当たらなかったので作りました。
グレースケール画像のリサイズと同じことしてます

```python:CSVをリサイズして返す関数
from PIL import Image
from glob import glob
import numpy as np
import os

def resize_csv(file, width, height):
    original = np.loadtxt(file, delimiter=",")
    img = Image.fromarray(original)
    resized_img = img.resize((width, height))
    return np.array(resized_img)

def resize_all_csv(folder, width, height):
    files = glob(folder + "*")
    for file in files:
        basename = os.path.basename(file)
        ext = os.path.splitext(basename)[-1]
        if not ext == ".csv":
            continue
        resized = resize_csv(file, width, height)
        np.savetxt(yourefolderandnamehere, resized, delimiter=',')

```
sqlxのNamedQueryをIN句に適用する方法(名前付きクエリ)

# 1. はじめに
Goの[sqlx](https://github.com/jmoiron/sqlx)でSQLを書く際に、IN句にNamedQueryを使おうとしてハマったので簡単な例文を書きます。
例はPostgreSQLで書いてます。


# 2. 例文
コネクション生成

```Go
db, err := sqlx("postgres","接続情報")
if err != nil {
    log.Fatal(err)
}
```

NamedQuery→PreparedStatementまでの変換

```Go
baseQuery := `SELECT * FROM users WHERE id IN (:userID) AND name = :userName`

bindParams := make(map[string]interface{})
bindParams["userID"] = []int{1, 2}
bindParam["userName"] = "Taro"
users := &User{}

query, params, err := sqlx.Named(baseQuery, bindParams)
if err != nil {
    log.Fatal(err)
}
fmt.Println(query)
// SELECT * FROM users WHERE user_id IN (?) AND name = ?
fmt.Println(params)
// [[1 2] Taro] 
```
sqlxのIn関数で、IN句の展開

```Go
query, params, err = sqlx.In(query, params...)
if err != nil {
    log.Fatal(err)
}
fmt.Println(query)
// SELECT * FROM users WHERE user_id IN (?, ?) AND name = ?
fmt.Println(params)
// [1 2 Taro] 
```
DBドライバーに合わせてバインドし直す

```Go
query = db.Rebind(query)
fmt.Println(query)
// SELECT * FROM users WHERE user_id IN ($1, $2) AND name = $3
fmt.Println(params)
// [1 2 Taro] 
```
SQLを実行し、結果をUser構造体にバインド

```Go
err = db.Select(&users, query, params...)
if err != nil {
	log.Fatal(err)
}
```
nvidia-smi で Failed to initialize NVML: Driver/library version mismatch と言われたとき【GPU】

# はじめに
機械学習でGPUを使いたいときにタイトルのエラーで詰まったので、解決までの道のりを書き残します。
OS は Ubuntu 18.04 または 16.04 です。

# 症状

```sh
$ nvidia-smi
```

を行うと、

```text
Failed to initialize NVML: Driver/library version mismatch
```

と言われたときの話です。

```shell:
$ sudo reboot
```
で再起動するのが一番手っ取り早いようなのですが、できれば再起動したくなかったり、それでも直らなかったりした時のための記事です。


# ドライバーのアンロード
エラーを解決するためにLinuxカーネルのnvidia関連のドライバーを一度アンロードします。まずは、

```shell
$ lsmod | grep nvidia
```
で現在使用されているドライバーを確認します。おそらく、

```text
nvidia_uvm            634880  8
nvidia_drm             53248  0
nvidia_modeset        790528  1 nvidia_drm
nvidia              12312576  86 nvidia_modeset,nvidia_uvm
```
のように表示されるはずです。
最終的に`nvidia`をアンロードするために、それぞれを順番にアンロードしていきます。

```shell
$ sudo rmmod nvidia_drm
$ sudo rmmod nvidia_modeset
$ sudo rmmod nvidia_uvm
```
ここで、`nvidia_drm`がアンロードできなかった方はDisplay Manegerをkillする必要があるため次の章を見てください。特に何も言われなかった方は飛ばしてください。

## `nvidia_drm`のアンロード

`nvidia_drm`をアンロードするために、Display Managerを`kill`します。
具体的には以下のコマンドを順番に実行します。途中で選択肢が出てきたら適当に選択してください。

```shell
$ systemctl stop gdm
$ systemctl isolate multi-user.target
$ systemctl stop systemd-logind
$ killall gdm-x-session
```
ここまでできたらもう一度

```shell
$ sudo rmmod nvidia_drm
$ sudo rmmod nvidia_modeset
$ sudo rmmod nvidia_uvm
```
を実行してみましょう。

#`ndivia`のアンロード
最後に`nvidia`をアンロードします。

```
$ sudo rmmod nvidia
```
成功したように思えたら、もう一度ドライバーを確認しましょう。

```shell
$ lsmod | grep nvidia
```
これで何も表示されなければ成功です。最後に`nvidia-smi`でGPUが認識できているか確認してみましょう。

```shell
$ nvidia-smi
```

```text
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 450.36.06    Driver Version: 450.36.06    CUDA Version: 11.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  TITAN Xp            Off  | 00000000:09:00.0 Off |                  N/A |
| 25%   41C    P0    57W / 250W |      0MiB / 12196MiB |      2%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```
GPUが認識されていることが確認できます。


# おわりに
読んでいただきありがとうございました。ご意見等ございましたらコメントお願いします。
『OODAループ思考』を参考に自律型組織に適した自走できる新人をOJTで育ててみた

# 自律型組織に適した自走できる人材とは？

弊社も自律型組織に向かって組織改善を取り組み始めているんですが、そのメッセージを受け止めた矢先に中途の新入社員2人のOJT担当になりました。
ぼくが異動する都合上、この2人に業務を引き継ぐ必要もあったためなんですが。

せっかく組織改善に向かっているなら、その未来に適した人材にしないといけないので、自律型組織にとって求められるのは、**「自ら考えて行動し、小さな失敗から学びを得られる人」**と位置づけました（コレも自己判断ｗ）

一番いいのはOODAループだろう、とは思っていたものの、もう少し新しい知識も活かしたいな。と思い読んでみたのが、ちょうど出版されたばかりの**『OODAループ思考』**でした。

**OODAループ思考[入門] 日本人のための世界最速思考マニュアル   入江 仁之**
https://www.amazon.co.jp/dp/4478106622/ref=cm_sw_r_tw_dp_U_x_VTB8Eb7ZFZTF5 @amazonJPより
![OODAループ思考.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4736/4f7430c7-a3d8-f94c-e2bd-35e83023b508.jpeg)

# OODAループ思考とは
今まで、色々とOODAループについては読んできましたが、特に新しさを感じたのが、
O = Observe（みる）
O = Orient（わかる）⇐ **Big O**
D = Decide（きめる）
A = Act（うごく）
この、Orient のBig Oが、見てわかったり、行動してわかったりした、わかりみが己の『世界観』を構築するのだ。ということ。

そして、**VUCA**（変動・不確実・複雑・曖昧）に照らした四象限において、OODAは柔軟に適応できる思考法である。とうことでした。
![OODAループ思考_VUCA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4736/08853bc2-e6fa-cea9-c6b4-b3bbb5f89158.png)

それ以外にも、宮本武蔵の五輪書になぞって解説されていたりして、かなり面白いのでOODAループに興味ある方はオススメします。

# OJTにどう組み込むか
この学びを、ぜひOJTに取り入れたい。期間は3ヶ月。
まず、報告スパンが月イチのPDCA的なフィードバック書類作成だったので、
1ヶ月ごとの目標はそのスケジュールに合わせて立てました。

ざっくりいうと、こんな目標です。
1ヶ月目：環境に慣れる。
2ヶ月目：業務と社内関係者を理解する。
3ヶ月目：自分で行動できる。社内関係者を動かせる。

**ちなみに、結果から言うと約2ヶ月くらいで3ヶ月めのゴールにほぼ手をかけてる。くらいまで到達しました。**

# やっぱり1on1とMission/Values
ただ、スタートするに当たりやっぱり絶対に必要なものは、もっと明確な目標の言語化です。
先程のOODAループ思考からの学びと、自分が定めた求める人物像を言語化すると、こうなりました。

## Mission
**自身で判断し、自身で行動し、自身でふりかえって、常に学びから自己成長することで、柔軟性とスピードで企業成長に貢献する人材となる**

## Values
即行動と挑戦　＝　小さな失敗から多くの学びを得て成長する
素直さと傾聴　＝　相手を尊敬し素直に受け入れて聞く姿勢
ふりかえる　　＝　常に今の自分を認知して次の一歩を見直す

##1on1
そして、1on1は毎週木曜、30分。
木曜日がいい。というのも去年行ったGoogle Re:Work勉強会からの学びです。
月曜は忙しいので最悪。金曜も週末に向けて業務やMTGが多くなる傾向があるので避ける。水・木がベストだそう。

1on1では、常にOJT担当であるぼくの行動や言動を観察して気づきを上げてもらう。
そして、自分自身の行動や行動できていないことも観察して気づきを上げてもらう。
そこから、学びも自分自身で導いて言葉にしてもらう。
そんな時間にしました。

ぼくは、ただ教えるわけではなく、一緒に気づきから学び合う感覚で、2人のBig Oの世界観を育み、広げていくための助言やコーチングしていく。そんな関わり方に徹しました。

# 結果
最初の2週間は、新しい環境に慣れる必要があるので新しい気づきを得られるほど心の余裕もないです。
ただ、環境に慣れてくると、3週以降からぼくの振る舞いに目を向ける余裕が生まれ始めて、気付きがいろいろと出てきます。

「なんで、ああいう雰囲気が作れるのか？」とか「なんで、敢えてあそこはああ言ったのか？」などなど。

そういう問いから、「わかりみ」が深まり、Big Oの世界観が広がっていく感覚を、自ら感じ取れるようになりました。

そこからは、ぼく以外の関係者のふるまいにも視野が広がり、より「わかりみ」が広がっていきます。
週１の1on1で確認し合うので、ペースも速いです。

そして、結果として2ヶ月ちょっとで目標に十分に到達していました。

しかも、忘れてはいけない。このコロナ禍で、誰一人出社もできず、直接顔も合わせられず、
ずっとリモート環境下で、オンラインコミュニケーションのみの状況下でも。です。


人を育てる方法論に、また一つ新しい兆しが見えました。
UE4のGarbage Collectionについて 

#概要
UE4のオブジェクトは、UPROPERTYを付けたポインタ変数で参照していればGCの破棄対象にならないというのは有名な話だが、付けていないのにGCにより破棄されないこともあり、どのような挙動になっているのか気になった為、少し調べてみた。
検証はUE4.24で行った。

#検証内容
1.NewObjectで生成したActorを、生ポインタ変数で参照する

```c++:.h
AActor* ObjectPointer;
```
```c++:.cpp
ObjectPointer = NewObject<AActor>();
```

2.NewObjectで生成したActorを、別のActorにアタッチする

```c++:.h
AActor* ObjectPointer;
```
```c++:.cpp
ObjectPointer = NewObject<AActor>();
ObjectPointer->AttachToActor(this, FAttachmentTransformRules::SnapToTargetIncludingScale);
```

3.NewObjectで生成したActorを、UProperty付きのポインタ変数で参照する

```c++:.h
UPROPERTY()
AActor* ObjectPointer;
```
```c++:.cpp
ObjectPointer = NewObject<AActor>();
```

4.SpawnActorで生成したActorを、生ポインタ変数で参照する

```c++:.h
AActor* ObjectPointer;
```
```c++:.cpp
ObjectPointer = GetWorld()->SpawnActorDeferred<AActor>(AActor::StaticClass(), GetTransform());
ObjectPointer->FinishSpawning(GetTransform());
```

#検証結果
1.NewObjectで生成したActorを、生ポインタ変数で参照する
→指定秒数後、GCにより破棄された。
やはり、生ポインタ変数で参照するだけでは、GCにより破棄されてしまうようだ。

2.NewObjectで生成したActorを、別のActorにアタッチする
→指定秒数後、GCにより破棄された。
アタッチされたオブジェクトは破棄されないように作られていたりするのか、気になって調べてみたが、破棄されてしまった。
アタッチしたActorも、破棄されないポインタ変数で管理した方が良さそうだ。

3.NewObjectで生成したActorを、UProperty付きのポインタ変数で参照する
→参照元のActorが存在する限り、破棄されなかった。

4.SpawnActorで生成したActorを、生ポインタ変数で参照する
→紐付いているレベルが破棄されるまで、破棄されなかった。

#結論
NewObjectで生成したActorに関しては、UProperty付きのポインタ変数で参照しなければ、GCにより破棄されてしまう。

UE4でよく使うSpawnActorに関しては少し例外で、この関数で生成したActorはレベルから参照されているので、GCにより破棄されることは無かった。
ただし、レベル遷移などのタイミングで、オブジェクトが破棄されるタイミングが順不同になることがあるので、レベル遷移などのタイミングでも参照する可能性があるポインタ変数には、UPropertyを付けておいた方が安心だと思われる。


#おまけ
Componentもポインタ変数で管理したりするが、ComponentはGCにより破棄されることは無いようだった。
最低限のリセットCSS

リセットCSSには、

- Eric Meyer’s “Reset CSS” 2.0
- HTML5 Doctor Reset CSS
- Yahoo! (YUI 3) Reset CSS
- Normalize.css
- Reboot.css
- ress

などいくつか既存のものがありますが、最低限リセットかけたい時は下記を使っています。

```css
@charset "UTF-8";

html,
body,
h1,
h2,
p,
ul,
li {
  margin: 0;
  padding: 0;
  line-height: 1.0;
}

ul {
  list-style: none;
}

a {
  text-decoration: none;
  color: inherit;
}

img {
  border: none;
  vertical-align: bottom;
  max-width: 100%;
}

html {
  font-size: 62.5%;
}

body {
  background: #fff;
  color: #333;
  font-size: 1.6rem;
  font-family:"游ゴシック",YuGothic,"Hiragino Kaku Gothic ProN",Meiryo, sans-serif;
}
```

色やフォントサイズは例です。
`margin,padding,line-height`の余白リセットは、使用する要素にのみ当てています。デザインによって使用する要素が増えたら適時追加します。

```css
html,
body,
h1,
h2,
h3,
h4,
p,
ul,
li,
dl,
dt,
dd {
  margin: 0;
  padding: 0;
  line-height: 1.0;
}
```

## table使用時

```css
table {
  border-collapse: collapse;
  border-spacing: 0;
}
```
## button・input・textarea使用時

```css 
input,
button,
select,
textarea {
  appearance: none;
  background: transparent;
  border: none;
  border-radius: 0;
  font: inherit;
  outline: none;
}

textarea {
  resize: vertical;
}
```
重複ファイルの除去

#背景
長年のPC歴によって、様々なファイルを様々なメディアに保存してきた。いい加減に統一してしまいたいのでNASを導入して次々と個別のメディア（USBフラッシュ, HDD, MO!, FDD!! etc.）からコピーしている（進行形）。古いメディアの殆どは低容量だし、場所も取るので廃棄中。

困るのは、PCを移行する度にHDDごと保管していたデータ。多くは前のPCから引き継いで引き継いで...×n..。重複ファイルが大量にある。持ち出し用にコピーしていたメディアにも大量に重複があるし、バージョン違いもあってカオス。

ひとまず１メディアに１ディレクトリを割り当ててコピーするだけしているが、やはりNASも有限なのでせめて同一ファイルは除去していきたいと思った。

#解法

```20240319追記：WindowsならWinMergeがお勧め！```

世の中には優秀なツールが沢山あるようだが、無料で良い物を探す気力が無い。そこで、ある程度自動かつ自分の目で確認しながら重複除去をするためのスクリプトを作成して対処している。

前提：`UNIXライクな環境 (GNU系列のコマンド体系)` `rdfindインストール済み`

```mergehelper.sh
#!/bin/bash
# Usage: mergehelper.sh DIR1 DIR2

DIR1=$1
DIR2=$2

rdfind -ignoreempty true -dryrun true ${DIR1} ${DIR2}
grep -v -e '^\s*#' -e '^\s*$' results.txt |  awk '{if ($1=="DUPTYPE_FIRST_OCCURRENCE") printf("\n"); for (i=0; i<=NF; i++){if (i>7) printf("%s "),$i} printf("\n")}' > duplications.txt
cat duplications.txt | sed -e 's/^/#rm -v \"/' | sed -e 's/$/\"/' | sed -e 's/#rm -v \""//g' | sed 's/\ "$/\"/g' > rmfile_comout.sh
```

実行すると、コメントアウトされた膨大なrmコマンドのシェルスクリプトが作成される。そのうち、必要なもの以外のコメントアウトを除外すると重複が排除される。

ブロックの先頭の一個を除いて最初からコメントアウトしないとか、リストの長さに応じて出力をカスタマイズすると良い気がする。自分の場合、例えば下記のpythonスクリプトのようにキーワードで削除するファイルを選んだりしている。

```selection.py
import sys

# 下記のキーワードを含むパスのファイルを消去する場合
rmlist = []
rmlist.append('KEYWORD1')
rmlist.append('KEYWORD2')
rmlist.append('KEYWORD3')
# as well ...

# キーワードを含むパスのコメントアウトを外す
def process(lines):
    nline = len(lines)
    n = 0
    for line in lines:
        delete = False
        token = line.strip()
        for l in rmlist:
            if l in token:
                delete = True

        if delete:
            n = n + 1
            if n < nline:   # 同一ファイルのリストのうち最後の１個は残す
                print(token.replace('#',''))
            else:
                print(token)
        else:
            print(token)

    return 0

# 標準入力で処理する
lines = []
for line in sys.stdin:
    if line != '\n':
        lines.append(line)
    elif line == '\n':
        print("")
        dummy = process(lines)
        lines = []
```

最後の行にパイプで繋いでも良いし、

```
cat rmfile_comout.sh | python3.x selection.py > rmfile.sh
```

として結果を確認しつつ調整しても良い。そのうち残すファイルを明示的に選びたいシチュエーションも出てくるかもしれない。
JBcryptを使用したパスワードのハッシュ化とその認証

#やったこと

Java(Spring) でJBcryptを使用してパスワードのハッシュ化とその認証を行いました。

#準備

[MVN REPOSITORY](https://mvnrepository.com/artifact/de.svenkubiak/jBCrypt/0.4)からjarファイルを取得

#パスワードのハッシュ化

```java

@PostMapping("/sample")
public String sample(@Validated SampleForm sampleForm,
	BindingResult bindingResult, Model model) {

        // 入力値のpasswordをハッシュ値に変換
	String hashedCode = BCrypt.hashpw(sampleForm.getPassword(), BCrypt.gensalt());

        // 以下ハッシュ化されたパスワードをDBに格納する処理

        ...
}
```

>ソルトはハッシュ関数に入れる前のパスワードの前後にくっつける文字列です。
>[「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word16974.html)より引用

#パスワードの認証

```java

@Override
public boolean isPasswordCorrect(String inputPassword) {

        final String SAMPLE_SQL = "SQL文をここに記載"

        // DBからパスワードを取得
        Map<String, Object> PasswordFromDB = jdbcTemplate.queryForMap(SAMPLE_SQL);
        String passwordFromDB = (String)PasswordFromDB.get("password");

        // 入力値である平文のinputPasswordとDBにあるハッシュ化されたpasswordFromDBを比較
        if(BCrypt.checkpw(inputPassword, passwordFromDB)) {
            // 処理
	    }
}
```

#まとめ

簡単にハッシュ化できる！

ハッシュ化する時は、

```java

BCrypt.hashpw(ハッシュ化したい値, BCrypt.gensalt());
```

ハッシュ化した値を認証する時は、

```java

BCrypt.checkpw(比較したい平文の値, DBから取得したハッシュ化された値);
```

以上です。最後まで読んでくださり、ありがとうございました。
UbuntuからSSHユーザーを消す

deluser コマンドで消せるよ。
`--remove-home` を指定することでユーザーのホームディレクトリ毎消せるよ。

```sh
$ deluser --remove-home user
```

`--remove-home` オプションを使うには perl のインストールが必要だよ。

```sh
$ apt-get install perl
```
Anaconda (conda)の簡単な使い方メモ

# はじめに
Anaconda (condaコマンド)の使い方に関して程よい資料 (情報が多すぎず少なすぎず)が見つからなかったのでまとめてみました。

本記事は、Anacondaがインストールされていることを前提としています。

インストールの確認は下記コマンドで行えます。

```bash
$ conda --version
conda 4.8.2
```
※Jupyter notebookの場合は、Pythonセル上で`!conda --version`とコマンド冒頭に`!`を付けてセルを実行すれば同様に確認できます。

# Anacondaとは
データサイエンス向けのPythonパッケージ集合体
- 1,500以上のパッケージに対応
- GUIとコマンドラインの両方に対応
- `conda`コマンドを使って操作できる

Anacondaを使うことでライブラリのインストール等に時間を取られることなく簡単に開発環境の構築や切り替えを行うことが可能です。

参考：https://www.creativevillage.ne.jp/72837

# Anaconda (condaコマンド)の使い方メモ
## 1. condaによる仮想環境の構築
```bash
$ conda create --name my_notebook_env python=3.7 -y
```
`-name my_notebook_env`：仮想環境の名前. 好きなものを設定できる
`python=3.7`：仮想環境で使用するPythonバージョン
`-y`：確認項目に自動的にyesで応答する

## 2. 仮想環境の有効化
仮想環境の有効化

```bash
$ conda activate my_notebook_env
```

仮想環境の無効化

```bash
$ conda deactivate
```

仮想環境の削除

```bash
$ conda remove --name my_notebook_env --all
```

## 3. 仮想環境内でのライブラリのインストール
pandasをインストールするには

```bash
$ conda install pandas
```

jupyterをインストールするには

```bash
$ conda install jupyter
```

インストールされているライブラリの一覧を表示

```bash
$ conda list
```

# 例：仮想環境内でjupyter notebooksを起動する
仮想環境の有効化し、jupyter notebooksを起動する

```bash
$ conda activate my_notebook_env
$ jupyter notebook
```

# まとめ
Anacondaを使うことで簡単に開発環境の構築や切り替えを行えます！また環境が壊れてしまった場合も容易に再構築可能なので安心です！

# 参考
[Introducing Anaconda | Even More Python for Beginners](https://youtu.be/7Zks84Hba_k)
Railsアプリに独自ドメインを与えてAWSに上げても表示されない問題

「自分のアプリを独自ドメインにしてAWSに上げたろー」

ということで以下の記事を参考に自分のアプリに独自ドメインを付与しました。
https://mel.onl/onamae-domain-aws-route-53/

しかし３日待っても全く表示されない。AWSの紹介ページが表示されるだけ・・・
そこで色々調べた結果、Nginxの設定が必要であるとわかった。

Nginxの設定

EC2で

```
[USERNAME|~]$ cd /etc/nginx/conf.d/
[USERNAME|conf.d]$ sudo vi 〇〇.conf （#自分のアプリケーション名）
```
〇〇.confで

```
server_name 　〇〇.com;(#アプリの独自ドメインに変更してください)
```
保存して終了。再起動する。

```
[USERNAME|〇〇（アプリ名）]$ sudo nginx -s reload
```

これで行けるはず！


参考文献
https://qiita.com/naoki_mochizuki/items/5a1757d222806cbe0cd1#nginx%E3%81%AE%E8%B5%B7%E5%8B%95

https://teratail.com/questions/49756
SQL テーブル結合の基礎を学ぶ

# 目的

- SQLのテーブル結合の基礎をまとめる。

# テーブル結合とは？

- 文字通りテーブルを結合することである。
- 結合は物理的にくっ付くのではない。(したがってテーブル結合を解除するSQL文などがあるわけではない)
- あくまで結合はデータを取得する為だけに一時的に結合する物である。
- テーブル結合を使用する例を下記に記載する。
    - 下記の様なusersテーブルとage_rangesテーブルが存在するとする。
        - usersテーブル

            | カラム名 | 格納される値の情報 |
            | --- | --- |
            | id | 数値が自動インクリメントされて格納される |
            | name | ユーザ名を表す文字列 |
            | age_renge_id | ユーザの年齢層を識別するID |
        - age_rengesテーブル

            | カラム名 | 格納される値の情報 |
            | --- | --- |
            | id | 数値が自動インクリメントされて格納される |
            | age_range | 年齢層を指定する文字列(２０代など) |
    - 下記の様にダミーデータが格納されている物とする。
        - usersテーブル

            | id | name | age_renge_id |
            | --- | --- | --- | 
            | 1 | miriwo | 2 | 

        - age_rengesテーブル

            | id | age_renge |
            | --- | --- |
            | 1 | 未成年 |
            | 2 | 20代 |
            | 3 | 30代 |
    - usersテーブルとage_rangesテーブルの内容を掛け合わせて下記の様に表示したい時に結合を使用する。（年齢層をidではなく文字列で表現したい）

        | id | name | age_renge |
        | --- | --- | --- |
        | 1 | miriwo | 20代 |

# 例

1. 先に定義したusersテーブルとage_rangesテーブルに格納されているダミーデータを用いて、テーブル結合を使用して下記の様に出力する方法をまとめる。

    | id | name | age_renge |
    | --- | --- | --- |
    | 1 | miriwo | 20代 |

1. 一旦下記のSQLを実行してテーブル結合を行い全てのカラムの値を出力する。

    ```sql
    mysql> select * 
           from users 
           join age_ranges 
           on users.age_range_id = age_ranges.id
           where users.id = 1;
    ```
1. 下記の様に結合後のusersテーブルのidが1のカラムが全て出力される。

    ```
    +------+--------+--------------+------+-------+
    | id   | name   | age_range_id | id   | name  |
    +------+--------+--------------+------+-------+
    |    1 | miriwo |            2 |    2 | 20代  |
    +------+--------+--------------+------+-------+
    ```
1. 全てのカラムが出力されてしまったのは`select *`と指定してしまっているからである。下記の様な形でデータが得られる様にselectの部分を修正する。

    | id | name | age_renge |
    | --- | --- | --- |
    | 1 | miriwo | 20代 |
1. 下記を実行することにより意図した形でデータを出力することができる。

    ```sql
    mysql> select users.id, users.name, age_ranges.name as age_renge 
           from users
           join age_ranges
           on users.age_range_id = age_ranges.id
           where users.id = 1;
    ```
1. 実行結果を下記に記載する。

    ```
    +------+--------+-----------+
    | id   | name   | age_renge |
    +------+--------+-----------+
    |    1 | miriwo | 20代      |
    +------+--------+-----------+
    ```

# 解説

- 最終的に実行したSQL文の解説を行う。
- 下記にコメント付きで先のSQL文を記載する。

    ```sql
    mysql> -- 最終的に出力するカラムを指定している。usersテーブルのidカラム、usersテーブルのnameカラム、age_rangesテーブルのnameカラムをage_rengeと改名して表示する命令である。
           select users.id, users.name, age_ranges.name as age_renge
           -- from テーブル名でメインのテーブルを指定している。 
           from users
           -- join テーブル名で結合を行うテーブルを指定している。
           join age_ranges
           -- on メインテーブル名.カラム名 = 結合を行うテーブル名.カラム名で結合ルールを指定している。
           -- 「usersテーブルのage_range_idカラムに格納されている数字とage_rangesテーブルのidカラムの数字が一致する物を結びつけてください」という意味である。
           on users.age_range_id = age_ranges.id
           -- ここまでのルールで取得できたデータでusersテーブルのidカラムが1の物だけ出力する命令である。
           where users.id = 1;
    ```