OmniAICreator/Qiita-1.07M huggingface dataset:
AWS GameDay Tokyo Microservices Madness 20190620

# [AWS GameDay](https://awsgamedaymicroservicesmadness.splashthat.com/) の備忘録
率直な感想を申し上げますと・・・

- 思い切って参加して良かったー😁！
- インフラエンジニアでもハッカソンにチャレンジできるんだー👨‍💻

でも、参加する前はこんな気持ちでした。

- 楽しそう！と応募してしまったもののイベント開催日が近づくにつれ、不安になってきました
- ゲーム（演習）についていけるのかしら？
- 保有スキル(IaaS)が役に立たないかも、イベントのタイトルに「Microservices」と書いてあるし😕
- キャンセルしようかな・・・

いやちょっと待てよ、自分に足りないスキルを早めに知る、いい機会かも💡と考え直し、思い切って参加してみたところ・・・

- 社外のエンジニアの方から刺激を受けました！
- 更にレベルあげるぞ！という前向きな気持ちになる
- みんな凄いぞ、自分はまだまだAWSのスキル未熟だな😔
- 使ったことのあるサービスのスキルは深くは理解できてないな
- 日常業務はシステム(環境)の構成・設計・運用を予め把握しているからできる気になっているけど、社外に出たら通用しないね
- AWSさんのスキル凄いぞ(ほぼマンツーでのヘルプで垣間見た感想)
- チームの順位は下から数えた方が早い😔でも楽しかった！

ちなみに私のAWS経験値はこんな程度です。

- AWS歴1年
- AWS認定資格なし
- Technical Essential 1,2受講済
- 代表的なサービスを実験的に幾つか実験したことある
- 仕事でVPC、EC2などのインフラ関連、最近WorkSpacesをちょっと

ゲームの内容は守秘義務がありますのでお話できませんが、ぜひ参加されてみては如何でしょうか。私は、①自分のスキルレベルが分かったのと、②AWSをしっかり理解したい、③認定資格を使って勉強する、と思うようになりました。

プライベートや職場の都合など色々あるかと思いますので、あくまでも個人の感想と捉えていただければと思います。

AWSさんからいただいたクッキーです↓ 挑戦者の証！
![cokkie.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280358/909348b3-2ba1-1a25-b392-44bd66762bc9.jpeg)
SourcetreeとGitlabの連携方法について調べてみた

Windows環境で、SourcetreeとGitlabの連携方法について調べてみました。
連携方法の手順は以下です。

・Sourcetreeのインストール
　SourceTree(3.0.15)をインストールしてみた - Qiita
　参考：https://qiita.com/tetsu831018/items/bb6ecf15ca5f67e5879a

・アクセストークン作成
　GitLabアカウントをSourceTreeに登録する方法 - Qiita
　参考：https://qiita.com/TakuyaHara/items/0424e188f5073aa362a5

・SSHキー設定
　SourceTreeでGithubの認証に秘密鍵を使う (Windows) - Qiita
　参考：https://qiita.com/reflet/items/4f7b5c4a312bc27df10e

・Gitlabからクローン
　GUIでわかりやすいので、説明は省きます
flaskアプリを、pdbを活用してデバッグする方法


#手順
[stack overflowのDebugging flask with pdb](https://stackoverflow.com/questions/26812150/debugging-flask-with-pdb)を参考にしています。

1. screenなどを使って２つ端末を立ち上げておきます。以降端末１、端末２と書きます。

2. flaskアプリ上のデバッグを開始したい箇所に、次のコードを埋め込みます。 

    ```python
    import pdb; pdb.set_trace()
    ```
3. 端末１で、flaskのdevelopment用サーバをflask runにて起動します。下のようにFLASK_ENVを設定するとデバッグ出力モードになります。（[参考：flask Development Server](http://flask.pocoo.org/docs/1.0/server/)）

    ```shell
    $ export FLASK_ENV=development
    $ flask run
    ````
4. この状態のまま、端末２で、curlコマンドで該当のアプリにアクセスします。
なお、curlの使い方は[「curlコマンドの使い方　～GET、POST、REST（json）の確認と、windowsでの利用手順」](https://viral-community.com/security/curl-8263/)が分かりやすく参考になりました。
5. そうすると、端末２(curl側)では待機状態になっているはずです。このまま端末１(flask側)を見るとpdbに入っていますので、後は端末１側でpdbにてデバッグすることができます。

#環境
次でできました。難しい仕組みを使っていないので、広く活用できると思います。
flask: 1.0.2
python: 3.7.3
サーバ側のOS: linux(CentOS7)
#最後に
pdbはシンプルで便利なので、flaskアプリでもpdbでデバッグができて幸せでした。
[Rails] ログイン機能 devise 流れ 簡易メモ

```:Gemfile
gem 'devise'
```
```:Terminal
$ bundle install
```

```:Terminal(サーバー立ち上げ直し)
$ rails s
```
```:Terminal（deviseの設定ファイルを作成）
$ rails g devise:install
```
```:Terminal（モデルを作成）
$ rails g devise user
```
```:Terminal（上記で作成されたマイグレーションファイルを実行）
$ rake db:migrate
```

```ruby:controller（ログインしていない時に他のアクションが動かないようにする）
before_action :move_to_index, except: :index

def index
  @tweets = Tweet.page(params[:page]).per(5).order("created_at DESC")
end

private
def move_to_index
  redirect_to action: :index unless user_signed_in?
end
```

```:Terminal（viewを変更したい時、このコマンドで作成されるviewを編集する）
 $ rails g devise:views
```

```:Terminal（カラムを追加）
$ rails g migration AddNicknameToUsers nickname:string
```
```:Terminal（上記で作成されたマイグレーションファイルを実行）
$ rake db:migrate
```

```erb:html.erb上記のカラムをviewから入力（登録）できるようにする。
 <%= f.text_field :nickname, autofocus: true, maxlength: "6" %>
```

```ruby:ApplicationControllerにストロングパラメーターを設定
class ApplicationController < ActionController::Base
   
  before_action :configure_permitted_parameters, if: :devise_controller?

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
  end
end
```
[Rails] ページネーション kaminari 流れ 簡易メモ

```:Gemfile
gem 'kaminari'
```
```:Terminal
$ bundle install
```

```:Terminal(サーバー立ち上げ直し)
$ rails s
```

```erb:view(html.erb)※変数@tweetsは一例
<%= paginate(@tweets) %>
```
```:controller※変数などは一例（pageとperを設定）
def index
  @tweets = Tweet.order('created_at DESC').page(params[:page]).per(5)
end
```
docker(15)今日のdocker error:denied: requested access to the resource is denied


```shell-session:macOS
$ docker push  kaizenjapan/qc-nakamori 
The push refers to repository [docker.io/kaizenjapan/qc-nakamori]
97c6efdca6e8: Preparing 
a7ab5d7b861b: Preparing 
75e70aa52609: Preparing 
dda151859818: Preparing 
fbd2732ad777: Preparing 
ba9de9d8475e: Waiting 
denied: requested access to the resource is denied
```

docker runは動くのに、docker pushがエラーになる。loginしなおしてみる。

```shell-session:macOS
$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: kaizenjapan
Password: 
Login Succeeded
```
もう一度。

```
$ docker push  kaizenjapan/qc-nakamori 
The push refers to repository [docker.io/kaizenjapan/qc-nakamori]
97c6efdca6e8: Pushed 
a7ab5d7b861b: Layer already exists 
75e70aa52609: Layer already exists 
dda151859818: Layer already exists 
fbd2732ad777: Layer already exists 
ba9de9d8475e: Layer already exists 
latest: digest: sha256:2ecf657f164325cea8fa9dced3dc5ed5ee06be90cc47147219b71dd7d8eee45d size: 1574
```

よかった。

# 文書履歴(document history)
ver. 0.01 初稿 20190622
### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.


<a href="https://b.hatena.ne.jp/entry/s/qiita.com/kaizen_nagoya/items/fae512ef5e0c04dabc25" class="hatena-bookmark-button" data-hatena-bookmark-layout="basic-label-counter" data-hatena-bookmark-lang="ja" title="このエントリーをはてなブックマークに追加"><img src="https://b.st-hatena.com/images/v4/public/entry-button/button-only@2x.png" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;" /></a><script type="text/javascript" src="https://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script>
https://b.hatena.ne.jp/guide/bbutton
Railsコンソールを使ってレコード追加する方法

**コンソール**とは、ターミナルからRails内で定義されているメソッドの確認やDB内にあるテーブルのレコードを操作できる機能のことである。

#コンソールの立ち上げ方

以下のコマンドを実行する。

```
rails c
```
すると、ターミナル上に以下のような表示がされる。

```
[1] pry(main)>
```

#レコードの追加方法

レコード追加する場合は、createメソッドを使う。createメソッドとは、レコードの作成を行うことのできるメソッドである。

```
[1] pry(main)> モデル名.create(カラム名："カラムの値")
```
※区切る時は、「,」半角カンマを使用する。

例）

```ruby
[1] pry(main)> Tweet.create(name: "takashi", text: "Nice to meet you!")
```

#コンソールの切り方
以下のコマンドを実行する。

```
[1] pry(main)> exit
```
中小底辺事務員が自動化を頑張る（出勤日だけPCを起動しておく）

#いきさつ
パソコンを立ち上げてデスクトップが表示されていても、ソフトの起動やデータの読み込みがすぐには終わっておらず、デスクトップが表示された直後はパソコンの動作が非常に重くストレス溜まります、落ち着くまで待っておけば良いのですが。
出社して席に着いた時には、起動後しばらくした落ち着いた状態でいてほしいです。

#やりたいこと
営業日だけパソコンをあらかじめ起動しておきたい。

##BIOSの自動起動の機能を利用する
起動スケジュールは曜日と時間の指定だけなので、営業日だけは無理ですね。
ただし、これを利用すれば。

##BIOSで毎日起動しておいてから、休日だったらシャットダウンする
WindowsのタスクスケジューラでOS起動後に今日が休日か判別して、休日ならシャットダウンする。という方法くらいしかないじゃないでしょうか。
OS上からBIOSの設定が書き換えれるなら、実現できそうですけど。

##実際には卑怯な手段で実現
「営業日だけ起動する」事が無理なのはわかったのですが諦めきれず。

社内で自分が触る事ができるサーバーがあったので、そこから営業日の朝にWoLを使ってマジックパケットを送り起動する事にしました。マジックパケットを送る方法は[MagicSend](https://www.vector.co.jp/soft/win95/net/se357465.html)というソフトを使いました。

以下のバッチをパソコンを起動したい時間に、タスクスケジューラに登録します。

~~~shell:wol_on_businessday.bat
@echo off

SET DATA=""
SET /P DATA=<dayoff.txt

IF %DATA%==%DATE% (
  FOR /F "skip=1 tokens=* usebackq" %%i IN ("dayoff.txt") DO @echo %%i>>dayoff.txt.tmp
  DEL dayoff.txt
  REN dayoff.txt.tmp dayoff.txt
) else (
  magicsend AA-BB-CC-DD-EE-FF
)
~~~

~~~text:dayoff.txt（休日＝PCを起動しない日を記述）
2019/01/01
2019/01/02
2019/01/03
.
.
.
2019/12/29
2019/12/30
2019/12/31
~~~

txtにある1行目と今日が一致（＝今日が休み）したらなにもせず1行目を削除、今日が一致しなかったら（＝今日が営業日）マジックパケットを送って対象のPCを起動します。

#おわりに
txtの1行目としか比較しないので、なにか問題があってずれてしまったらずっとうまく動作しないという問題があること。そもそも1行目を消さなくてもtxtと全文と今日の文字列の比較だけすれば問題も起こりにくいし、単純な事にあとで気付きました。

でも、バッチ処理でテキストファイルの1行目を削除するのってどうするんだろう？と頭を悩ませた経緯があったので、あえてこの方法を公開してみました。
市町村名が表す地理的イメージをワンライナーとTableauで可視化

# 元ネタ
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">町名の最後の一文字だけで書いた東京の地図できた…！ <a href="https://t.co/UKV4rwuPYo">pic.twitter.com/UKV4rwuPYo</a></p>&mdash; 三土たつお (@mitsuchi) <a href="https://twitter.com/mitsuchi/status/1142048530309079040?ref_src=twsrc%5Etfw">2019年6月21日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

- mitsuchiさんのツイートが面白そうだったのでやってみた

# 元データ

- 国土交通省国土政策局GISHP【インターネットサービス】 

    - http://nlftp.mlit.go.jp/isj/index.html

- データを見てみる

```
% iconv -f SHIFT_JIS -t UTF-8 13_2018.csv|head                                                                                                                                                                                                 
"都道府県コード","都道府県名","市区町村コード","市区町村名","大字町丁目コード","大字町丁目名","緯度","経度","原典資料コード","大字・字・丁目区分コード"
"13","東京都","13101","千代田区","131010001002","内幸町二丁目","35.670812","139.754182","0","3"
"13","東京都","13101","千代田区","131010001001","内幸町一丁目","35.670839","139.758119","0","3"
"13","東京都","13101","千代田区","131010002003","霞が関三丁目","35.671825","139.746988","0","3"
"13","東京都","13101","千代田区","131010003000","北の丸公園","35.691555","139.751639","0","1"
"13","東京都","13101","千代田区","131010004001","富士見一丁目","35.697871","139.746978","0","3"
"13","東京都","13101","千代田区","131010005001","永田町一丁目","35.675895","139.746306","0","3"
"13","東京都","13101","千代田区","131010006000","千代田","35.684052","139.752145","0","1"
"13","東京都","13101","千代田区","131010007000","三番町","35.690557","139.743591","0","1"
"13","東京都","13101","千代田区","131010008002","九段南二丁目","35.693143","139.745694","0","3"
```

# 特徴を表す最後の１文字を抽出する

```
% iconv -f SHIFT_JIS -t UTF-8 13_2018.csv| /usr/bin/sed -e 's/"//g' | awk -F',' '{print "echo "$7 "," $8 "," $6 ",$(echo " $6 "|sed -e \"s/.丁目//g\" -e \"s/市//g\" -e \"s/町//g\" -e \"s/村//g\" | rev | cut -c 1)"}'|bash > tokyo_features.csv

% head tokyo_features.csv 
緯度,経度,大字町丁目名,名
35.670812,139.754182,内幸町二丁目,幸
35.670839,139.758119,内幸町一丁目,幸
35.671825,139.746988,霞が関三丁目,関
35.691555,139.751639,北の丸公園,園
35.697871,139.746978,富士見一丁目,見
35.675895,139.746306,永田町一丁目,田
35.684052,139.752145,千代田,田
35.690557,139.743591,三番町,番
35.693143,139.745694,九段南二丁目,南
```

# Tableauで可視化

## 特徴の出現頻度

- 田が最も多いらしい

- 続いて台、川、山など

<img width="1502" alt="3.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18613/840cfa37-4688-c495-4872-9bd7f6493a11.jpeg">

## 地図上での可視化

- 文字が表すイメージを直感で色分けしてプロット

<img width="1676" alt="4.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18613/aaad3b07-606a-dd5d-4cb7-c57c371a553b.jpeg">

## 方角もやってみた

- エリアごとの方角を示してそう

<img width="1664" alt="ScreenShot 2019-06-22 at 1.57.46.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18613/3bd80666-29ab-e896-cb81-dba4f3bd4f6e.jpeg">
ニートの自然言語処理100本ノック:52

nltkのstemからPorterStemmerを持ってきて実装。


```python
"""
52. ステミング
51の出力を入力として受け取り，Porterのステミングアルゴリズムを適用し，単語と語幹をタブ区切り形式で出力せよ． Pythonでは，Porterのステミングアルゴリズムの実装としてstemmingモジュールを利用するとよい．
"""
import re
from nltk import sent_tokenize
from nltk.stem import PorterStemmer
from pprint import pprint
from n50_exercise import load_text,find_specialchar_index,sent_tokenize_Plus
from n51_exercise import sentence_ToWords,write_50word_ToText



def stemming_text(file_path):
    '''
    stem word in text file
    '''
    stemed = []
    ps = PorterStemmer()

    with open(file_path,'r') as file:
        line = file.readline()
        while line:
            stem = ps.stem(line.rstrip())
            stemed.append(stem+'    '+line[len(stem):].rstrip())
            line = file.readline()
    return stemed


if __name__ == "__main__":
    
    path = "nlp.txt"
    # テキストの読み込み
    sentence = load_text(path)
    # 特殊な文字の位置を取得する
    index = find_specialchar_index(sentence)
    # token化　一文化
    sent_token = sent_tokenize_Plus(sentence,index)
    # print(sent_token[0])
    # とりあえず一区切りだけ入れる
    words,length = sentence_ToWords(sent_token)
    # 単語書き込み
    write_50word_ToText(words,length)
    # ファイルを指定
    word_index = """
    100    1099   1199   149    249    349    449    50     599    699    799    899    99
    1000   1100   1200   150    250    350    450    500    600    700    800    900    999
    1049   1149   1249   199    299    399    49     549    649    749    849    949
    1050   1150   1250   200    300    400    499    550    650    750    850    950
    1050   1150   1250   200    300    400    499    550    650    750    850    950
    :
    """
    file_path = "words.txt" + input("この中から番号を選んでください\n"+word_index)
    # stemming適応
    stemed = stemming_text(file_path)
    pprint(stemed)

```
SORACOM バイナリパーサーで、位置情報送ってみよう！

### 経緯

WioLTE M1/NBを使っている人が思うこと、LTE-Mの通信料の高さに驚いている人も居るとおもいます。
なんとかパケット使用料を減らそうと、バイナリでデータをUDP等で送る訳なのですが、位置情報をどのようにバイナリデータにすればいいんだ？と悩んで居る方がきっと居ると思うので、サンプルを作ってみました。

### バイナリパーサーの設定

SORACOMコンソールで、下記のようにバイナリパーサーを設定したとして、floatの変数に位置情報が入っているとして、UDPパケットで送るデータを作成し、実際に、SORACOMに送信した際にサーバに届いた結果も合わせて公開します。

![190622-0001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33220/9bb527d0-1b95-b5a7-468c-a968f6220626.png)

### バイナリパーサフォーマット作成に役立つ、Playground

SORACOM Blogで『新機能: バイナリパーサーを簡単にお試しいただけるようになりました』が出ていましたので、使ってみました。　
(https://blog.soracom.jp/blog/2019/06/21/binary-parser-playground/)

![190622-0002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33220/b8c2321a-62e8-da84-2bcb-651b8f6c81ae.png)

### ここからがコード

データ作成のみを掲載しています。

```c:sample.ide
// SORACOMバイナリパーサーを使ってGPSデータを送るとしたらのサンプル
// Programed by kazuyuki Eguchi
// パーサーのフォーマット
// lng::float:32 lat::float:32

#include <WioCellLibforArduino.h>

void setup() {
  SerialUSB.begin(115200);
  delay(4000);
  
  SerialUSB.println("");
  SerialUSB.println("--- START ---------------------------------------------------");
  
  float lng = 139.725328;
  float lat = 35.62754;

  // double型の大きさを調べて見よう
  SerialUSB.printf("sizeof(lng)=%d",sizeof(lng));
  SerialUSB.println("");

  int lng_i = *( ( int* )&lng );
  int lat_i = *( ( int* )&lat );
  
  SerialUSB.printf( "lng=%f ( %08x )",lng,lng_i);
  SerialUSB.println("");

  SerialUSB.printf( "lat=%f ( %08x )",lat,lat_i);
  SerialUSB.println("");

  // 送信するデータを作ってみよう
  char data[8];

  data[0] = (lng_i >> 24) & 0xff;
  data[1] = (lng_i >> 16) & 0xff;
  data[2] = (lng_i >> 8) & 0xff;
  data[3] = lng_i & 0xff;

  data[4] = (lat_i >> 24) & 0xff;
  data[5] = (lat_i >> 16) & 0xff;
  data[6] = (lat_i >> 8) & 0xff;
  data[7] = lat_i & 0xff;

  // 人間がデータを確認するために１６進数の文字列で表現しているよ(Webでの確認するため）
  SerialUSB.printf("data=%02x%02x%02x%02x%02x%02x%02x%02x",data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]);
  SerialUSB.println("");  
}

void loop() {
}
```

### サーバで受信した結果

{"lng":139.72532653808594,"lat":35.627540588378906}

となりました！

以上、ご参考までに
不具合発生時の対応

# はじめに
不具合が発生した時の対応について、まとめてみました。
やり方は色々あると思うので、これがあっているという訳ではありませんが、自分がこれまでやってきたことが少しでも誰かのためになればと思い書いてみました。

# 不具合発生時の流れ
 1. 再現確認・発生手順の明確化
 2. 再現時のログを取得する
 3. 上長、リーダーに報告
 4. どこが問題かの切り分け
 5. 原因調査
 6. 上長、リーダーに報告
 7. 対策検討・工数見積もり
 8. 上長、リーダーに日程調整
 9. 実装資料の作成
 10. 実装／コードレビュー
 11. 改修評価
 12. 修正したソースをコミット

※報告する相手は現場による

#1. 再現確認・発生手順の明確化について
不具合の報告を受けたら、その現象が本当に再現するかを確認します。
どういう条件、環境のもとで不具合が発生したのか、しっかり報告者からヒアリングして、
出来るだけその環境に近づけて確認します。 

#2. 再現時のログを取得する
1.で再現できたら、その時のログを取得しましょう。現場によってはログを吐き出してないところもあると思います。
その場合は、自分でログを吐き出すなりして、ログを取得しましょう。このログの情報は、4.で切り分けする時に必要になってきます。

#3. 上長・リーダーに報告
ここは、誰に報告するかは現場によってくると思いますが、一旦必ず現状を報告しましょう。
そのまま、切り分け、原因まで自分で調べてからすぐにわかるなら良いですが、緊急性の高いものだったり、時間がかかりそうなら一旦現状を報告しましょう。

#4. どこが問題かの切り分け
組み込み系だとどこのモジュールなのか。Web系だとざっくりですが、フロントなのかサーバーサイドなのか。
2.で取得したログの情報、ソースコード、（その他設計・実装資料など）を頼りに、どこでおかしくなっているのかを切り分けて行きます。

#5. 原因調査
4.で切り分けができて、うちに問題があった場合、実際のどこの処理でこけているのか、問題が起きていのか原因を調査します。

#6. 上長・リーダーに報告
原因がわかったならば、その内容をすぐに報告しましょう。

#7. 対策検討・工数見積もり
まず、原因から対策方針を検討してきます。
対策方針が決まったら、自己完結せずにレビューをしてもらいましょう。レビューしてもらうことでその方針が問題ないか早めに気づくことができます。

対策方針が定まったら、工数を見積もっていきます。ここで、見積もる時に無理な見積もりはやめましょう。急いで修正してデグレを引き起きしてしまう方がなおさら最悪です。8.で調整ができるのであれば、自分が本当にできる`工数 + リザーブ(2日）`で見積もるとよいかと。


#8. 上長、リーダーに報告し、日程調整
7.で見積もった内容を報告。
もし、それでもっと早く仕上げてくれってなった場合は、人をかけるなりして対応しましょう。

#9. 実装資料の作成
自分の場合、こんな感じで資料に残して実装資料を作成しています。
めんどくさいと思うかもしれませんが、後から見返したときになんでこんな実装したんだっけとか、
意味の無いな実装をしないようにするためです。

 - 原因
 - 混入経緯（いつ混入？わからなくても予測）
 - 他に似たような問題がないか（機能又はソース）
 - 再発防止策（原因と混入経緯から作り込みによる防止／確認時に置ける防止策）
 - どのように修正するか
 - その修正での影響範囲 

#10. 実装／コードレビュー
実装が完了したら、ミスや考慮漏れを防ぐためにその内容をレビューしてもらいましょう。
レビューを依頼するときは、どのような観点で見て欲しいかを事前に伝えておくと、レビューの
質がよくなります。
Rubyでワードクラウドを用いたTwitterトレンドの可視化

# はじめに
Twitterのトレンド一覧では、単語しか出てこず、一体何に関する話題なのか分からない。
ということで、トレンドからツイートを取得してワードクラウドを作成することで、一目でどんな話題で盛り上がっているのか可視化しようと思います。

せっかちな方のために、先に結果を載せときます。
トレンド"#きのう何食べた" に対する実行結果
![#きのう何食べた](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180925/876bdbca-fcab-b0e9-ced8-0f24b7add8c4.png)

# 使用技術
Ruby: 2.4.1
Mecab: 0.996

# Twitterからデータを取得
## アクセストークンの設定
まず、Twitterにアクセスするためのトークンなどを設定します。

```
require 'twitter'
client = Twitter::REST::Client.new do |config|
    config.consumer_key        = "Consumer Key (API Key)"
    config.consumer_secret     = "Consumer Secret (API Secret)"
    config.access_token        = "Access Token"
    config.access_token_secret = "Access Token Secret"
end
```

参考
[https://qiita.com/shimisunet/items/c3a0b93fb13fa82ed8be](https://qiita.com/shimisunet/items/c3a0b93fb13fa82ed8be)

## トレンドの取得
次にトレンドを取得します。

```
client.trends_place(23424856).take(3).each do |trend| # 23424856:日本のtrend
    p trend.name
end
```

## ツイートの取得
トレンドのツイートを取得します。

```
client.search(word, exclude: "retweets").take(count).each do |tweet|
    p tweet.text
end
```

# 前処理
取得したツイートに対し、

* URLの除去
* 分かち書き (Mecab)

を行います。

## URLの除去
Rubyのuriパッケージを利用します。

```
require 'uri'
URI.extract(text).uniq.each {|url| text.gsub!(url, '')}
```

参考
[http://thr3a.hatenablog.com/entry/20180315/1521079183](http://thr3a.hatenablog.com/entry/20180315/1521079183)

## 分かち書き
Mecabを利用して分かち書きをします。
副詞など、どのツイートにも出てきそうな単語は除去します。

```
require 'mecab'
tagger = MeCab::Tagger.new
wakati = tagger.parse(text)
wakati.delete!("EOS")  # 分かち書きの結果に"EOS"が出てくるため除去
wakati = wakati.split("\n")  # 単語ごとに分割
words = []
wakati.each do |w|
    word = w.split("\t")  # タブ文字前に単語、後に単語の情報があるため分割
    if word[1].include?("形容詞") || word[1].include?("名詞")
        unless word[0] == "#"  # "#"は名詞に分類されるため除去
            words.push word[0]
        end
    end
end
```

# ワードクラウド作成
解析に入ります。
分かち書きの結果、トレンド内のツイートに出てくる単語を格納した配列を作成します。
それを元にワードクラウドを作成します。

magic_cloudの裏側ではImage Magickが動作しており、:font_familyに'Arial Unicode'を指定することで日本語に対応できます。(重要)

```
require 'magic_cloud'
font = 'Arial Unicode'
words =  words.group_by(&:itself).map{ |key, value| [key, value.count] }.to_h
cloud = MagicCloud::Cloud.new(words, rotate: :none, scale: :linear, :font_family=>font)
cloud.draw(500, 250).write("#{word}.png")
```

参考
[Rubyで配列内の重複する要素を数える方法](https://techacademy.jp/magazine/19771)
[https://github.com/zverok/magic_cloud](https://github.com/zverok/magic_cloud)

# 考察
2019年6月22日の夜ごろのトレンド"#きのう何食べた"に対して、以下の結果が得られました。
![#きのう何食べた.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180925/484c52cb-569d-d915-207f-a626d3577c6b.png)

とりあえず、どんな話題なのか読み取れそうです。
私の考察としては、

* ドラマらしい
* 来週最終回らしい
* ~~個人的にはyajuが気になる。~~

といったところです。
ソースコードのコメントって必要なの？

ソースコードのコメントについて必要なのか考えてみました。

僕自身、コメントに関しては書いてる方で、
指導して頂いた先輩たちにも「コメントを書いてね」と言われてきました。

それに対して、疑問も浮かばなかったけど、
実際の動作に影響がないのに何で書いているんだろうと振り返りました。

## 何でコメントを書いていたのか
僕自身、そこまで生産性のあるプログラムを書けている訳ではないため、
機能を把握して貰える様に書いていました。
説明書のようなものです。


## 何で説明書が必要だったのか
複雑なソースコードを使用するには説明書が必要ですよね！

ん？

(つд⊂)ｺﾞｼｺﾞｼ 
　 
(；ﾟдﾟ) ・・・ 

気付かなかったけど
それって単純にソースコードが悪いんじゃ...


## どんなソースコードだったらコメントはいらないの？
適切な名前で、他に依存しない、役割が明確ならばコメントは不要
ついでにソースコードの質も上がるのではないかと思います（本来こっちが本質ではありますが）


## 理想は可能な限り書かない
コメントを書く必要なソースコードは、粒度が大きい可能性があり、
ソースコードで表現できないからコメントが必要になると思います。

TODOや仕様を書きたい場合もありますが、別途タスク管理ツールを使うことをお勧めします

## まとめ
プロジェクトによっては、コメントを細かく書く事もあると思いますが、必要以上のコメントは可読性も悪くなりコストもかかると思います。
そのコメントが間違っている可能性もないとは言い切れません。

コメントではなくコーディングに注力したいですね♪

## 追記
コメントはなるべく書かないと記載しましたが、
facadeパターン等で中身が追いにくいものに関しては書いてもいいと思いました。
【VBA】Classモジュールの書き方_Initialize版

# ClassモジュールのInitializeの使い方
　ClassモジュールでInitializeを利用すると、Classモジュールを呼び出した時に自動的に処理が走るプロシージャを作れます。

## 実演
```VB:Class_Initialize
'このClassモジュール名は「Class」です。
Private Sub Class_Initialize()
 Msgbox "Hello World"
End Sub
```
これを呼び出すとこんなかんじですね。

```VB:CallTest
Sub CallTest()
 Dim Class As Class
 set Class = New Class
End Sub
```

classモジュールを呼び出すと処理が走るので、こういう感じになります。

## 応用編
前回紹介したClassモジュールの使い方を、Initialize機能でキレイにします。

```VB:前回の振り返り
'Classモジュール
'FSOのプロパティ
Property Get FSO() As Object
  Set FSO = CreateObject("Scripting.FileSystemObject")
End Property

'WSHのプロパティ
Property Get WSH() As Object
  Set WSH = CreateObject("Wscript.Shell")
End Property

'ここから標準モジュール
'マクロブックに存在するファイルを全部コピー
Sub CopyFile()
 Dim obj As New CallObject

 For each File In obj.FSO.GetFolder(ThisWorkbook.Path).Files
   obj.WSH.Run "cmd.exe /c XCOPY " & File.Path & " " & "backup_" & File.Path
 Next
End Sub
```

プロパティには通常オブジェクトの性質を示すデータを格納するわけだから、上記の使い方はそもそも邪道というか間違いですね。

こういう使い方がよいです。

```VB:修正版
'Classモジュール
横断定義
Private FSO As Object
Private WSH As Object

Private Sub Class_Initialize()
  Set FSO = CreateObject("Scripting.FileSystemObject")
  Set WSH = CreateObject("Wscript.Shell")
End Sub

'ここから標準モジュール
'マクロブックの存在するフォルダ内のすべてのファイルをコピー
Sub CopyFile()
 Dim obj As New CallObject
 'Classオブジェクトは上記のように一行で定義することができます。
 'ただし以下のように明示的に呼び出している場合のみ。
 For each File In obj.FSO.GetFolder(ThisWorkbook.Path).Files
   obj.WSH.Run "cmd.exe /c XCOPY " & File.Path & " " & "backup_" & File.Path
 Next
End Sub
```

このような使い方をすると、各オブジェクトを都度呼び出すという必要がないのです。
`Dim obj As New CallObject`の部分でFSOやWSHにオブジェクトを格納しているので
メモリを余分に食うようなことがないです。

念のためInitializeを閉じる用にTerminateも用意しとくといいかもしれないですね。

なお、FSO やWSHはグローバル変数として使うと、定義内容を書き換えられてしまうので、プライベート関数として使いましょう。
プライベート関数を使った場合でも、書き換え用アクセサ(Property Let)を使えば書き換えられますが
これらは定数として使うべきなので、間違ってもこれらオブジェクトの書き換え用アクセサは用意しないようにしましょう。

以上。
OculusQuest / OculusGo / Androidのリモート接続をスクリプトで自動化する

# はじめに

Androidは `adb tcpip [port]` と`adb connect [ipaddr:port]` でリモート接続できます。
ですが何度も実行するのは面倒なのでスクリプトで自動化しました。

# 使い方

https://gist.github.com/shiena/e0bfbd465fefae424e42b909f24e5434

1. ここからOSに合わせたファイルを以下のように保存します。
    * Windowsは`adb-connect.bat`を改行コードCRLFで保存
    * macOSとLinuxは`adb-connect.command`を改行コードLFで保存して`chmod +x adb-connect.command`で実行権限を付ける
1. 変数 `ADB` をadbコマンドのフルパスに書き換えます。

あとはそのまま実行するだけです。2台以上のAndroidがUSB接続されているとそれぞれリモート接続するか選択できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8995/d07ffc8c-3939-111a-88ee-e6a4394035c6.png)

# 所感

Windowsのバッチファイルでも意外と文字列処理できるもんですね。
【Git】git ignoreを使ってみよう

#はじめに
今回はGitを使用する際に重要なgit ignoreについて紹介します！

#git ignoreとは？
gitを使って開発を行なっていると、管理対象にしたくないファイルが出てくることがあります。
分かりやすいところだと、

* .DS_Store(プロジェクトのmetaデータ)
* APIKey

などが挙げられると思います。例えばAPIKeyをgitの管理対象にした状態で誤ってGitHubにプッシュしてしまうと、APIKeyを第三者に不正に利用される危険があります。git ignoreを使うことでgitの管理外に置くファイルを設定し、このような問題を解消することができます。

#1. コミット前にgit ignoreを設定する方法
Sampleフォルダを作成し、その中に作成したsample.txtをgitの管理対象から外す方法を紹介します。
###Sampleフォルダを作成

```terminal
$ mkdir Sample
```

###Sampleフォルダ内に「sample.txt」と「.gitignore」を作成

```terminal
$ touch sample.txt
$ touch .gitignore
```
###sample.txtをgitの管理対象から外す
Sampleディレクトリにいる状態で以下のコマンドを打ち込むとsample.txtと.gitignoreが作成できているのが確認できるかと思います。(.gitignoreは隠しファイルなので`ls`だけでは確認できません。)

```terminal
$ ls -a
```

`.gitignore`をテキストエディタで開き、管理対象外にしたいファイル名を書き込みます。今回は`sample.txt`を書き込むだけでOK! 

#2. コミットを行なった後にgit ignoreを設定する方法
.gitignoreを作成する前にコミットを行なっていると、上記の手順だけでは特定のファイルを管理対象外にすることはできません。その場合はまずプロジェクトのディレクトリに移動し、1と同様に「.gitignore」を作成の後、.gitignoreに管理対象外にしたいファイルを書き込みます。その後ターミナルで以下のコマンドを実行します。(sample.txtを管理対象外にする場合) 以下のコマンド実行後にコミットを行えばOK!


```terminal
$ git rm --cached sample.txt
$ git add .
```
ActiveSupport::TimeZoneを0オフセットでインスタンス化すると1時間ずれる

指定したオフセット値（JSTなら9時間）で `ActiveSupport::TimeZone` を作り、それをもとに `ActiveSupport::TimeWithZone` インスタンスを作りたい。

```ruby
jst = ActiveSupport::TimeZone[9]
# => #<ActiveSupport::TimeZone:0x00007fbbe3b034b0 @name="Osaka", @utc_offset=nil, @tzinfo=#<TZInfo::TimezoneProxy: Asia/Tokyo>>

jst.now
# => Fri, 21 Jun 2019 21:24:26 JST +09:00
```

+9は、問題なし。

```ruby
utc = ActiveSupport::TimeZone[0]
# => #<ActiveSupport::TimeZone:0x00007fbbe3afb030 @name="Casablanca", @utc_offset=nil, @tzinfo=#<TZInfo::TimezoneProxy: Africa/Casablanca>>

utc.now
# => Fri, 21 Jun 2019 13:25:48 WEST +01:00

utc.tzinfo.current_period.utc_offset                      
# => 0
```


ファッ！？ `+00:00` が期待されるところ `+01:00` となっている！？
TZInfoのutc_offsetは0を指しているようだが...

そもそもoffsetだけではtimezoneと言えないのでやろうとしていることが強引な気もするが、それはさておき、どうやるのが正解なのだろうか。

---

関係ありそうだが、詳しくは読んでない。
https://github.com/tzinfo/tzinfo/issues/98 

---

動作確認環境
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin16]
activesupport (5.2.1)
tzinfo (1.2.5)
IntelliJ IDEAで、Nuxt.jsのコンポーネント間ジャンプがしたいんや

## はじめに

IntelliJ IDEA、使ってますか？
僕はエディタなんて軽さ命だと思ってたので今までVSCode一筋だったんですが

**「IntelliJはいいぞ」**

という声を最近ちまちま聞いていたので、使ってみています。
ただ、VSCodeだとプラグイン入れるだけでできる**コンポーネント間移動**が、IntelliJだとそのままではできなかったので、いい感じになるようにしてみました。

## webpack.config.jsを作って、IntelliJに読ませる

IntelliJがそのままの設定だとコンポーネント間移動してくれない理由は、デフォルト設定だとルート直下の`webpack.config.js`を読むようになっているらしく、Nuxt.jsのプロジェクトは`nuxt.config.js`なので読めない、ということです。
ググって見ると、`nuxt.config.js`を読ませるようにして、その中に`@`と`~`のエイリアスを登録するといいよって書いてありましたが、あんまり`nuxt.config.js`に書きたくないよなーという思いと、できれば設定あんまりいじらなくていいように、新しく`webpack.config.js`をプロジェクトルートに置くことにしました。

```bash:shell
$ yarn create nuxt-app sample-intellij
$ cd sample-intellij
$ vim webpack.config.js
```

```js:webpack.config.js
const path = require('path');

module.exports = {
  resolve: {
    extensions: ['.js', '.json', '.vue', '.ts'],
    root: path.resolve(__dirname),
    alias: {
      '@': path.resolve(__dirname),
      '~': path.resolve(__dirname),
    },
  },
},
```

これで読み込まれない場合は、`Preferences → Languages & Frameworks → JavaScript → Webpack`でパスを追加してください。


## webpack.config.jsをgitの監視対象外にする
時には、IntelliJ IDEAを使っているのが自分だけで、プロジェクトルートに置いた`webpack.config.js`をgitの監視対象外にしたくないときが出てくるかもしれません。
また、監視対象外にしたいけど、`.gitignore`にも登録できない事情があるかもしれません。
そんなときは、プロジェクトのgitの設定をいじって、自分だけ監視対象外にしてあげましょう。

```bash:shell
$ vim ./.git/info/exclude
```

```shell:exclude
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

webpack.config.js # ←を追加
```

こうすることで、自分のプロジェクトだけ`webpack.config.js`を監視対象外にしてくれました🎉

## おわりに
そんなこんなで、ちょっと便利になりつつあるので、フロントエンド開発はVSCodeからIntelliJ IDEAに移行していく予定です。
便利な機能を知ってる人がいたら、教えてください🙏


## 2020/06/05追記

最近はプロジェクトルートにIntelliJの設定ファイルを置いています。
ファイル名は何でもいいのですが、わざわざ`webpack.config.js`の設定をしなくていいので楽です👍

```js:intellij-config.js
/* eslint-disable no-undef */
// r.f. https://youtrack.jetbrains.com/issue/WEB-22717#focus=streamItem-27-1558931-0-0
System.config({
  paths: {
    '@/*': './client/*',
    '~/*': './client/*',
    '@@/*': './*',
    '~~/*': './*',
  },
});

```
SharePointとその周辺技術を紹介している公式外サイトリンク集

# はじめに
人にSharePointどこから勉強したらいい？と聞かれるので、リンク集（MS公式除く）作りました。
説明は読まなくてもいいので、ここで紹介したサイトは読んでおいてくれたら嬉しい。
QiitaでもRESTの投げ方とか、PowerShellのPnPプロビジョニングについてとか投稿してる人がぼちぼちいらっしゃるので、読んでみると勉強になります。
（ですます調ここまで）

# 技術PickUp
サイトを全部見るなんて無理、という時はとりあえずその辺の書籍＋ここあたりおすすめ。
## 1.汎用性高め
[SharePoint Online のモダン サイトでサイトテンプレートを作成する方法](https://trivia365.hatenablog.com/entry/2018/07/04/235125)

[Microsoft Flow を使って SharePoint Online に保存されたドキュメントの承認ワークフローを作ってみる](https://idea.tostring.jp/?p=3540)

[[PowerApps] SharePoint リストフォームのカスタマイズ (1)](https://shanqiai.weblogs.jp/sharepoint_technical_note/2018/01/customizesharepointlistbypowerapps-1.html)

## 2.それなりに込み入った事をやりたい時

[XML スキーマと OData エンティティー・データ・モデル (EDM) のデータ型のマッピング
](https://www.ibm.com/support/knowledgecenter/ja/SSGR73_7.5.1/com.ibm.wci.doc/OData_datatype_mapping.html)RESTでクエリ投げる時に、Odata EDM⇒Camlのデータ型対応の参考に


# MS公式外サイトで特におすすめ

## [idea.toString();](https://idea.tostring.jp/)
SharePointのコンサルもやっている（株）内田洋行の太田さんのブログサイト。
SharePointってタグがついてる記事は全部読んで欲しい。
シンプルで凄く見やすいページ構成でMarkdown記法のお手本のよう（本筋からずれるが）。
あと、ブログじゃないけど[太田さんのSlideShare](https://www.slideshare.net/hirofumi_ota)も参考になる。
サイト内お勧め：[SharePoint Online モダン ページで “ちょっと” カスタマイズできる方法を模索してみる](https://idea.tostring.jp/?p=3986)

## [鍋綿ブログ](https://www.micknabewata.com/)
承認フローについて色々書いてくれているので、一時期死ぬほど読んだ。（今も読んでる）
SharePointの承認フローを構成する上でもはや必須となったFlow(InfoPathは死んだのだ…）についても
テストケースサンプルを記事にしてくれているのでありがたさMAX。
サイト内お勧め：[【初心者向け】SharePoint Framework (SPFx) 入門](https://www.micknabewata.com/entry/sharepoint/spfx/newbee)

## [SharePoint Technical Notes(オフィスアイ）](https://shanqiai.weblogs.jp/sharepoint_technical_note/)
「ひと目で分かる」シリーズ(Office365,SharePointServer2016他）の著者の平野愛さんの運営しているブログ。
サイト見るっていうより、本を買ってくださいお願いします（私も持ってます）。
そしたらSharePoint2016のServerじゃないやつとか、2019とかOnline（すぐ変わるから無理か？）の本を出してくれるかもしれない…（切実）
当たり前ですが、サイトも非常に為になる。
サイト内お勧め：[[SharePoint Online] サイトページのセクション レイアウトの例](https://shanqiai.weblogs.jp/sharepoint_technical_note/2019/03/sharepoint-online-my-favorite-site-page-layout.html)

## [もくだいさんのOffice365至高のレシピ](https://mokudai.jp/)
至高とか書いてあるから庶民には理解できないのかなと思ったが、どちらかといえば初心者に優しいサイト。
ナレッジベース（今のところ配置は画面右上）を開いてSharePoint Onlineで色々出てくる。
サイト名どおりO365全般を紹介しているので、SharePointをみっちり解説しているわけでないことは注意。
サイト内お勧め：[SharePointのドキュメントライブラリをファイル置き場として使う際のアンチパターン](https://mokudai.jp/knowledge-base/spo-tips/spodoclib-antipattern/)

## [吉田の備忘録](https://memo.tyoshida.me/)
MSの何か凄い人。Global Black Beltという称号をお持ちらしい。あと、アイコンのひよこがかわいい。
SharePointのカスタム入力フォームやらFlow連携やらでシェアポと切っても切り離せないPowerAppsの技術紹介が多い。
Qiitaには最近投稿していないようだが、Twitterでよく技術系呟きをしている（サイト上部から全部行ける）
de:code(MSのカンファ)で実際お会いしたことがあるが、こちらの伝えたアプリをPowerAppsでちゃちゃっと5分で作ってくれた凄い人。
PowerAppsはローコードではあるけれどもノンコーディングではないのではなかろうかという気がしないでもないが（勿論求めるレベルによる）「ね？簡単でしょ？」と言いながらナチュラルにスパルタ教育を施してくれる。そこそこ勉強する気があるならお勧め。
サイト内お勧め：[PowerAppsを始めるために必要なリンク集まとめ](https://memo.tyoshida.me/powerapps/useful-websites-to-start-powerapps/)

## 番外：[SharePoint Maniacs](http://sharepointmaniacs.com/)
懇切丁寧に色々書いてあって、とにかく読んでくれ！…と言いたい所なのだが最終更新が2015年で情報が古いという致命的な弱点がある。
Sharepoint含め、Office365サービスは流れが速いので、どうしても今の現状と食い違いが出ている。
何か色々あった事が会社のサイトから推察されるが、どうかまた更新して欲しい…。
Benefits of Telemedicine App Development

In order to change the healthcare industry landscape telemedicine app development has begun. It is a subset of telehealth, which uses a wide range of modern technologies and specializes in providing medical services from a distance with the help of software and communication tools.

According to Statista the telemedicine market size will grow to $41.2 billion by 2021. It is obvious that telemedicine apps are becoming more popular among patients, medical establishments, and investors.

![telemedicine app development](https://d32myzxfxyl12w.cloudfront.net/images/blog_images/eccc98ca3e5527206e384491e6245e0a87ebb89d.jpg?1559202792)

###Benefits of Telemedicine App Development

Telemedicine helps to support the healthcare system across patients, doctors, and medical establishments. The major task of telemedicine services is to provide remote doctor visits, increase medical service efficiency, and monitor health conditions from a distance.

Read on to learn about the main advantages of telemedicine app development.

1) Availability of medical services

At first, a telemedicine app provides healthcare service for distant regions with no access to clinics. Besides, there is a problem of healthcare personnel shortage, especially in rural areas. These apps can help veterans, elderly people, school kids, etc, reach medical services easily.

2) Convenient and time-efficient medical care

You don't have to spend time visiting a hospital and waiting in line to get a preliminary doctor consultation. This process could take ages, if you need to visit a few different specialists.

Telemedicine apps can be used to make an appointment for remote medical help. Patient and doctor can connect at a convenient time and treatment starts quickly and more effectively. Moreover, telemedicine applications can be widely used in emergency care.

3) Medical record keeping

Telemedicine applications help doctors access and store medical data more effectively. Nowadays it is difficult to access these records and transmit them to other doctors for better treatment prescriptions.

4) Unified patient management and monitoring system

Telemedicine app development solutions can help with updates to prescriptions, consultations, chronic disease monitoring, and so on.

5) Efficient time management of healthcare specialists

With the help of telemedicine apps, doctors can organize their workload more effectively and examine more patients correctly. The research shows that about 15% of doctors experience burnouts and depression. Telemedicine solutions can offer a better life-work balance for doctors.

Follow this [article](https://mlsdev.com/blog/telemedicine-app-development) to find out more about the benefits of telemedicine app development.
2020年東京オリンピックチケット当落発表の負荷分散について考察してみた

# はじめに
先日2020年開催の東京オリンピックのチケット当落発表があり、エンジニア目線で面白い負荷分散方法だなと思ったので、どういったところが面白いと思ったのか綴ってみます。
なお、私はチケットを申し込みをしていないので、周りの人から聞いた情報となります。

※本記事は裏付けや根拠など一切ない主観的かつ個人の感想なので、事実とは異なります。

# オリンピックの当落結果を知る方法
1.当落メールが届く
2.公式サイトでの当落確認

上記2つの方法で確認ができます。

# 負荷分散方法
## ①すべて落選した人には早い段階でメールで落選を伝える
周りの人を見ていると申し込んだチケットがすべて外れた人は朝早い段階で落選メールが届いていました。
逆に一つでも当選している人には朝の段階ではメールは届いていませんでした。

このことから推測できる負荷分散は、すべて落選した人に早めに伝えることによって、サイトへのアクセスを減らすことができるのではないかと思いました。
わざわざサイトで確認する必要がないので、アクセス集中を避けられることにより負荷軽減ができると感じました。

全員に同時にメールが来ないって斬新だなって思いました。

アクセスだけでなくメール配信の負荷も分散されていますね。

## ②公式サイトで確認する場合に待ち情報が表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207298/cf829553-42e0-ffa3-b1ed-8c5c1253d4a8.png)
引用：https://www.huffingtonpost.jp/entry/olympic-ticket_jp_5d0ae7b1e4b09f5a54b5e888

サイトに当落確認のためにアクセスすると上記のような画面が表示されます。

このことから推測できる負荷分散は、「すぐには確認できないこと」、「どのくらい待てば確認できるか」、「何人くらい待っているか」という情報をユーザーが知ることで連続でアクセスすることを回避させることができます。
ユーザーのアクセス集中を待ち時間、待ち人数を伝えることで、連続でアクセスして確認するというシステム泣かせのアクションを抑制することができると思いました。

また、これは完全な推測ですが、システム的には初回アクセス時に確認待ちキューにデータを入れ、順次キューのデータを処理して、当選を伝えているのではないかと思いました。
（それだとDB接続とか発生してしまうので、負荷分散できないのでフロントだけで解決できる仕組みとかも利用しているのかなとか色々思いました。残念ながら私の知識ではそこまで想像することはできなかったですが、、）

# 最後に
負荷分散というとLBやマイクロサービスとか色々ありますが、こういったユーザーの行動抑制という形で分散する方法もあるのだなと新たな気づきになりました。
使い捨てのシステムで予算の限られた中では良き選択なのではないかなと思いました。(AWSとかで大量にサーバ建てて負荷分散とかもできると思うけど、費用対効果が見合わないのかなと思いました)

エンジニアとしてはもっと深堀して知ってみたいなーと思ったりもしました（笑）

最後までお読みいただきありがとうございました。
CLionで競プロ用に複数のmainを扱いたい

## 前置き
競プロ（AtCoder）をやっていると、
「いま触っているmainを動かしたいんじゃー！」
と思うようになりました。

先駆者様のCMakeFileList.txtを参考にして、それっぽいことが出来るようになったので置いておきます。

## CMakeFileList
以下のものから必要な部分をCMakeFileList.txtに追加します。
「Reload CMake Project」して反映します。

**・注意点**
cppファイル名とその上のディレクトリ名でビルド構成の名前にしているので、
AtCoder/ABC/001/a.cpp
AtCoder/AGC/001/a.cpp
という配置だと名前が重複（001_a）して動きません。

AtCoder/ABC/abc001/a.cpp
AtCoder/AGC/agc001/a.cpp
のようにcppを入れているディレクトリ名がユニークになるようにしてください。

```cmake:CMakeFileList.txt
cmake_minimum_required(VERSION 3.14)
project(AtCoder)

set(CMAKE_CXX_STANDARD 14)

# 指定したとこ含めて、cppファイルがあったらビルド構成作る
MACRO(CREATE_BINARY target_dir)
    # 指定したディレクトリの中身一覧（孫までは取れない）
    FILE(GLOB children RELATIVE ${target_dir} ${target_dir}/*)
    FOREACH(child ${children})
        SET(path ${target_dir}/${child})
        # ディレクトリなら更に潜る、生成されるディレクトリは除外
        IF(IS_DIRECTORY ${path} AND NOT ${path} MATCHES "cmake-build-debug")
            CREATE_BINARY(${path})
        # cppファイルならバイナリー作成
        ELSEIF(${path} MATCHES \.cpp$)
            # バイナリー名を用意
            SET(binary_name "")
            STRING(REGEX MATCH [^\/]+\/[^\/]+\.cpp$ binary_name ${path})
            STRING(REGEX REPLACE "\/" "_" binary_name ${binary_name})
            STRING(REGEX REPLACE "\.cpp" "" binary_name ${binary_name})
            # 実行可能ファイルを追加
            ADD_EXECUTABLE(${binary_name} ${path})
        ENDIF()
    ENDFOREACH()
ENDMACRO()

CREATE_BINARY(${CMAKE_CURRENT_SOURCE_DIR})
```

## 運用
【その１】
コンテスト追加するなどして、フォルダ構成を変えたら
「Reload CMake Project」する

【その２】「おお、勝手に切り替わる！素敵！！」
編集中のmain()内で右クリックして、RunとかDebugする
※ main()内にカーソル無いとRunとDebug出ない（solve()とかで書いてる場合）
※ CLionの右上からでもビルド構成を選択できる（多くて間違いそう）

## あとがき
main()内で右クリックでそのビルド構成が勝手に選択されて動くことに気づいたので、その勢いで書きました。
何番煎じか分かりませんが、何かの役に立ったらいいなー。
Gitで複数アカウントを使った時に困って使ったコマンド集

# Gitで複数アカウントを使った時に困って使ったコマンド集
macを使っています。
備忘録的に書いてみました:bow_tone1:

## グローバルのGitユーザーを確認
```
git config --global --list
```

## ローカルのGitユーザーを確認
```
git config --local --list
```

## ローカルのGitユーザーを設定
```
git config --local user.name "hoge"
git config --local user.email "hogehoge@email.com"
```
## すでにしてしまったコミットのAuthor、Commiterを確認
```
git log -1 --pretty=full
```

## すでにしてしまったコミットのAuthor、Commiterを修正
```
git filter-branch -f --env-filter "GIT_AUTHOR_NAME='hoge'; GIT_AUTHOR_EMAIL='hogehoge@email.com';GIT_COMMITTER_NAME='hoge'; GIT_COMMITTER_EMAIL='hogehoge@email.com';" HEAD
```
Railsの起動エラーとMySQLのエラー解除方法（個人メモ）

Railsの起動エラーと、MySQLのエラー解除方法を個人的にメモする。
【PC：MacBookPro2012(13-inch, Mid 2012)、MacOS Mojave 10.14.4】
【ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin18]】
【Rails 5.2.3】
【mysql  Ver 8.0.15 for osx10.14 on x86_64 (Homebrew)】


#MySQLのエラーについて。
まずはmysqlの場所を確認。

```
$ which mysql
/usr/local/bin/mysql
```

MySQLサーバーを起動させる。

```
$ mysql.server start
Starting MySQL
...... ERROR! The server quit without updating PID file (/usr/local/var/mysql/*****.local.pid).
```

PIDファイルを確認する。

```
$ ls -la /usr/local/var/mysql/*****.local.pid
ls: /usr/local/var/mysql/*****.local.pid: No such file or directory
```

MySQLサーバーをストップしてみる。

```
$ mysql.server stop
ERROR! MySQL server PID file could not be found!
```

sudoを入れて起動してみる。

```
$ sudo mysql.server start
Password:
Starting MySQL
. ERROR! The server quit without updating PID file (/usr/local/var/mysql/*****.local.pid).
```

安全にMySQLを起動してみる。

```
$ mysqld_safe
2019-04-24T03:34:24.6NZ mysqld_safe Logging to '/usr/local/var/mysql/*****.local.err'.
2019-04-24T03:34:24.6NZ mysqld_safe Starting mysqld daemon with databases from /usr/local/var/mysql
2019-04-24T03:34:29.6NZ mysqld_safe mysqld from pid file /usr/local/var/mysql/*****.local.pid ended
```

とりあえずアンインストールしてみる。

```
$ brew uninstall mysql
Uninstalling /usr/local/Cellar/mysql/8.0.15... (267 files, 234.6MB)
```

ちゃんと削除できたか確認。

```
$ which mysql
（何も出てこない）
```

再度インストールしてみる。

```
$ brew install mysql
```

これでmysql.server startしてもエラーだったので、上の操作を繰り返してみたけどダメ。

「PIDファイルが見つからない」ので、ファイルの生成をしてみる。

```
$ /usr/local/var/mysql/mysql > touch /usr/local/var/mysql/*****.local.pid
-bash: /usr/local/var/mysql/mysql: is a directory
```

奇跡的に起動しないか願いを込めて。

```
$ mysql.server start
Starting MySQL
...... ERROR! The server quit without updating PID file (/usr/local/var/mysql/*****.local.pid).
```

どこかで見つけたこのコマンドを入力してみる。

```
$ /usr/local/var/mysql/mysql > sudo mysql.server restart
-bash: /usr/local/var/mysql/mysql: is a directory
```

同じかい！！(ノ_＜)

```
$ sudo chown -R _mysql:_mysql /usr/local/var/mysql /tmp/mysql.sock
Password:
```

何やらパスワードを求められた。。。いけるのか？

sudoで起動させてみよう。

```
$ sudo mysql.server start
Starting MySQL
..... ERROR! The server quit without updating PID file (/usr/local/var/mysql/*****.local.pid).
```

あかんのかい！(T . T)

sudoなしで起動できるようにするらしいコマンド。

```
$ sudo chown -R `whoami`:admin /usr/local/var/mysql /tmp/mysql.sock
```

起動させてみる。

```
$ mysql.server start
Starting MySQL
.. SUCCESS! 
```

**キターーーーーーーーー！！！！！！♪───Ｏ（≧∇≦）Ｏ────♪**
よーし！早速Railsをローカル環境で表示させてみよう。

Railsのシステムを起動。

```
$ rails s
```

ブラウザでlocalhost:3000を入力。（成功なら画面にRailsの初期画面が表示される）

**なんとエラー！！恐怖の赤い画面！！**
ActiveRecord::NoDatabaseError (Unknown database 'hello_sample7_development'):
**え、データベースがない・・・？∑(ﾟДﾟ)**

ということでデータベースを作成。

```
$ rails db:create
Created database 'ファイル名_development'
Created database 'ファイル名_test'
```

再度Railsのシステム起動。

```
$ rails s
```

**Railsの初期画面が出た！！！☆*:.｡. o(≧▽≦)o .｡.:*☆**
Railsのマイグレーションについて

マイグレーションに関する備忘録


#1.マイグレーションファイルの実行状況を知る方法

以下のコマンドをターミナル上で実行する。

```
rake db:migrate:status
```

そうすると、以下のような表示がされる。

```
Status   Migration ID    Migration Name
--------------------------------------------------
   up     20190618115638  Devise create users
   up     20190620183857  Create groups
   up     20190620183912  Create group users
  down    20190621063102  Add devise to users
```

up 　　→　マイグレーションファイル実行済み
down　→　マイグレーションファイル未実行

#2.マイグレーションファイルを修正する方法

２つの修正方法を紹介する。

1つ目の方法
①以下のコマンドを実行して、一度マイグレーションファイルが実行される前の状態に戻す。

```
rake db:rollback
```

この時に、DB(データベース)上のカラムなどが消去されているかを確認する。

ちなみに、マイグレーションファイルの変更履歴を確認したい場合は、schema_migrationsを見れば、今までの変更履歴が確認できる。
db/schema.rbのディレクトリにある。
https://gyazo.com/e2d48570c5a046a8f425e56838aae0e6


②マイグレーションファイルの中身(カラム名やカラムの型など)を修正する。
③再度、以下のコマンドを実行して、マイグレーションファイルを実行する。

```
rake db:migrate
```


2つ目の方法
①以下のコマンドで、新たなマイグレーションファイルを作成する。

```
$ rails g migration クラス名
```
※クラス名は、処理と対象を書く。usreテーブルにnameカラムを追加したい場合は、以下のようになる。

```
rails g migration AddNameToUsers name:string
```

②修正箇所を正しい内容に変更するためのマイグレーションファイルを作成する。
③マイグレーションファイルを実行する。


#3.一度実行したマイグレーションファイル自体の内容を変更あるいは、ファイル自体を削除しない方がいい理由


アプリケーションのファイルをデプロイ先にpushし、マイグレーションファイルの実行をした時、ローカル環境と異なったDB(データベース)ができてしまったり、エラーになってしまうから。

＜参考記事＞
・https://qiita.com/usizou/items/6dcdea46ec0b4a89c661
・http://railsdoc.com/rake
・https://qiita.com/azusanakano/items/a2847e4e582b9a627e3a
NuxtでQRコードを読み込んでなにか処理をする

# 概要
今作成している機能で、WebアプリからQRコードを読み取り商品情報を取得し決済するという実装が実用になった

# 前提
Nuxt.js 2.4
SSR
[vue-qrcode-reader](https://github.com/gruhn/vue-qrcode-reader)
[参考資料](https://qiita.com/blachocolat/items/07e0ca55dfbdb963dc5b)

# 実装方法

## インストール

```
npm install --save vue-qrcode-reader
```

今回は、SSRなのでそのまま使用すると動かないみたいなので
プラグインを使用してクライアントサイドのみで実行するようにします。

```plugin/vue-qrcode-reader.js
import Vue from 'vue'
import VueQrcodeReader from 'vue-qrcode-reader'

Vue.use(VueQrcodeReader)
```

```nuxt.config.js
plugins: [
    ~
    { src: '~/plugins/vue-qrcode-reader', ssr: false }
],
```

`<qrcode-stream>`を使用すれば簡単にQR読み取り機能が実装できる
onDecodeで読み取ったデータの処理を行うことができる

```js
<template>
  <div>
    <p class="error">{{ error }}</p>

    <p class="decode-result">
      Last result: <b>{{ result }}</b>
    </p>

    <qrcode-stream @decode="onDecode" @init="onInit" />
  </div>
</template>

<script>
export default {
  layout: 'client/simple',
  data() {
    return {
      result: '',
      error: ''
    }
  },
  methods: {
    onDecode(result) {
      this.result = result
    },

    async onInit(promise) {
      try {
        await promise
      } catch (error) {
        if (error.name === 'NotAllowedError') {
          this.error = 'ERROR: you need to grant camera access permisson'
        } else if (error.name === 'NotFoundError') {
          this.error = 'ERROR: no camera on this device'
        } else if (error.name === 'NotSupportedError') {
          this.error = 'ERROR: secure context required (HTTPS, localhost)'
        } else if (error.name === 'NotReadableError') {
          this.error = 'ERROR: is the camera already in use?'
        } else if (error.name === 'OverconstrainedError') {
          this.error = 'ERROR: installed cameras are not suitable'
        } else if (error.name === 'StreamApiNotSupportedError') {
          this.error = 'ERROR: Stream API is not supported in this browser'
        }
      }
    }
  }
}
</script>

```
aptitude しまくりと思ったらリポジトリ設定の確認 (in Raspberry Pi)

## background

```
以下のパッケージには満たせない依存関係があります:
 xxxxxxxxx : 依存: xxxxx-dev しかし、インストールされようとしていません
             依存: xxxxx-dev しかし、インストールされようとしていません

E: 問題を解決することができません。壊れた変更禁止パッケージがあります。
ERROR: the following rosdeps failed to install
```


`apt` でパッケージをインストールしようとすると上記の通りのエラーが出るので、 `aptitude install xxxxxx` を使って依存しているパッケージのダウングレードをすることをして、入れたいパッケージを無理矢理入れていたのですが、あるとき気づきました。

**リポジトリの設定自体古いのではないか** :thinking:

```:OS
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 9.9 (stretch)
Release:	9.9
Codename:	stretch
```

```:sources.list
$ sudo vim /etc/apt/sources.list
deb http://ftp.jaist.ac.jp/raspbian Jessie main contrib non-free rpi
```

OSは`stretch`で最新versionだったのですが、 リポジトリの設定が`Jessie`と１世代古い設定になっていました。:scream:

何回tryしてもパッケージのversionが会わないわけだ。（そりゃそうか:sweat:）

参考までにOSのversionとnameを記しておきます。

|Debian               |codename |    Date       |
|:--------------------|:--------|:--------------|
|Debian 9             |Stretch  |2017/08/16～   |
|Debian 8             |Jessie   |2015～	        |
|Debian 7             |Wheezy   |2013～2016     |
|Debian 6.0           |Squeeze  |2011～2014     |
|Debian GNU/Linux 5.0 |Lenny    |2009～2012     |
					

## method
修正方法ですが、まずリポジトリの設定ファイル開き、`Jessie`から`Stretch`に編集します。

```:sources.list
$ sudo vim /etc/apt/sources.list
deb http://ftp.jaist.ac.jp/raspbian Stretch main contrib non-free rpi
```

で、そのままupdateをかける。

```
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get dist-upgrade
```

これで、依存関係に係わるerrorは解消しました！

## reference
[Ubuntuで依存関係が壊れている時の対応](https://blog.tizen.moe/entry/2016/02/13/202938)
[Raspberry Piの過去の古いバージョンの Raspbian OSのイメージファイルをダウンロードする方法](http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_old_version_raspbian_os_image/)
C++で手動DIしようとしたらハマった件

　最近、DI覚えました。真に作りたい機能に集中して作れるのはとってもいいもんです。

　で、ちょっとしたCSVパーサーを作ってた時のこと。CSVを読み込むにも、ファイルからなのかWEB上からなのか、そもそも文字コードの問題もあるわけです。

　そんなことをいちいちパーサーに書きたくない。そこで、読み込み部分はIRepositoryというインターフェースにして疎結合を目指そうとしました。疎結合あるあるですね。

そんな感じでザッと書いたコードがこんな感じ。

```
#include <iostream>
using namespace std;


class IRepository
{
public:
    virtual string GetText() const = 0;
};

class CSVParser
{
public:
    CSVParser(const IRepository &repository){/*なんやかんや*/}
    const char *Value(int row,int col){return "なんやかんや";}
};

class TempRepo : public IRepository
{
public:
    string GetText() const {return string("ねこ,にゃーん\ncat,meow");}
};

int main(void){
    CSVParser parser(TempRepo());
    cout << parser.Value(0,1); //(1)
    return 0;
}
```

　具体的なパーシングは省略しましたが、適当なCSV文字列を一旦TempRepoに持たせて、その文字列のカンマや改行が適切に解釈され、(1)の部分で「にゃーん」と表示されるはず。
　しかし、この行で「式にはクラス型が必要です。」のようなエラーが出てビルドさせてくれません。つまりparserがCSVParser型と認識してないんです。


ところで、クラスを引数なしコンストラクタで初期化して使うときは()を書いてはいけません。

```
CSVParser parser(); //エラー
CSVParser parser; //OK
```
()を書くと関数宣言とみなされ、意味合いが違ってきます。

症状としては近いのですが、今回は引数ありです。うーん。

```
CSVParser parser = CSVParser(TempRepo());
```
これは通りました。

じゃ、試しにキャストしてみるか。

```
CSVParser parser((const IRepository &)TempRepo());
```
通った:innocent:

ここに強く深く刻む　わすれられぬように
PHP/Laravel5で本番環境リリース後にすること

自分が、**Laravel**でローカル環境から本番環境にコピーした後、特に忘れがちなことをメモ。
各々の環境や開発ポリシーで、大きく違うところもあるかと思うので、あくまで参考程度にして下さい。

### パーミッション設定
```console
cd /var/www/html/example
chown -R <user>:apache .
find . -type d -exec chmod 750 {} \;
find . -type f -exec chmod 640 {} \;
chmod -R 770 ./storage ./bootstrap/cache
```

### Apache設定
```apache:/etc/httpd/conf.d/example.conf
Alias /example /var/www/html/example/public/

<Directory "/var/www/html/example/public">
    AllowOverride All
    Require all granted
</Directory>
```

### htaccess設定
```apache:public/.htaccess
RewriteEngine On
RewriteBase /example
```

`PHP`のビルトインサーバで開発していると忘れがち。

### .env の修正 もしくは .env.production への差し替え
```:.env
APP_ENV=production
APP_DEBUG=false
```

### .env のAPP_KEY更新
```
php artisan key:generate
```

### オートローダー最適化
```
composer install --optimize-autoloader --no-dev
```

### キャッシュ最適化
```
php artisan config:cache
php artisan route:cache
```
デュアルブートしているUbuntuのボリューム拡張を微妙だが安全に行う

#はじめに
こちらは、すでにデュアルブートをしている方向けの記事です。デュアルブート自体は[こちら](https://qiita.com/yo_kanyukari/items/2a944a300db22482c696)を参考にして私はやりました。なので少しそれを元にしての記事となっています。
#なぜ微妙だが安全な方法を？
私は、windowsとubuntu18.04をデュアルブートできるようにしているのですが、30GB程度のサイズでパーティションを作ったため、3ヶ月程度でディスクの容量が一杯になってしまいました。
なので拡張をしようとなったのですが、GPartedを使ってサイズを変更させようとしても、ディスクの後ろの方は空いていないので先頭の位置を変えざるをえず、すると/の位置が変わることにより/bootの位置が変わるためうまくブートできなさそうで、かといってGRUB2の使い方もよくわからず、どうしようか悩んだ結果微妙だが安全な方法を思いついたので、それを実行しました。
そういった、色々とよく分からなくて不安という人向けの記事なので、よく分かっている人は無視してより良い方法でやってください。
#方法
1. インストールされているものの中で、必要なものを並べて保存
2. ubuntuのバックアップを取る
3. GPartedで、拡張する分だけ場所を開ける
4. ubuntuを再インストール
5. バックアップから復旧をする
6. 1で用意したインストールするものリストを使って、再インストール

これをすることで、初期設定等は面倒かつ一部データは消えますが、ほぼ安全に拡張ができます。
消えるデータも、おそらく1でリストアップしなかった物と2でバックアップ生成に失敗したもの、ubuntu自体の初期設定程度で済むはずです。
#インストールされているものの中で、必要なものを保存
まず、インストールされているものは以下のコマンドで確認できます。

```
dpkg -l
```

この中から、今後も必要そうなものをまとめてインストールできるようなスクリプトを書いておくと楽になります。
とはいえ、見るのは面倒だと思いますし、覚えているものだけ書いてインストールするでもいいと思います。というのも覚えていないものならばそれだけ意識していないものですし、なにより必要ならまたインストールすればいいです。
#ubuntuのバックアップを取る
ubuntuのアプリケーションのところにバックアップと入力すれば、バックアップについて出てくるのでそれでバックアップを取ってください。
Googleアカウントなどのオンラインアカウントと紐つけるのをおすすめします。
また、このとき本当にバックアップが取れているかを確認するために一度バックアップを試すことをおすすめします。
#GPartedで拡張する分だけ場所を開ける
GPartedを起動します。もしなければインストールしてください。

```
sudo apt-get install gparted
```
そして、余っていてなおかつubuntuと隣合わせのディスクを必要な分だけ縮小して未割り当てのパーティションとしてください。ここで縮小した分が、ボリュームの拡張分となります。
このパーティションは未割り当てのまま一旦ほおっておきます。
もし、未割り当てのパーティションがubuntuのパーティションより後ろにあるのならばこれ以降の動作は必要なくGPartedをそのまま使って後ろに伸ばすだけでいいです。
#ubuntuを再インストールする
上の記事でやっているように、USBなどから起動をして、ubuntuのインストールを開始します。
ここで、インストール設定の途中で『Ubuntu18.04がディスクに残っていますがどうしますか？『
』みたいなことを聞かれます。
そのときに、一番上の選択肢『ディスク上のUbuntuを削除する』的な事が書かれていいるものを選びます。
このとき、勝手に未割り当ての部分も使ってインストールしてくれるようです。
#バックアップから復旧をする
ubuntuが操作できるようになったら、またアプリ一覧でバックアップを起動して、先程取ったバックアップを使って復旧をします。
#1で用意したインストールするものリストを使って再インストール
1のときに書き連ねたインストールする物リスト(スクリプト)を元に、またインストールをします。
#おまけ 共通のディレクトリ
上のリンクを見て環境を作った場合、ホームにWindowsが残ってしまっていると思います。
また、共通のディレクトリはマウントされておらずこのままだと使うことができません。
なので、とりあえずWindowsを消して、またWindowsディレクトリを作りマウントを取らせるようにします。

```
sudo fdisk -l 
```
これで、どのディレクトリが共有で使っていたディレクトリかを確認します。今回は/dev/sda6としておきます。

```
(使いたいディレクトリ名で、以前のものから変更もできます、/hogefugaでもなんでもいいです)
sudo mkdir /Windows
sudo mount -t /dev/sda6 /hogefuga
cd ~/
ln -s /Windows
```
これで、以前と同じように共有ディレクトリも使うことができます。