OmniAICreator/Qiita-1.07M huggingface dataset:
Google OAuth 2.0 認証を使ったGoogle Sign-Inの実装（JS編）

#概要

最近はどのサイトでもSNSからのログインだったり、登録するサイトが当たり前になっています。

<img width="255" alt="スクリーンショット 2020-02-04 19.43.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323436/b83c691f-29b3-6128-2ba5-8d22604be05c.png">

よく見かけるこんな感じのボタンですね。。


今回はjsだけを使って簡単にGoogle Sign-Inを実装してみます。

#Googleアカウントの作成

まずはじめにGoogleアカウントを作成しましょう。
可能ならそのアプリ専用に作った方がいいと思います。

#Google Cloud Platformでの設定

https://console.cloud.google.com/getting-started

まずは先ほど作ったGoogleアカウントでログインしましょう。

左上の[**Project**]からプロジェクトを作成を選択します。

<img width="589" alt="スクリーンショット 2020-02-04 19.56.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323436/8a4de75f-7139-ebb5-b40e-89d0a75ce554.png">

プロジェクト名はわかりやすい任意の名前をつけて、場所はとりあえずこのままで作成します。

先ほど作成したプロジェクトを選択して左のメニューから
[**APIとサービス**]→[**認証情報**]を選択

[**認証情報を作成**]→[**OAuth クライアント ID**]から今回使うOAuth認証情報を作成します。

<img width="645" alt="スクリーンショット 2020-02-04 20.15.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323436/007c73a0-258f-11c4-6e0d-7827ae80ade6.png">

今回は[**ウェブアプリケーション**]を選択して[**名前**]を入力します。

[**承認済みのJavaScript生成元**]には作ったアプリのDomainを入力します。(複数選択可能)
例:http://localhost:8080


[**承認済みのリダイレクトURI**]にはユーザーが認証された後にリダイレクトされるURLを設定します。
例:http://localhost:8080/login/callback


[**作成**]すると**クライアントID**が発行されるのでメモしといてください。

#実装
では実装してみましょう。

```HAML:HTML
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="google-signin-client_id"content="YOUR_CLIENT_ID.apps.googleusercontent.com">
    <script src="https://apis.google.com/js/platform.js" async defer></script>
  </head>
  <body>
    <div class="g-signin2" data-onsuccess="onSignIn" data-theme="dark"></div>
  </body>
</html>

```

正直HTMLにこの記述するだけでGoogle Sign-Inの実装はできちゃいます。
[**YOUR_CLIENT_ID**]は先ほどメモした**クライアントID**を入力しましょう。
簡単ですよね。

更にログインしたユーザーのプロフィール情報を取得するには**getBasicProfile()**メソッドを使用します。

```javascript:JavaScript

function onSignIn(googleUser) {
  var profile = googleUser.getBasicProfile();
  console.log('ID: ' + profile.getId()); // GoogleのID
  console.log('Name: ' + profile.getName()); // アカウント名
  console.log('Image URL: ' + profile.getImageUrl()); // プロフィール画像
  console.log('Email: ' + profile.getEmail()); // ユーザーのメールアドレス
}

```

ちなみにログアウトを追加したい場合は、こんな感じで書けます。

```HAML:HTML
<a href="#" onclick="signOut();">ログアウト</a>
<script>
  function signOut() {
    var auth2 = gapi.auth2.getAuthInstance();
    auth2.signOut().then(function () {
      // ログアウトした後の処理
    });
  }
</script>

```

#まとめ

今回はJSを使ってGoogle OAuth 2.0 認証を使ったGoogle Sign-Inの実装をしました。
ほんとこれだけでログイン機能の実装はできてしまうので皆さんも今時のおしゃれサイトにする際は使ってみてください。
ただ、実際の運用に使う際はこれだけだとセキュリティーガバガバなのでサーバーサイドでIDトークン検証したりなど、工夫が必要ですね。
また別でサーバーサイドでの処理などの実装もあげるのでよかったらみてください。


#参考

https://developers.google.com/identity/sign-in/web
Oracleのバージョンを調べる

# はじめに

[RDS上のOracleをメジャーアップグレードする](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.Oracle.html#USER_UpgradeDBInstance.Oracle.Major)にあたり、Oracleの正確なバージョンを把握しておく必要が出てきたため、その方法を調べてみました。

# データベースのバージョン

* `SELECT * FROM v$version`という簡単なSQLでバージョン情報を調べられました。
 * MySQLは `SELECT version();` でバージョンを調べられるので、ちょっと似ていて覚えやすいかもしれません。

```sql:SQL*Plusの実行結果
SQL> SELECT * FROM v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE    11.2.0.4.0      Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
```

* Web上でOracleのSQLを試せる「Oracle Live SQL」で実行した結果は以下の通りです。
 * `BANNER_FULL`、`BANNER_LEGACY`、`CON_ID`は割愛して、`BANNER`の部分だけを抜き出しています。

```sql:OracleLiveSQLの実行結果
BANNER
--------------------------------------------------------------------------------
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
```

# クライアントのバージョン

* Oracleクライアントのバージョン（=SQL*Plusのバージョン）は、以下のコマンドで取得できました。
 * おそらくLinux版も同じコマンドを使えると思います。

```text:コマンドプロンプト
C:\Users\NKOJIMA>sqlplus -v

SQL*Plus: Release 11.2.0.4.0 Production
```

# 参考URL

* [Oracleバージョン/エディションの確認方法](https://blogs.oracle.com/oracle4engineer/oracle-v96)
* [ORACLEクライアントのバージョンを確認する方法](https://oreno-it.info/archives/3203)
初心者によるプログラミング学習ログ 229日目

#100日チャレンジの229日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

229日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>229日目<br>・udemyで、css+javascript講座<br>・webサイト部分的模写<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1224424974271692800?ref_src=twsrc%5Etfw">February 3, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
ツイキャス配信で閲覧人数が増えた時にデスクトップ通知する 

ツイキャスの配信では右上に今いる人と累積の人数が表示されている。
配信をみているとキャス主はその数字が変化するたびに `n名様いらっしゃい` と律儀に言っている人が多かった。おそらく右上の数字が変化していくのを目視で確認していると思う。

<img width="500" alt="AxRc2VwTnHfZm0o1580815950_1580816974.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579094/b2b17a42-025c-98c5-99b5-20bf912a599b.png">

人が増えたら `n名様いらっしゃい` と毎回言うためにはこの数字をずっとみてないといけない。
なんだか大変そうだったので人数が増えた時のみデスクトップ通知を行うためのブックマークレットを書いた。

```
javascript:(()=> {
	const getFraction = () => parseInt(document.querySelector(".tw-fraction").textContent.split("/")[0]);
	let oldFraction = getFraction();
	let newFraction;
	let intervalId = setInterval(() => {
	    newFraction = getFraction();
	    if (newFraction > oldFraction) {
		new Notification(newFraction + "名様いらっしゃい");
	    }
	    oldFraction = newFraction;
	}, 2000);
	console.log("Interval ID = " + intervalId);
})();

```

このコードをブックマークレットとして登録する。

<img width="352" alt="スクリーンショット 2020-02-04 20.51.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579094/c4f01fed-399b-19a0-ac15-e515f121513f.png">

<img width="530" alt="スクリーンショット 2020-02-04 20.51.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579094/8e004ab3-b805-9f81-e371-4adc3861ca8f.png">


実行するためには配信画面で登録したブックマークをクリックすれば良い。人数が以前取得した値よりも増えた場合に以下のように通知される。

<img width="374" alt="スクリーンショット 2020-02-04 20.25.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579094/870df851-f57d-a15d-9eaa-ba6dfe117584.png">

動作環境
- Google Chome: バージョン: 79.0.3945.130（Official Build） （64 ビット）
Draft.jsで絵文字(サロゲートペア )をEntity化して削除を良い感じにできるようにするう方法

# Draft.jsで絵文字(サロゲートペア )をEntityにして良い感じに削除をできるようにする方法

Draft.jsで絵文字を扱うと削除した時にいい感じに消えてくれない問題が発生します。
その解決法にたどり着くまでに地味に時間がかかったので備忘録をかねて書きます

## 問題

例えばdraft.jsで４人家族の絵文字を消そうとすると、３人家族になったりします
`👩‍👩‍👧‍👦` => `👩‍👩‍👧‍`

この問題はdraft.jsでサロゲートペアの絵文字を扱うと発生してしまいます
これを解決する方法として、Draft.jsの [Entity](https://draftjs.org/docs/advanced-topics-entities/) というものがあります

**Entity**
> メタデータを使用してテキストの範囲に注釈を付けるために使用するエンティティシステムについて説明します。
エンティティは、スタイル付きテキストを超えるレベルの豊かさをもたらします。リンク、メンション、
および埋め込みコンテンツはすべて、エンティティを使用して実装できます。


といったもので、指定した文字の範囲に役割を与えたり、複数の文字列を一つの文字？として扱うことが可能です

## デモ ＋ コード

そしてデモとコードをCodeSandboxで用意しました

https://codesandbox.io/s/draft-js-emoji-to-entity-tdoe2

![スクリーンショット 2020-02-04 18.00.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131778/1bf2e3eb-49bf-665d-9b00-b2d8e54fc9b7.png)

## 解説

ざっくり説明すると
初期化時、文字入力時、コピペ時、IMEの入力(コンポジットモード)が終わった時に操作した文字列の絵文字を正規表現で開始と終了のindexを取得して、EntityのIMMUTABLEというものに変換しています。

こうすることで、一つの文字列として扱うことができ削除の問題を解決できます。
引数に渡している正規表現を変えることで他のEntity化の用件にも対応できると思います

もう少し詳しく書くと、最終的に変更されたContentBlockから絵文字を見つけてEntity化し、操作履歴を誤魔化すために、一度UndoしてからPushだとかいろいろしてたりします。細かく話すとDraft.jsの構造の話になって面倒なので割愛

## 最後に

ググってもいい感じの記事にたどりつけなかったので、誰かの役に立てるとありがたい

最後にDraft.jsを触った感想ですが、これよりいい感じのライブラリはないものか:weary:
メンテが殆どされていないのと、不具合があったり、IMEのイベントまわりがうまく制御されていないのか、ちょっと変化ことをしようとすると日本語とかでバグったりする
ActiveRecord::PendingMigrationErrorと表示された時の解決法！


##記事の目的
rails db:migrateでマイグレーションできない問題に対しての対処法を共有すること。

## 状況
モデル作成時に
```rails g model posts```のように```post```としなければならないところを複数形で書いてしまったため、一度削除した。その後、```rails g model post```でモデルを作り```rails db:migrate```をしたところ、
```ActiveRecord::PendingMigrationError```
というエラーが発生。

（もしかしたら削除後に```bundle exec rails db:migrate```を行なっていなかったことが原因の可能性あり。）


## 対処法
###ActiveRecord::PendingMigrationErrorって何？
簡単にいうと、未実行のmigrationがある場合に出てくるエラー。
自分の場合は```rails db:migrate```をしても解決しなかったのでデータベースをいじってみることにした。

###最初に試したこと
マイグレーションがcreatできてないと考え、まずはデータベースの中を```$ rails dbconsole```のあと確認。

```
MySQL [app_development]> SHOW TABLES;
+---------------------------+
| Tables_in_app_development |
+---------------------------+
| ar_internal_metadata      |
| schema_migrations         |
+---------------------------+
2 rows in set (0.00 sec)

```
```
MySQL [app_development]> SHOW DATABASES; 
+--------------------+
| Database           |
+--------------------+
| information_schema |
| app_development    |
| app_test           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
6 rows in set (0.01 sec)
```
postテーブルはない...。
でもrails db:createは実行されている。

###対処できた処理
ここで、schema_migrationsをみてみる。

```
MySQL [app_development]> SELECT * FROM schema_migrations;
+----------------+
| version        |
+----------------+
| 20200202112028 |
+----------------+
1 row in set (0.00 sec)
```

####schema_migrationsとは！？
Railsの```schema_migrations```はどのマイグレーションスクリプトまで実行済みなのかを記録するためのテーブル。

つまり、今回は実際にテーブルには反映されていないけどRailsは作ったよと言い張っている感じ。

このファイルがあると新しくモデルを作るときに邪魔なので削除する。

```
MySQL [app_development]> DELETE FROM schema_migrations WHERE VERSION=20200202112028 ;
Query OK, 1 row affected (0.06 sec)
```
確認すると、

```
MySQL [app_development]> SELECT * FROM schema_migrations;
Empty set (0.00 sec)
```
空になっている！！！！
```exit```で抜けて```rails db:migrate```すると、

```
== 20200202112028 CreatePosts: migrating ======================================
-- create_table(:posts)
   -> 0.2196s
== 20200202112028 CreatePosts: migrated (0.2264s) =============================
```
となり無事作成することができた！
## 終わりに
データベースでおかしいことがあれば```SHOW```などで中身を見る癖をつければトラブルシューティングになりそう！

おかしなところがあればフィードバックをください！
Zephyr > math > pow()の使用 > CONFIG_NEWLIB_LIBC=y | pow()が0.0になる条件

```txt:動作環境　
Ubuntu 18.04 LTS
ボード: STM32L476 Nucleo_64 (以下、STM32L476)
Zephyr 2.1.0-rc1
放射温度計センサー: MLX90632 (CLICK-IRThermo)
ロジック確認: Analog Discovery 2 (AD2)
```

pow()を使おうとして調査したことの整理をしておく。

### pow()の使用 > CONFIG_NEWLIB_LIBC

prj.confにCONFIG_NEWLIB_LIBC=yをつかする。

```prj.conf
CONFIG_PRINTK=y
CONFIG_I2C=y
CONFIG_SERIAL=y
CONFIG_NEWLIB_LIBC=y  # for math.h (2020-02-03)
CONFIG_DEBUG=y
```

### pow()が0.0を返す > math.hのインクルード忘れ

```
#include <math.h>
```

上記がない場合、west buildは通ってしまうが、pow()の値が0.0になる。
ない場合はRTOSが用意するダミー関数が使われるのかもしれない（推測）。

### 関連

- [v1.13.0 Standard C Library](https://docs.zephyrproject.org/1.13.0/subsystems/c_library.html)
    - バージョンが古いが参考にした
    - latestのドキュメントでは場所が変わっている？
- [Compiling for native_posix with newlib is missing various math symbols](https://github.com/zephyrproject-rtos/zephyr/issues/8502)
- [ビルトインのmath.h?](https://github.com/zephyrproject-rtos/zephyr/blob/master/lib/libc/minimal/include/math.h)
2/4 授業ノート

#昨日の復習
・Outline上、見出しとコンテンツは基本的にセットで扱われる
・ナビゲーションは文法上見出しとして扱われるが名前は付けないためoutline上では「Untitled Section」と表示され、中身もない
・記号は基本的に文字参照しておくと無難
・リンク先が**別サイト**の場合は```<a href="#"```**```target="_brank"```**```>aaa</a>```と記述

#今日習ったこと
**header要素について(教科書P27～30)**
・header要素は基本的にh1要素とp要素を包括していると考える
　ex:)```<header><h1>Title</h1><p>Description</p></header>```←ここまでがheader要素の中身

**インライン/ブロック要素について(教科書P40～)**
・インライン要素
　→テキストデータや画像、a要素(```<a></a>```)など横並びでマークアップするテキストレベルの要素(＝テキストデータとして扱われる)
・ブロック要素
　→見出し、段落、箇条書き、表組みなど文書構造の骨組みを構成する要素
　※ブロックレベルの要素はマークアップすると自動改行される
→概念的にはブロック要素は入れ物、インライン要素は中身
　**つまり…ブロック要素の中にインライン要素/ブロック要素(入れ物に中身)は入るが、
　インライン要素の中にブロック要素(中身に入れ物)は入れられない！**
　☆もっとも手軽な見分け方→要素を記述した時に自動改行するかどうかで判断

・セクション要素(教科書P208～)
　→見出しとそれに伴うコンテンツのひとかたまりのこと。
　　文書の「アウトライン」を生成し、情報の階層構造尾を明示する役割を持っている。4種類存在
　4種類のセクション要素
　・section要素→章、節のような見出しと概要を伴う一般的なセクションを表す要素
　・nav要素→主要なナビゲーションを表す要素
　※以降2つは未履修
　・article要素→自己完結した独立したセクションを表す要素
　・aside要素→メインコンテンツと関係が薄く、取り外しても問題がないセクションを表す要素

**section要素について**
　→開始タグと終了タグで囲まれた範囲を一つのまとまりと指定する要素
　ex:)
```<section> <h1></h1><p></p> </section>```
→section要素の中に「h1要素とp要素」がまとまっている
```<section> <h2></h2><section>  <h3></h3><p></p> <section> </section>```
→section要素の中に「h2要素」、さらにその中に「h3要素とp要素」がまとまっている(入れ子構造)

#感想
section要素の概念について理解は出来たものの言語化するのがとても大変だった。
まだ詰め切れてないので、この部分は要復習。
セクション要素を全て理解したらきれいに言語化できるかな？
if current_user.admin? && !current_user?(user)で「!」が必要な理由

##事象
railsチュートリアル「10.4.2 destroyアクション」において、
「現在のユーザーが管理者のときに限り」という条件を作るためにチュートリアルでは、下記のように記載されていました。

```app/views/users/_user.html.erb
 <% if current_user.admin? && !current_user?(user) %>
```

２つの条件が成り立つ場合のif文になります。
右の条件において先頭に「！」が必要になる理由がわからなかったので記事にしました。
具体的には、現在のユーザーを「!」で否定すると条件が成り立たないのではと疑問に思っていました。

※左の条件は現在ブラウザを操作している自分が管理者権限を持つか判定しています。
※右の条件は後述していますが、現在ブラウザを操作している自分と同じユーザーかを判定しています。

##!の意味
!はnot演算子です。
式の値が真である時偽を、偽である時真を返します。

`!true=>false
!false=>true
`

##!current_user?(user)が何を表すか
current_user?の判定を「!」で逆転しています。
ここでは、
current_user?がtrueならfalseで返し、
current_user?がfalseならtrueで返します。

##忘れがちなeach文の存在
チュートリアルでややこしいことをやっているといま自分が何をやっているかわからなくなってしまうことが１周目だとちょくちょくありました。それゆえの失念だと思いますが、

そもそも、表題の条件文はeach文の中にあります。
下記がrender元のeach文です

```app/views/users/index.html.erb
  <ul class="users">
     #省略型のeach文を表しています
　　　<%= render @users %>
  </ul>
```
下記がrender先になります。

```app/views/users/_user.html.erb
<li>
  <%= gravatar_for user, size: 50 %>
  <%= link_to user.name, user %>
  <% if current_user.admin? && !current_user?(user) %>
    | <%= link_to "delete", user, method: :delete,
                                  data: { confirm: "You sure?" } %>
  <% end %>
</li>
```

このためuserの部分にユーザーの全レコードがそれぞれ入れられていく処理になります。
するとif分の結果として下記の４通りあるはずです。

①真＆＆真（＝管理者 かつ userがcurrent_user）
②真＆＆偽（＝管理者 かつ userがcurrent_userではない）
③偽＆＆真（＝非管理者 かつ userがcurrent_user）
④偽＆＆偽（＝非管理者 かつ userがcurrent_userではない）

そして``!current_user?(user)``
この条件はeach分によって割り当てられたuserがcurrent_user(=ここでは現在ブラウザを見ている自分)と同じかを判定しています。
current_userで無い限り``!false``となり、結果``true``になります。

初見ではちょっとわかりづらい部分かと思います。
成り立つのは②の「管理者 かつ userがcurrent_userではない」時のみになります。

※補足（20201106）
結果として以下の文によって、
ブラウザ上では、ユーザー一覧の内管理者である自分以外のユーザーの情報をdeleteするリンクを表示することになります。

```
<%= link_to "delete", user, method: :delete,data: { confirm: "You sure?" } %>
```



##まとめ
if current_user.admin? && !current_user?(user)
上記の文は管理者かつeach文によって割り当てられたuserが管理者（current_user）で無い限り成り立つことになります。

よって、管理者がユーザー一覧ページを開くと管理者以外のユーザーに対して削除ボタンを追加できるようになっています。
つまり管理者が自分自身を消せないようにもなっています。

##参考
・https://docs.ruby-lang.org/ja/latest/doc/symref.html
・https://teratail.com/questions/198416
TypeScript で型エラーにならないバグのうちよくハマるものの個人用メモ

# 概要

* 自分用メモの側面が強いのでご了承ください。
* JavaScriptの仕様のハマりやすいポイントのメモ
* TSの型チェックやESLintなどの一般的なチェックツールで弾けるものは対象外
* TypeScriptで普通に型付けしてても型エラーにならず実行時エラーになるケースなど

## 配列添字アクセス

* `map`, `filter`, `forEach` メソッドあたりを使っていれば配列添え字アクセスはめったに必要にならないが、ユーティリティ関数などの実装でたまに必要になることがある。
* 配列 `xs: T[]` の要素へ添字アクセス `xs[i]` すると値が `undefined` になりうるが、 `xs[i]` の型は `T | undefined` ではなく `T` に評価されているので型チェックで発見できず実行時エラーとなりうる。
* `at: (array: T[], index: number) => T | undefined` のようなより安全な添え字アクセスをするための関数を自作するのもあり。
* `Immutable.js` の `List` であれば、 `List<T>` 型のリストの要素アクセスメソッド `get` の返り値は `T | undefined` となるので安全だが、ビルトイン配列オブジェクトより遅く、手軽さも損なわれる。

## Array.sort

* 文字列でソートされるので注意
* 数値でソートしたい場合 `array.sort((a, b) => a - b)` と書く必要があるが、やや面倒。`sortNumeric: (array)` のような関数呼び出しにしてもよいが、メソッドチェーンでそのあとに処理をつなげたいときなどに見づらくなりこれはこれで不便。
* （2020/03/06追記） 比較関数の指定を強制するeslintルールがあった → https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/require-array-sort-compare.md

pipeline operatorが実装されれば `at` や `sortNumeric` 関数が使いやすくなるはずだが、現状関数呼び出しするしか無い印象。

---

（今後追記予定）
Zephyr > Debug > printk("%f"); > %fが表示される（デバッグには使えない) + 代替案

```txt:動作環境
Ubuntu 18.04 LTS
ボード: STM32L476 Nucleo_64 (以下、STM32L476)
Zephyr 2.1.0-rc1
放射温度計センサー: MLX90632 (CLICK-IRThermo)
ロジック確認: Analog Discovery 2 (AD2)
```

### printkデバッグ > %fが表示される

Zephyrにはprintk()が用意されている。

- [Zephyr Project: printk()](https://docs.zephyrproject.org/apidoc/latest/printk_8h_a768a7dff8592b69f327a08f96b00fa54.html)

```
float res = 3.141592;
printk("%f\n", res);
```

この実装は下記となる。

```
%f
```


## float, double変数の値確認

%fがないため、float, doubleの値確認は別の方法を取ることになる。

### 案1. printk("%d", res*1000)

有効桁がわかっている場合、小数部分が整数になるように桁調整をして%dで表示する。

### 案2. west debugでブレークする

west debugで実行してbreak main.c:79のようにしてからcで実行。
停止したところで、p resのようにして変数値を読む。


### 案3. sprintf()を使う

- [Zephyr > debug > double型をprintk()で出力する: sprintf("%f")を使う [CONFIG_NEWLIB_LIBC_FLOAT_PRINTF] | double型使用時の注意点 > loggingサブシステムはdouble型変数をサポートしない](https://qiita.com/7of9/items/f0a4d64743f938992185)
PWA night conference  2020 行ってきた

## 行ってきたので書いた
カンファレンス行ってきたので自分で調べたこととかも交えてこんな感じかなというサマリを記載
※発表内容そのままという訳ではないのであしからず、間違っているところもあるかも
所感としては内容が普通に面白かったので行ってよかったなーというのと
PWAでできることってWebでできる事の依存が大きいので、Webでできる事が増えたぞ→PWA的にはどうだろうという事が考えられる良いカンファレンスでした

## Project Fugu
Project fuguでChromiumの開発中の機能とかの一覧とインターフェースが見られるよ！
（fuguはあのフグだよ！）
https://docs.google.com/spreadsheets/d/1de0ZYDOcafNXXwMcg4EZhT0346QM-QFvZfoD8ZffHeA/edit#gid=557099940

chromeは
chrome://flags/
で試験中の機能をONにできるよ！

##ScrapboxでのService WorkerとCacheの活用

###キャッシュについて
####既存のアプリに入れるとcorsエラーが起きる場合があるよ
特定のタグ`<img>`や`<script>`などからはcorsのリクエストが許可されているが、JavaScriptからは許可されておらずその辺の実装をService Workerでキャッシュしようとするとcorsのエラーが起きるよ！
CDNのレスポンスヘッダにAccess-Control-Allow-Originを追加しようね！

#### エラーのキャッシュはすると場合によっては詰むよ
エラーをキャッシュするとエラー画面がキャッシュされてしまうのでresponse.okだけキャッシュしようね！キャッシュファーストだとユーザーが詰むよ！

#### キャッシュは色んな方法で探せるよ
サーチパラメータを考慮したり、methodをまとめて探すことができるよ！
https://developers.google.com/web/ilt/pwa/caching-files-with-service-worker
（match dataのとこに書いてあるよ！）

#### 見せ方
環境ごとに必要な見せ方を考えるのが大事だよ！
モバイルは全画面表示できるけどリロードボタンとかなくなるのでそれを用意してあげるとか
デスクトップ版もURLなくなるのでコピーどうするかとか
どっちかというとネイティブっぽい考え方が必要になるよ！

##進化するHTTP


####HTTP３
詳しく書くとこれだけで1〜2記事書けそうなので割愛するけど
すでにcanary落とせばHTTP3自体はブラウザから試すことができるよ！
アプリ開発者はHTTP3のためにコードを変更する必要はないよ！（HTTPを流す接続を自分で選択するような低水準なライブラリは除く）
alt-svc:h3=“:443”で試せるよ！
https://japan.cnet.com/article/35143184/

##まもなくやってくるVue.js3

めちゃくちゃ変更点あるっぽいよ！
所感としては割とReactっぽくなるような気がするよ、特にrender関数でJSX使えるようになるとことか！
ライフサイクルフックの名前が大体全部変わるよ！
CSSのscopedの書き方も変わるよ！
パイプ演算子で使えたフィルタが削除されるよ！
refでラップしたオブジェクトを渡してリアクティブな状態を共有することになりそうだよ！
プラグインはDIで実装を推奨するよ！
下手したら割と書き直しになるプロダクトとかあるかもなって思ったよ！

##PWA on Windows
毎回物江さんの話はおもしろいよ！
MicrosoftはPWAに前向きだよ！
ただPCの電源途中で切れたからメモが残ってなくて記憶があやふやだよ！
Edgeは＋ボタンでPWA追加できるとか
今はchromium版のEdgeから落としてもchromium版じゃない方準拠でPWA立ち上がるとか
アプリケーションの追加と削除から消すとうまく消えないからじゃなくて直接消してくれとか
みんな大好きvscodeにPWA拡張があるけどなんたらかんたら
みたいな事を話してた気がするよ！
あとみんなこの神の発明品を使おうね！
https://www.pwabuilder.com/

##LT大会
全員発表のエッジが効いてて聞いてる方も楽しかったよ！
PWA RTA in Japanでpreactの30秒がWRというのがネタとしては好きだったよ！

おわり
React+material-uiでコピーボタン付きのテキストボックスを作る

こういうの

![textbox.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349145/a40ed27c-86e0-5eda-7264-1245a361ed75.gif)

# 準備

必要なモジュールをインストールします。

- `@material-ui`: いい感じのコンポーネントを提供してくれるやつ
- `react-copy-to-clipboard`: クリップボードにコピーとかしてくれるやつ

今回は`yarn`を使用します。
`npm`を使用している場合は適宜読み替えてください。

```bash
$ yarn add @material-ui/core @material-ui/icons react-copy-to-clipboard
```

今回はTypeScriptを使用するため、`react-copy-to-clipboard`の型定義ファイルもインストールします。

```bash
$ yarn add --dev @types/react-copy-to-clipboard
```

# サンプルコード

```tsx
import React, { useState } from 'react';
import FormControl     from '@material-ui/core/FormControl';
import OutlinedInput   from '@material-ui/core/OutlinedInput';
import IconButton      from '@material-ui/core/IconButton';
import InputAdornment  from '@material-ui/core/InputAdornment';
import AssignmentIcon  from '@material-ui/icons/Assignment';
import Tooltip         from '@material-ui/core/Tooltip';
import CopyToClipBoard from 'react-copy-to-clipboard';

const TextBoxWithCopyButton: React.FC = () => {
  const [input,   setInput]   = useState<string>('');
  const [openTip, setOpenTip] = useState<boolean>(false);

  const handleChangeText = (e: React.ChangeEvent<HTMLInputElement>): void => {
    setInput(e.target.value);
  };

  const handleCloseTip = (): void => {
    setOpenTip(false);
  };

  const handleClickButton = (): void => {
    setOpenTip(true);
  };

  return (
    <FormControl
      variant='outlined'
    >
      <OutlinedInput
        type='text'
        value={input}
        onChange={handleChangeText}
        endAdornment={
          <InputAdornment position="end">
            <Tooltip
              arrow
              open={openTip}
              onClose={handleCloseTip}
              disableHoverListener
              placement='top'
              title='Copied!'
            >
              <CopyToClipBoard text={input}>
                <IconButton
                  disabled={input === ''}
                  onClick={handleClickButton}
                >
                  <AssignmentIcon />
                </IconButton>
              </CopyToClipBoard>
            </Tooltip>
          </InputAdornment>
        }
      />
    </FormControl>
  );
};

export default TextBoxWithCopyButton;
```

# まとめ

細かい解説は省きます。
Material UI、それなりに綺麗なUIを簡単に作れるので本当に便利ですね。

# 参考

- [Text Field React component \- Material\-UI](https://material-ui.com/components/text-fields/)
- [react\-copy\-to\-clipboard \- npm](https://www.npmjs.com/package/react-copy-to-clipboard)
vueでscopedした親コンポーネント以下の子にstyleの影響を与えたい

## 結論 ::v-deep

```vuejs
<style scoped>
::v-deep .redText {
  color: red;
}
</style>
```

### 参考

[Qitta - スコープ付きCSSで別のコンポーネントにスタイルを当てる](https://qiita.com/totto357/items/f42caf4c3935cc52b4c4)
[Vue LoaderのDeep Selectorの::v-deep](https://blog.mahoroi.com/posts/2019/03/scoped-css-v-deep/)

`>>>`や`/deep/`をするのは知っていたんですが今では非推奨らしいですね！
プログラミング歴１ヶ月　PythonでNYダウの株価を抽出！

初めまして、Kayです。

投資をやっていまして、今年の１月からPythonにフロンティアを感じ、投資に応用出来ないかということで、ようやくYahooファイナンスの株価の抽出くらいまでたどり着きました。
というわけで、プログラミング歴は１ヶ月です（笑）
github↓
https://github.com/Kay-Hatsune/NY-Dow/blob/master/dow.py

#使用したもの

言語：Python3

ライブラリ：urllib、BeautifulSoup

MacBook Pro

#BeautifulSoupをインストールする

```shell.sh
$ pip3 install beautifulsoup
```
自分の場合、MacOSだったので、pip3インストールとなりました。windowsの人は違うと思うので注意してください。

#Pythonのコード
```Python:dow.py
import urllib.request
import ssl
from bs4 import BeautifulSoup

url = "https://finance.yahoo.co.jp/quote/%5EDJI"

ssl._create_default_https_context = ssl._create_unverified_context

html = urllib.request.urlopen(url)

soup = BeautifulSoup(html, "html.parser")

p = soup.find_all("p")

dow = ""
for tag in p:
    try:
        string_ = tag.get("class").pop(0)

        if string_ in "wlbmIy9W":
            dow = tag.string
            break
    except:
        pass

print(dow)
```
BeautifulSoupでYahooファイナンスからurlを引っ張ってきます。
↓
株価がpというところに入っているのでhtmlデータの中のpを検索します。
↓
pの中のclass="wlbmIy9W"の場所を特定するようにfor文とtry except文で構築する。

ちなみに、サイトを右クリックで検証を押すと、簡単に抽出箇所を特定できます。
<img width="1191" alt="スクリーンショット 2020-02-04 18.51.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575377/8d189008-2b0f-2d99-73ee-e0176b12067f.png">


#Python3ではSSL証明書が必要になるのが注意点

```
import ssl

ssl._create_default_https_context = ssl._create_unverified_context
```
Python3ではこのコードを書き込む必要があります。
書かないと必ずエラーになります。
もしかしたらPython2では必要ないかもしれません。

#抽出完了
```shell.sh
$ python dow.py

>>>28,399.81
```
ようやく抽出完了です。５時間もかかりました（笑）
今後はもっと発展させていきたいですね。:stuck_out_tongue_winking_eye:

#参考にさせていただいた記事

こちらの方がもっと発展したコードを書いているので必読です！

[Python Webスクレイピング 実践入門](https://qiita.com/Azunyan1111/items/9b3d16428d2bcc7c9406)
オブジェクト指向

```py:
class Person(object):
    def __init__(self, age=1):
        self.age = age
    def drive(self):
        if self.age >= 18:
            print('OK')
        else:
            raise Exception('No drive')

class Baby(Person):
    def __init__(self, age=1):
        if age < 18:
            super().__init__(age)
        else:
            raise ValueError

class Adult(Person):
    def __init__(self, age=18):
        if age >= 18:
            super().__init__(age)
        else:
            raise ValueError

class Car(object):
    def __init__(self, model=None):
        self.model = model
    def run(self):
        print('run')
    def ride(self, person):
        person.drive()

baby = Baby()
adult = Adult()
car = Car()

car.ride(adult)
```

```:実行結果
OK
```

最後の行を

```py:
car.ride(baby)
```
にかえると

```:実行結果
Exception: No drive
```
Jenkins ジョブでSVNコミットする方法


## はじめに

Jenkinsでいろいろやっていると、Jenkinsで作成した成果物をSVNまたはGITにコミットしたい時が時々ある。
チェックアウトはJenkinsの標準機能で利用すればよいが、ファイルをコミットするときはシェルで個別に実装する必要がある。

毎回考えるのも面倒なので、忘備用に残しておく。
最近は、pipeline を利用することが多いため、両方のパターンを用意した。


## Jenkins GUIを利用する場合

GUI上のビルドの「シェルの実行」を選択することで、シェルの実装ができる。
ここで記載するシェルの内容は、Jenkinsが立っているOS環境で動くため、
Linux環境なら、普通にshell を利用することが可能。

```shell

# svn info
SVN_OPTION="--no-auth-cache --username ${build_user_account} --password ${build_user_password}" 

# commit message
# ※ コミット用のチケットを別途作成してもよい
SVN_COMMIT_MSG="変更コミット" 

# target
TARGET="${WORKSPACE}/svn" 


# add
svn status ${TARGET} ${SVN_OPTION} | grep ^? | awk '{print $2}' | xargs svn add ${SVN_OPTION}

# commit
svn status ${TARGET} ${SVN_OPTION} | awk '{print $2}' | xargs svn commit -m "${SVN_COMMIT_MSG}" ${SVN_OPTION}

```

＜補足＞
* 更新、削除などの場合は、コミット処理のみでよいが、新規ファイルの場合は追加の処理が必要
* svn status で更新情報の一覧を取得し、各ファイルに対して、Add、Commit 処理を行う。
* 追加対象の場合、svn status の第一引数が [?:バージョン管理外]になるため、これをキーでgrepし、2個目の項目にパスがあるため、awk コマンドでファイルパスを取得した後、xargs でファイルパスを引数に渡してコミットを行っている。



## Jenkins のPipeline を利用する場合

Jenkinsのpipeline で記載する場合、groovy 言語の中に、シェルを記載する。
微妙な変更箇所にはまったため、記載する。


```groovy

sh"""#!/bin/bash
# svn info
SVN_OPTION="--no-auth-cache --username ${build_user_account} --password ${build_user_password}" 

# commit message
# ※ コミット用のチケットを別途作成してもよい
SVN_COMMIT_MSG="変更コミット" 

# target
TARGET="${WORKSPACE}/svn" 

# add
svn status ${TARGET} ${SVN_OPTION} | grep ^? | awk '{print \$2}' | xargs svn add ${SVN_OPTION}

# commit
svn status ${TARGET} ${SVN_OPTION} | awk '{print \$2}' | xargs svn commit -m "${SVN_COMMIT_MSG}" ${SVN_OPTION}
 """

```
＜補足＞
* Jenkinsのpipleline で、シェルを書く場合、[#!/bin/bash]を明示的に指定する必要はないが、awk コマンドを利用しているため、エスケープ対応のために明示的に指定。
* \$2について、$はShell外のパラメータを渡すことができるため、シェル内のみしか利用しない場合は、特別にエスケープが必要。


### おわりに

今後は、バージョンが変わらない限りコピーするだけ。
Jenkinsの標準で関数を用意してくれるとコード量が減って助かるのだが。。
A-Frame: aframe-star-system-componentの調査

[前回のA-Frameで利用できるパーティクルコンポーネント調査](https://qiita.com/matsukatsu/items/adec590eddad5510c196)から、[aframe-star-system-component
](https://www.npmjs.com/package/aframe-star-system-component)の使い勝手が良さそうだとわかりました。
パーティクルを使いこなせるようになる為、コンポーネントの各プロパティがどのような意味を持つのか、詳しく見ていこうと思います。

### color
![スクリーンショット 2020-02-01 23.43.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/0faebb9d-1743-3b63-557d-7fbba13c88bf.png)
スター粒子の色
type: String
default: #FFF'
min: -
[demo - color: red](https://k38.github.io/aframe/star-system/color.html)

*色名、HEX、RGB、HSLが使えるようです。*

### radius
![スクリーンショット 2020-02-01 23.45.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/2451e20e-6d1a-038c-5ab1-5ab735405b2b.png)
内側の星球に球の中心からの距離
type: Number
default: 300
min: 0
[demo - radius: 10](https://k38.github.io/aframe/star-system/radius.html)

*デフォルト値が300で結構遠くにあるので、10ぐらいまで近づけてみると、星に見えていたものがただの四角形でした。*

### depth
![スクリーンショット 2020-02-01 23.46.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/268a6df5-dfb1-14f8-e8ed-d18bf27acfc5.png)
内側の球と外球の間の距離
type: Number
default: 300
min: 0
[demo - depth: 0, radius: 50](https://k38.github.io/aframe/star-system/depth.html)

### starSize
![スクリーンショット 2020-02-01 23.48.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/6c037f80-992d-644c-8efa-278e3a6ff599.png)
個々の星の大きさ
type: Number
default: 1
min: 0
[demo - starSize: 1, radius: 10](https://k38.github.io/aframe/star-system/size.html)
[demo - starSize: 2, radius: 10](https://k38.github.io/aframe/star-system/size2.html)

*モジュールの説明ではプロパティ名はsizeと書かれていましたが、コードを見てみるとstarSizeでした。*

### count
![スクリーンショット 2020-02-01 23.50.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/ea0ee3e4-235a-431d-272b-653ce0cdbd1e.png)
作成された総星の数
type: Number
default: 10000
min: 0
[demo - count: 100;](https://k38.github.io/aframe/star-system/count.html)

*100個程度だと、あるかないかわからないです。*

### texture
![スクリーンショット 2020-02-01 23.51.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/78191afb-6f5f-273a-30c4-845b54a162f9.png)
スプライトは、個々の星に使用する（例：PNGイメージ）
type: Asset
default: -
min: -
[demo - texture: image/compass.png; radius: 20; depth: 0;](https://k38.github.io/aframe/star-system/texture.html)

*jpn, png, svg, gifが使えました。
アルファチャンネルは有効ですが、画像同士が重なるとうまく抜けてないようです。*
*アニメーションgifを使ってみましたが、静止画になっていました*
【開催レポート】OutSystems愛知ユーザー会#3


![IMG_0146.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537509/a05a26eb-9a8a-7463-247d-50260c1e006e.jpeg)

OutSystems愛知ユーザー会運営の土橋です！

2020年1月29日(水)にOutSystems愛知ユーザー会#3を開催しました。

#今回の内容
1回目と2回目のイベントではLTなど、登壇形式でユーザー会を行いましたが、
アンケートでの要望もあり、ユーザー同士の交流を行いやすくするため今回はワークショップ形式で開催しました。

第2回レポート
https://note.com/osp_users_chubu/n/n0bf111da5d71

今回はグループに分かれてリファクタリングを行いました。

###リファクタリングとは？

> 既存のアーキテクチャを変更して再利用性と柔軟性を向上させるアプローチです。

(オンライントレーニング)アプリケーションの検証とリファクタリング
https://www.outsystems.com/ja-jp/learn/lesson/1229/refactoring-an-application/

##当日の流れ

1. ベストプラクティスおさらい
<br>↓
2. グループワーク
<br>↓<br>
3. 発表

※リファクタリング元は運営が準備したアプリを利用

###ベストプラクティスおさらい
まずリファクタリングの前提知識として、OutSystemsのトレーニング講師も務めている松井さんより
ベストプラクティス(OutSystemsが推奨するアプリの作り方)をおさらいしました。

当日の資料
https://speakerdeck.com/outdevelopers/outsystemsbesutopurakuteisushao-jie

###グループワーク
グループ(1グループ5人ほど)に分かれ1人5分づつ作業し、
最後はグループ代表者が全体に向けて成果発表をしました。

OutSystems経験は参加された皆さんそれぞれでしたが、各自5分程度
実際にOutSystemsを操作して頂きチーム全員で協力して実施しました。


リファクタリング開始
![IMG_0141.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537509/8a9af0d4-003e-8921-12c6-d1e1359a1b15.jpeg)


当日の用意していた回答例(リファクタリング内容)はこちら
https://speakerdeck.com/outdevelopers/outsystemsai-zhi-yuzahui-number-3shi-yong-hui-da-li

#結果
どのチームも頑張って頂き、成果発表は非常に接戦となりました。
最終的には用意した回答例に対してどれだけ実施できたかをチェックし
優勝チームを決めました。
※優勝チームには景品としてOutSystemsタオルを贈呈しました！

イベント後には懇親会も行いました。

#所感
今回初めてのグループワーク形式でしたが、活気があり非常に盛況でした。
イベント中に交流があったため、その後の懇親会でも情報交換がしやすかったみたいです。

ユーザー会を情報交換の場として考えると、
事前にグループワークなどでアイスブレイクできたのは良かったと思います。

また、他人が作ったアプリを触れたのはいい機会だったという意見も聞きました。

#終わりに
次回イベントは3月～4月を企画中です。
計画でき次第コンパスにて告知しますので、グループへの参加をお願いします！

OutSystems愛知ユーザー会
https://outsystems-chubu.connpass.com/

今回参加できなかった方のご参加もお待ちしております!

土橋
FFmpegで手軽にサクッとmacの画面録画をいい感じのgifにする

TwitterやSlack、メールなどで情報を共有する時ってやっぱり動画だと楽じゃないですか。

ビジュアルや動作の部分を伝える時は、結構シビアに言葉選ばなきゃいけないし、伝えられる側もUIの部分とか文章で説明されても困るわ！って思いますよね。

動画があればお互いに簡単に情報共有できるし、認識のズレも少なくなって時短にもなる。

いいことづくめなんだけど、mac買ったばっかりの素人が動画送ろうとするとちょっとハードル高いんですよね…

そもそも、画面のキャプチャー動画を作るツールもよくわからないし設定も必要だし、そもそもデータ容量重すぎ…どうしよ…

みたいな方結構いると思うんですよね！
僕がそうでした！！

この記事ではmacの標準機能で画面録画を行う方法と、FFmpegでサクッと画面録画をgifにする方法を紹介します！

# 画面録画

macは標準機能として`commando + shift + 5`で画面録画が出来ます！

同時に押すと以下のような画面が出ます

画面端に破線が表示されているのがわかるでしょうか？

この破線の範囲内が画面録画を行う範囲になります。
（画面全範囲などを指定することが出来たり、その他オプションもあるので試してみてください）

範囲は自由にいじれます。任意の箇所を囲った後に右端の「収録」ボタンを押しましょう！

<img width="1440" alt="スクリーンショット 2020-02-04 18.47.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/1dfb8f7e-5d3b-20e1-174b-6e08379aa05a.png">

するとすぐに録画スタートです！

終わりたい時は再度`commando + shift + 5`を押すとメニューバーが出てきますので、停止ボタンを押してください。

<img width="1440" alt="スクリーンショット 2020-02-04 18.53.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/19347874-53a5-355f-d2cb-dd4081d10c83.png">

こんな感じで超簡単に画面録画が出来ます！

# gifに変換

このままだと短い動画でも容量が大きく、投稿することは出来ません。

なのでFFmpegでgifに変換していきましょう。

## FFmpegインストール

```
$brew install ffmpeg
```

## gifに変換

今回はサクッと手軽にいい感じのgifを作成したいだけなので細かいオプションについては説明しません！！！！（わかりません）

とりあえず以下のコマンドで絶妙にいい感じの容量と画質のgifになります！！！！！

詳しいことは以下の記事なんかがとても参考になると思います!
[それFFmpegで出来るよ！](https://qiita.com/cha84rakanal/items/e84fe4eb6fbe2ae13fd8)

```
ffmpeg -i sample/sample.mov -vf scale=960:-1 -r 10 sample/sample.gif
```

`sample/sample.mov`は撮影した動画のパス
`sample/sample.gif`は吐き出し先のパス

※※※※※ちなみに、撮影した動画の名称はデフォルトだと「日本語+スペースあり+拡張子なし」のようなアホみたいな名称になっているので、`sample.mov`のようにリネームすることをお勧めします！※※※※※

そして出来上がったgifがこちら！

![maptiler 21.46.10.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203944/102394c2-0e8c-3892-ea95-610344d7d028.gif)

[MapTilerの地図をReact/Mapbox GL JSを使って最短でブラウザ上に表示させる](https://qiita.com/nokonoko_1203/items/16b1e9f70bdfafc9728d)で作った動画になります（宣伝）

こんな感じで簡単にgifを作成して情報共有できるのでぜひ利用してみてくださいね！!!
混乱しがちなIDEのショートカットまとめ（Visual StudioとEclipse編）

## はじめに
 業務でよく複数言語を扱うことがあり、その言語ごとにIDE（統合開発環境）が異なり、ショートカットキーも微妙に違っていて、個人的に混乱しがちでした。

 せっかくQiitaのアカウントもあることなので、まとめて整理してみようと思います。

## 対象範囲と前提条件
* 言語
  * Java8(Java+JSP(html+JavaScript+jQuery))
  * Visual Basic 2013
* IDE
  * Eclipse Java EE IDE for Web Developer(Photon Release (4.8.0))（※以降Eclipseと呼びます。） 
  * Microsoft Visual Studio Professional 2013(12.0.21005.1 REL)（※以降Visual Stdioと呼びます。）
* 前提条件
  * ショートカットキーの設定は初期値のままとします（たぶん変えていないはず、初期値と変わっていたらスミマセン）。逆に言うと、変更していたらこの限りではありません。

## ショートカットキーの調べ方
* Eclipseの場合
  * ［ウィンドウ］メニューから［一般］の［キー］の一覧
* Visual Studioの場合
  * ［ツール］メニューから［オブション］の［環境］の［キーボード］の一覧

## デバッグ系
一番最初に混乱した分野。特に“ステップ・イン”と“ステップ・アウト”はお互いの別のコマンドのバインディングと被っていて、本人としては予期せぬ動きをして「なんで？」とはてなマークを浮かべたことも。

|コマンド名|Eclipse|Visual Studio|
|:--|:--|:--|
|デバッグ開始|Alt+Shift+D,J[^1]|F5|
|再開|F8|F5|
|実行|Ctrl+U|F5|
|中止|Ctrl+F2|Shift+5|
|ステップ・イン|F5|F11|
|ステップ・オーバー|F6|F10|
|ステップ・リターン|F7|-|
|ステップ・アウト|-|Shift+F11|

[^1]: Javaアプリケーションのデバッグの場合


## 検索系
これも混乱しがち。
ここでは置換に言及していませんが、多くの検索ダイアログ内で切り替え可能なはずです。
Eclipseの“リソース検索”が便利すぎて多用中です。画面処理系とDtoの検索の時に超便利です。

|コマンド名|Eclipse|Visual Studio|
|:--|:--|:--|
|クイック検索|Ctrl+F|Ctrl+F|
|検索ダイアログを開く|Ctrl+H|Ctrl+Shift+F|
|リソース検索|Ctrl+Shift+R|-|

## リファクタリング系
対象範囲が一気に変えられてしまうので、注意が必要ですが、わかっているとちょっとおトク感のあるショートカットキー。

|コマンド名|Eclipse|Visual Studio|
|:--|:--|:--|
|名前の変更|Alt+Shift+R|Ctrl+R|
|移動|Alt+Shift+V|-|

## 開く（ジャンプ）系
メソッドの呼び出し元を開いたり（ジャンプしたり）するコマンドです。

|コマンド名|Eclipse|Visual Studio|
|:--|:--|:--|
|宣言（定義）を開く|F3|F12|
|型階層を開く|F4|-|

## コメント系
Visual Studioはシンプルですが、Eclipseは言語が混じるので要注意です。JSPのコードにJavaのコメントを書いちゃって「あれー？」なんてこともあったりなかったり。

|コマンド名|Eclipse|Visual Studio|
|:--|:--|:--|
|コメント|Ctrl+/ or Ctrl+7 or Ctrl+Shift+C|Ctrl+K, Ctrl+C|
|コメント（解除）|コメントと同様|Ctrl+K, Ctrl+U|
|ブロック・コメントの追加|Ctrl+Shift+\ |-|
|ブロック・コメントの除去|Ctrl+Shift+/ |-|

今のところはこんな感じで。
また思いついたら書きます。
（React + TypeScript）i18nextで名前空間の導入

[（React + TypeScript）UseContextとi18nextを使ってi18n対応してみる](https://qiita.com/_akira19/items/be421679e7fe38b6a936)の続きみたいな感じです。

i18nextを使ったi18n対応で、コンポーネントごとにファイルを分けたいので名前空間を導入します。

## 名前空間の導入
```tsx:App.tsx
import { useTranslation, initReactI18next } from 'react-i18next';
import i18n from 'i18next';
import enCommon from './locales/en/common.json';
import jaCommon from './locales/ja/common.json';
import jaNamespace1 from './locales/ja/namespace1.json';
import enNamespace1 from './locales/en/namespace1.json'

i18n.use(initReactI18next).init({
  debug: true,
  resources: {
    en: { common: enCommon },
    ja: { common: jaCommon },
  },
  lng: 'ja',
  fallbackLng: false, 
  returnEmptyString: false, 
});

// 名前空間の追加
i18n.addResources('ja', 'namespace1', jaNamespace1);
i18n.addResources('en', 'namespace1', enNamespace1);

export const App: FC = () => {
  const { i18n } = useTranslation();

  // ...以下省略
}
```

初期化時にはcommonという名前空間しかありませんでしたが、`addResources('locale名', '名前空間（ファイル名）', importしたファイル)`という関数を使って別の名前空間を追加できます。

## 名前空間の使用
```tsx:Component.tsx
import { useTranslation } from 'react-i18next';

export const Component = () => {
  const { t } = useTranslation('namespace1');
  return(
     <p>{t('テスト1')}</p>
     <p>{t('テスト2')}</p>
  );
}
```
`useTranslation()`の引数に名前空間の名前をいれることで、このコンポーネント内ではデフォルトの名前空間として、namespace1.json内で定義されてる単語、文章を出力します。（この例ではテスト1とテスト2がキーになります）

## 辞書ファイルの自動生成
[こちらの記事](https://qiita.com/suzukalight/items/54860fdda35e6ce983d9)で紹介されている自動で辞書を生成する`babel-plugin-i18next-extract`というライブラリですが、名前空間を自動で検出してくれます（助かるー）。
上記の章のテスト1、テスト2というキーが存在しない場合、自動でテスト1、テスト2というキーを作成してくれます。

```json:package.json
"scripts": {
    "i18next-extract": "NODE_ENV=development babel './src/**/*.{js,jsx,ts,tsx}'"
  },
  "babel": {
    "presets": [
      "react-app"
    ],
    "plugins": [
      [
        "i18next-extract",
        {
          "locales": [
            "ja",
            "en"
          ],
          "outputPath": "./src/locales/{{locale}}/{{ns}}.json"
        }
      ]
    ]
  },
  "dependencies": {
   ...以下省略
```
ここで`outputPath`が出力するjsonファイルになります。
そのため日本語の辞書は、`src/locales/ja/namespace1.json`へ、英語の辞書は`src/locales/en/namespace1.json`へ自動的に出力されます。

あとは、`yarn i18next-extract`するだけです。

## 疑問
本当は名前空間を導入して、各ページごとに読み込むファイルを分けたかったんですが、うまくいきませんでした。。。
ページごとにi18nを初期化すればできそうだけど、なんか違う様な。。。
詳しい方いらっしゃたら教えてください。

(2020.02.5追記)
一晩寝かせておいたらなんかできました。

```tsx:ChildComponent.tsx
  useEffect(() => {
    i18n.addResources('ja', 'namespace2', jaNamespace2); 
    i18n.addResources('en', 'namespace2', enNamespace2); 
  },[])
```

こんな感じでuseEffectで囲うだけ。

## 参考文献
https://www.i18next.com/overview/api#addresourcebundle
https://i18next-extract.netlify.com/#/configuration
Androidアプリの時間指定公開の手順と注意点【2020年2月4日時点】

Google Play Console で【時間指定公開】をする場合のやり方と注意点のメモです。
現状、UXがかなり分かりにくいので、早く改善されることを祈ってます。

対象：すでにリリースされているアプリのアップデート更新での利用
#時間指定公開とは？
時間指定公開と聞くと、日時を設定して、自動的にストアにリリースされるイメージですよね？　しかしAndroidではこの概念がそもそも違います。

Androidアプリの時間指定公開とは、**先に申請をだして審査を完了させておき、後日公開したい日に開発者が手動でアプリをリリースする機能**のこと。

時間指定じゃないやん！って思いますよね。
iosとは公開の概念が全く違うので注意が必要です。


#【注意】内部テストを飛ばして審査中の時は、そもそも時間指定公開の設定ができない


調査してみたところ、どうやら現状では内部テストが審査中のステータスの時は、時間指定公開の設定はできない仕様のようです。

審査中のステータスが消えると、時間指定公開設定バーが表示されるようになるので、内部テストがリリースされてから製品の時間指定公開の設定をするようにしましょう。

これはヘルプを見ても分からなかったので注意が必要です。

 [Play Console ヘルプ 時間指定でアプリを公開する](https://support.google.com/googleplay/android-developer/answer/9543912?hl=ja "時間指定でアプリを公開する")


#【STEP1】時間指定公開をonにする
![01-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486362/ca11d93f-c4f2-0f27-aa28-9466047d8a7e.png)

google play consoleの左メニュー`ストアの掲載情報`を選択し、右画面下に表示されている`時間指定公開`のトグルを**on**にする

#【STEP2】時間指定公開のホップアップでオンにするを選択
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486362/9a4f20d0-3d91-c0cc-3910-ce49bf4ccc0a.png)

#【STEP3】トグルがonになっていることを確認する
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486362/5835c885-8368-7244-425e-65ae5e60dc69.png)

トグルがonになっているのを確認して下さい。
この時、右側にあるボタン【アップデートを送信】は何も触らずに無視して下さい。

#【STEP4】通常の製品リリース手順と同じ操作をして製品版として公開を開始ボタンを押す
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486362/0318aa30-bb38-a2dc-588c-5780d3dfbbbf.png)
製品リリース手順はここでは省きますが、いつも通りAPKを設定しリリースノートなどを準備して下さい。

添付画像の`製品版として公開の開始`ボタン押すとリリースされてしまうのでは？！
という恐怖心があるかとおもいますが、勇気を振り絞ってポチっと押してしまいましょう。
このボタンを押すと審査が始まりますが、**審査が完了しても自動公開はされません**のでご安心下さい。

審査は場合にもよりますが早ければ数時間以内、長ければ最大７日程かかる場合があるようです。

#【STEP5】審査が終わったら公開したい日時に公開ボタンを押すと即座にストアに公開される
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486362/133eaff8-b4d8-03e5-ab19-e6bc1d9e1479.png)
審査が無事完了すると、添付画像のようにアプリのリリースページ上部にバーが表示されるので、公開したいタイミングで`公開`ボタンを押せば即座にplay storeに反映されます。

ストアに問題なくアップデートが反映されていたら作業完了です。

#まとめ
時間指定公開でアプリのアップデートをリリースしたい場合、毎回このトグルをonにする作業からやる必要があります。

また、審査をしてもらうために「製品として公開を開始」という今にもリリースしてしまいそうな文言のボタンを勇気出して押さなくてはなりません。

初めて時間指定公開をする時にひっかかりやすい部分だと思うので、少しでもお役に立てれば幸いです。

現場からは以上ですm(_ _)m
PythonでModuleNotFoundError: No module named 'XXX'が起きた時の対応


表題の対処メモです。
今回はWTFormsが無い想定です。

##まずはpip showでモジュールが存在するか確認

```console
pip show WTForms
Name: WTForms
Version: 2.2.1
Summary: A flexible forms validation and rendering library for Python web development.
Home-page: https://wtforms.readthedocs.io/
Author: Thomas Johansson, James Crasta
Author-email: wtforms@simplecodes.com
License: BSD
Location: /Users/XXX/.pyenv/versions/3.7.5/lib/python3.7/site-packages
Requires: 
Required-by: wtforms-validators, Flask-WTF 
```
※ここで存在しなければモジュールをインストール(pip install Flask-WTF)してください。


##ソースにLocationのパスを通す

```sample.py
import sys
sys.path.append("/Users/XXX/.pyenv/versions/3.7.5/lib/python3.7/site-packages")
```

これで解決しました。

##参考
https://web.plus-idea.net/2017/05/python-import-error-no-module-name/
Mac Chromeで使うショートカット


|__タブとウィンドウ__  |　　　　　　　　　　　　　  |
|---|---|
|隣のタブに移動する  |⌘+option+矢印  |
|特定の・最後のタブに移動する  |⌘+1~8・9  |
|戻る・進む  |⌘+[・] または ⌘+矢印  |
|現在のタブまたはポップアップを閉じる &nbsp;&nbsp; |⌘+w  |
|__Google Chrome 機能__  |  |
|デベロッパーツール（検証）を開く・閉じる  |⌘+option+i  |
|__アドレスバー__  |  |
|アドレスバーに移動する  |⌘+l  |
|__ウェブページ__  |  |
|再度読み込み  |⌘+r  |
|キャッシュコンテンツを無視して再度読み込み  |⌘+shift+r  |
|クリック可能な項目間を移動する（順・逆）	  |tab・shift+tab  |
|ページ上のすべての要素を拡大・縮小する	  |⌘+ +・-  |
|ページ上のすべての要素をデフォルトのサイズに戻す	  |⌘+0  |
|ウェブページを 1 画面ずつ下・上にスクロールする	  |space・shift+space  |
|ホームページを現在のタブで開く  |⌘+shift+h  |
adb接続できない端末でadbコマンドを実行する

特殊すぎる状況だと思います。普通に開発していれば知らなくて良い情報だと思いますが、同じ境遇に遭遇してしまった方へ哀悼の意を込めてこの記事を贈ります。

## 対象端末

私が出逢ってしまった子のスペックは、以下のとおりです。

- Android5.0
- WiFi接続は可能
- USB type-Aのポートはあるけど、ADB接続できなさそう
- USB type-Cはない
- micro USB Type-Bもない

つまりPCと接続できないため、**adbコマンドが実行できない**という特殊端末を想定します。
Wifi経由での接続方法もありますが、その場合もwifi経由での接続前に`adb tcpip`コマンドを打つ必要があるため、一度はPCとのadb接続しなくてはいけません。

## 手順

#### (1)Android端末上でコマンドを打てるアプリをインストールする

Android端末上でadbコマンドを実行するため、アプリをインストールします。必要に応じて、ストアから、またはサイトからAPKを落としてきてUSBなどで転送することも可能です。
ここではAndroid Terminal Emulatorを紹介します。 
[PlayStoreから](https://play.google.com/store/apps/details?id=jackpal.androidterm&hl=ja)
[サイトからAPKをDL](https://android-terminal-emulator.jp.uptodown.com/android)

#### (2)ADB接続

```shell
su 2000 -c 'setprop service.adb.tcp.port 2020'
su -c 'stop adbd && start adbd'
su -c adb connect localhost:2020
```

**1行目**
adb接続のためにlistenするポートを指定します。ここで、2020の部分はポートの指定ですが、1024以上ならOKとのことです。
**2行目**
adbを再起動します
**3行目**
localhostにadb接続します。このとき、1行目で指定したポート番号を指定します。

[こちらの記事](https://android.stackexchange.com/questions/142533/run-adb-command-inside-the-terminal-emulator-or-programmatically-without-root)を参考にしました。


以上で、PCとの接続なしでADBコマンドを端末から直接実行できます。
MySQLで足りない日付を埋めたい

何かのデータを日付ごとに出したい時、

```sql
SELECT date_format(created, '%Y-%m-%d') AS date,
       count(id) AS count
FROM users
GROUP BY date;
```

とすると、

```sql
+------------+--------+
| date       | count  |
+------------+--------+
| 2020-02-04 |     1  |
| 2020-02-02 |     2  |
| 2020-01-31 |     4  |
+------------+--------+

```
`created`に存在しない日付は飛ばされてしまいます。


# 解決

1. 日次ごとの日付テーブルを作成し、
2. そこに必要なテーブルをJOINしていきます


## 日次ごとの日付テーブルを作成
```sql
SELECT CURDATE() - INTERVAL seq_no DAY AS date
FROM
  (SELECT @seq_no := 0 AS seq_no
   UNION SELECT @seq_no := @seq_no + 1 AS seq_no
   FROM information_schema.COLUMNS LIMIT 5) tmp

+------------+
| date       |
+------------+
| 2020-02-04 |
| 2020-02-03 |
| 2020-02-02 |
| 2020-02-01 |
| 2020-01-31 |
+------------+
```

## 必要なテーブルをJOIN
```sql
SELECT date_table.date AS '日付',
       IFNULL(count_table.count, 0) AS '登録者数'
FROM
  (SELECT CURDATE() - INTERVAL seq_no DAY AS date
   FROM
     (SELECT @seq_no := 0 AS seq_no
      UNION SELECT @seq_no := @seq_no + 1 AS seq_no
      FROM information_schema.COLUMNS LIMIT 5) tmp) date_table
LEFT JOIN
  (SELECT date_format(created, '%Y-%m-%d') AS date,
          count(id) AS COUNT
   FROM users
   GROUP BY date) count_table ON date_table.date = count_table.date;

+------------+--------+
| date       | count  |
+------------+--------+
| 2020-02-04 |     1  |
| 2020-02-03 |     0  |
| 2020-02-02 |     2  |
| 2020-02-01 |     0  |
| 2020-01-31 |     4  |
+------------+--------+
```

`IFNULL(count_table.count, 0)`で、JOINしたテーブルに日付が存在しない場合は、count数を0に指定しています。
【CocoaPods】iOSのライブラリをForkして使う

iOSアプリのライブラリを一部カスタマイズして使う機会があったので。

# フォーク
まず普通にFork。
https://help.github.com/ja/github/getting-started-with-github/fork-a-repo
GitHub公式練習用リポジトリ[Spoon-Knife](https://github.com/octocat/Spoon-Knife)を使って説明。

このボタンを押して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272677/4ab2c658-2d75-68cc-59c5-b38f67ab5487.png)
こうなれば成功。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272677/127e8f4d-cf79-016f-8bb2-13d236845d46.png)


Fork元の変更を楽に取り込むローカル構成手順もあるが割愛。
https://help.github.com/ja/github/getting-started-with-github/fork-a-repo#step-1-set-up-git

# Podfile
ライブラリを修正したら、Podfileで本来このように書くものを…

```ruby
  pod 'Spoon-Knife'
```

このようにfork先のrepoとbranchを指定して`pod install`。

```ruby
  pod 'Spoon-Knife', :git => 'git@github.com:{{ your name }}/Spoon-Knife.git', :branch => '{{ your branch }}'
```

参照 : https://guides.cocoapods.org/using/the-podfile.html#from-a-podspec-in-the-root-of-a-library-repo

ただし元のライブラリが既にインストール済みの場合、リポジトリのみの変更は解釈されないので一度この行を消しての再インストールが必要だった。
AWS Lake Formationの概要を図と用語で整理する

[AWS Lake Formation](https://aws.amazon.com/jp/lake-formation/)をざっくりと理解するために基本的な概念とコンポーネントを、図と用語で整理してみます。


# AWS Lake Formationとは？
- **AWSでデータレイクを構築・運用するためのマネージドサービス**
    - 実体は、ほぼAWSの各種サービスをラップしたもの(Glue, IAM, S3, etc..)
    - データレイク専用にアクセス制御を行うために、IAMとは別に独自の権限管理機構を持つ
- **実データも保持しセキュリティ向上と権限管理が簡単に行えるAWS Glue**という印象
    - IAMやGlueを個別に駆使してデータレイクを構築・運用するよりデータレイクに特化していて扱いやすい

# ざっくりした概念図
図にするとかなりシンプル。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50056/3f3012ba-2336-0e40-9d8a-914078442b57.png)


## 備考
- [公式ドキュメント](https://docs.aws.amazon.com/lake-formation/latest/dg/what-is-lake-formation.html) (2020/02/04時点では英語のみ)
- [公式マンガ](https://aws.amazon.com/jp/campaigns/manga/vol9-1/)があるよ
- Lake Fromationの根っこにはAWS Glueがあるため[AWS Glueの概要を図と用語で整理する](https://qiita.com/sot528/items/1c56bb95ac3060772634)と一緒に見るとわかりやすいかもしれません

# 用語
AWS Lake Formationにおける各用語の定義。

|用語|意味|
|---|---|
|データレイク(Data Lake)|Lake Formationの**データカタログ**の実体としてS3に保管されたデータ。構造化データ、非構造化データのどちらも格納する|
|データアクセス(Data Access)|Lake Formation（以後LF）において、データへのアクセス権限を管理する。実体はIAM|
|ブループリント(Blueprint)|データレイクにデータを簡単に格納するためのテンプレート。ブループリントから**ワークフロー**を作成できる。|
|ワークフロー(Workflow)|関連ジョブの入れ物。**ブループリント**から生成される。実体はAWS Glueのクローラーとトリガー。Glueの面倒なあれこれをラップしている|
|データカタログ(Data Catalog)|**メタデータストア。**Apache Hiveのようにメタデータでデータを管理。実体はそのままGlueのデータカタログ。1AWSアカウント、1リージョンに1つだけ作成できる|
|Underlying Data|**データカタログ**の**テーブル**が参照する元データ|
|プリンシパル(Principal)|そのままIAMのプリンシパル|
|データレイク管理者(Data Lake Administrator)|Lake Formation管理下にあるリソースの全権限を付与されたプリンシパル。LFを開始した際に最初に作られるユーザ。データレイク専用の管理者としてIAMの権限管理機能とは別に定義されており、IAMの`AdministratorAccess`を持っていても自動的にはデータレイク管理者にはならない(自分で自分を指定することは可能)。[※詳細](https://docs.aws.amazon.com/lake-formation/latest/dg/access-control-overview.html)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50056/2ab4f94d-f51d-d703-c563-441268952b62.png)|

# メモ
- LFはGlueとデータカタログを共有する
- Glueにできないことはできない
macにwindowsを入れる

# macにwindowsを入れる

## virtualboxのmac用をダウンロード
https://www.oracle.com/virtualization/technologies/vm/downloads/virtualbox-downloads.html

![スクリーンショット 2020-02-04 18.03.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33553/934cf15c-7c89-e7e0-5fc5-dcfa7e743e52.png)

## virtialboxを解凍し開く

※ 自分のはすでに入れてしまったので画像ではある。。。！！

![スクリーンショット 2020-02-04 18.10.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33553/a3cc1ab7-4662-5faf-5003-32afdb1b3713.png)


## microsoftのサイトでイメージをダウンロード

### 今回はcrominiumじゃないedge
https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/

![スクリーンショット 2020-02-04 18.05.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33553/2f3077aa-3584-09e9-f9b9-2cf20cbdd186.png)

## 解凍

`The Unarchiver` を使って解凍

https://theunarchiver.com/

![スクリーンショット 2020-02-04 17.06.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33553/ccf00459-9a27-7a05-3e0b-864ee1c5417f.png)

## イメージをvirtualboxにインポート

![スクリーンショット 2020-02-04 18.15.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33553/5504ac54-0c74-3d68-cbf2-0395f9629127.png)

![スクリーンショット 2020-02-04 18.15.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33553/404090fb-1629-2ef1-730f-b69dc63f851b.png)


![スクリーンショット 2020-02-04 17.05.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33553/5b463029-a6c4-dab2-f43f-defe0fcad30b.png)

## virtualboxのWin10を起動

クリックして起動
![スクリーンショット 2020-02-04 18.19.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33553/7b9b3cca-2365-145a-ae56-952be9ca0b69.png)

#### ユーザーパスワードは `Passw0rd!`を入力

![スクリーンショット 2020-02-04 18.21.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33553/db592c98-9623-754a-5918-2a9c3875af7a.png)

## 言語を日本語に変更

検索ボックスから `language` で検索  
ローカルエクスペリエンスパックをクリック

![スクリーンショット 2020-02-04 18.24.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33553/3a1b375a-8ef5-b3ec-33e4-3d9ef69b8446.png)

![スクリーンショット 2020-02-04 17.57.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33553/3f409b89-40d2-0ea3-694c-8803adc48b84.png)

をインストールして、言語を日本語に変更する