OmniAICreator/Qiita-1.07M huggingface dataset:
Google Apps Script（GAS）で日付の計算でつまづいたこと

GASで日付の計算をしたときに、記述の仕方によって処理結果が大きく変わってしまいましたので投稿します。

# 参考サイト
https://macprimary.white-doll.net/?p=304

# 成功した記述例

```js
// 今日から3日前の日付
var date = new Date();  // 今日の日付を取得
var newDate = new Date(date.getYear(), date.getMonth(), date.getDate() - 3);  // 3日前にする

// 今日から5日後の日付
var newDate = new Date(date.getYear(), date.getMonth(), date.getDate() + 5);  // 5日前にする
```

## for文を使用
```js
var date = new Date();  // 今日の日付を取得
for( var i = 1; i < 7; i++ ){
  var newDate = new Date(date.getYear(), date.getMonth(), date.getDate() - i);  // 1日ずつ日付をさかのぼる
  Logger.log( Utilities.formatDate( newDate, 'Asia/Tokyo', 'yyyy/M/d') );       // ログに出力
}
```

# 失敗した記述例1
for文を使用した場合に以下のような記述にしてしまうと思わぬ処理結果になります。
説明を分かりやすくするために日付を指定しておきます。

```js
var date = new Date("2019/12/2");  // 日付を指定
var day = date.getDate();          // 日付のみ取得
for( var i = 1; i < 7; i++ ){
  date.setDate(day - i);
  Logger.log( Utilities.formatDate( date, 'Asia/Tokyo', 'yyyy/M/d') );
}
```

上記のように `getYear()` `getMonth()` を書かずに `getDate()` のみとし、 `setDate()` を使用すると以下のように途中から1月ずつさかのぼってしまいます。

```
出力結果
2019/12/1
2019/11/30
2019/10/30
2019/9/28
2019/8/28
2019/7/27
```

# 失敗した記述例2
今度は `date.getDate()` を変数に入れずに直接記述したものです。

```js
var date = new Date("2019/12/2");  // 日付を指定
for( var i = 1; i < 7; i++ ){
  date.setDate(date.getDate() - i);
  Logger.log( Utilities.formatDate( date, 'Asia/Tokyo', 'yyyy/M/d') );
}
```
```
出力結果
2019/12/1
2019/11/29
2019/11/26
2019/11/22
2019/11/17
2019/11/11
```

このように日付が1日ずつではなくさかのぼる日数がどんどん増えていきます。
減算の例のみをあげましたが、加算の場合でも同様の結果になります。
記述例1の方は月が変わる処理をしてしまうと、1月ずつさかのぼってしまいますが月が変わらなければ正常に処理が可能です。
なお、どちらのパターンでもfor文を使用しなければ指定した数字での計算が可能です。

```js
var date = new Date("2019/12/2");  // 日付を指定
var day = date.getDate();          // 日付のみ取得
date.setDate(day - 3);
Logger.log( Utilities.formatDate( date, 'Asia/Tokyo', 'yyyy/M/d') );
```
```
出力結果
2019/11/29
```

# 結論
日付の計算をする場合は `getYear()` `getMonth()` `getDate()` のすべてを指定しておくとよさそうです。

```js
new Date(date.getYear(), date.getMonth(), date.getDate() - n);
```
5秒で見せられる餃子コマンド(ハンズオン)


AdventCarender22日目を務めます、DMM WebcampメンターのNIRA GYOZA(@gyouza)です!!!

# はじめに

皆も経験した事がある事だと思います。仕事中で、ふとした時にあの丸みを帯びた艶やかなbodyをした餃子を拝めたくなる時を何回も経験した事があると思います。しかしながら仕事中はかぐわしい匂いがする餃子を食べにくいです。食べられない所がほとんどでしょう。なのでいつでも見れるように、パソコン内に餃子を作りました。とても簡単で作れたので、作り方を布教したいと思います。


この記事は自作コマンドのハンズオンです(Mac OX)。目的は物を作り上げて、***普段のプログラミング学習環境をすこしだけハッピー***にする事です。

では作っていきましょう！

# 完成品
指定した文字をターミナルで打つと,何かが表示されるものを作ります。タピオカコマンドやネココマンド、色んなコマンドを作成できます。

![gyoza.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307230/e05972a2-a3a9-33f4-a168-879601a673ec.gif)

# 🥟作り方🥟

準備するもの
- 表示させたいものの画像
- 美味しく作るための愛情

## 実行するファイルの作成

```terminal:ターミナル
$ cd ~/
$ mkdir bin
$ cd bin
$ vim gyoza 
```

gyozaファイルの中身を書いていきます！
挿入モードにしてからgyozaファイルに

```terminal:gyoza
echo 'hello gyoza'
```

と書いた状態でこの記事を読み進めていくと、gyozaとコマンドを押すとhello worldが帰ってくるようになります。
つまり、***echo '表示内容'*** となります。

最初にみたgifのようなものに、リアルな餃子感を出す場合はこちらの[アスキーアート生成](https://tool-taro.com/image_to_ascii/)というサービスを利用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307230/229426cb-1736-f341-5468-67e7fd98beaf.png)

上記のサービスで表示させたい物の画像をテキスト形式に変換してもらいます。その内容をコピペして、echoの後に貼り付けましょう。横幅は任意のサイズで大丈夫です。

ファイルの保存方法は「esc」→「:wq」です。
詳しいvimの操作方法はこちら([マジで最低限覚えておきたいvimの使い方【Vim入門】 ](https://takakisan.com/vim-how-to-use-begginer/))よりお願いします。

実行するファイルを作成が出来ました！！！！！
残る肯定は実行するための設定です。

## ファイルのパスを通す

パスを通すとは？([PATHを通すとは？ (Mac OS X)](https://qiita.com/soarflat/items/09be6ab9cd91d366bf71))
簡単にいうと実行するファイルを探しに言っている事らしいです。

```terminal:ターミナル
vim ~/.bash_profile
```

ファイルの中身を追記する。

```:.bash_profile
PATH="$PATH:~/bin"
```

.bash_profileの内容を即座に反映させるようにする。

```terminal:ターミナル
source ~/.bash_profile
```


完成〜〜〜〜！！！！美味しく出来ましたか？ぜひ友人やご家族に見せてみてください！！！！！！！！

## 表示されなかった場合

ファイルの権限ですかね。。実行ファイルの権限を変更してみてください。

```terminal:ターミナル
sudo chmod 755 実行ファイルへのパス
```

# まとめ
記事を読んでもらうとわかると思うのですが、正直とても難しい事はしていません。コピペをするとできます。
しかしながらアスキーアート生成のアプリを知らない方が大半なおかげもあり、ありがたい事に、初めて見せた時には驚いてもらえました。しかも仕事中に美味しそうなビジュアルて的に可愛い餃子が見れるので、作業効率も爆上がりしました。(個人差あり)

ぜひ誰かに見せてみてください。少しでもこの記事をみて作ってくれて、それを元に誰かを笑わせる事。誰か1人でも楽しい開発ライフを送ってくれたら嬉しいです。

最後まで読んでいただきありがとうございました。それでは皆さん良い餃子ライフを！！！！！！！！！！！！！！！

# 参考記事

[コピペ1分でMacの自作コマンドを作る](https://qiita.com/JJJJJJJJ/items/cc4357f5ba2a9eed809d)
MACBOOK PROでMAMPを利用したDATABASE作成でつまづいた話


備忘録として書き残すので大した内容ではありませんがもし同じように悩む人の役に立てばこれ幸い也。

勉強書「スラスラわかるPHP　志田仁美　著」

##経緯
PHPの勉強でホームページ制作。コンテンツ内に掲示板を作成することにした。当方MACBOOK PRO でMAMPを使って環境構築し順調に設計していたがMySQLで作成したデータベースが読み込めない。ぜんぜん読み込めない。ｗｈｙ？


![スクリーンショット 2019-12-03 14.50.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517245/9ef32197-6f74-97a6-1088-50ae9b77226e.png)



##原因
phpの記入ミスやMySQLのデータベースに正しくログインできていなかったのでは？とうろたえて数日経過。
なんてことはない。
自身のPCにMySQLをインストールしてデータベースを使用していただけだった。
MAMPにはローカル開発環境を立ち上げるために必要なソフトウェア（Apache、MySQL、PHP）がパッケージ化されているんだから余計なことしなくてよかったのだ。

##解決法
備忘録なので簡潔に

1. MAMPを起動してターミナルを起動する
2. ターミナルからMAMPの作業ディレクトリへ移動

`````console
$ cd /Applications/MAMP/Library/bin/
`````
このコマンドで作業ディレクトリへ

3.MAMPの作業ディレクトリからMySQLへログイン

通常のMySQLへのログインと同じ

`````console
$./mysql -u root -p
`````

`````
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.26 MySQL Community Server (GPL)

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

`````




4.データベースを作成する

こちらも通常どうりに使用する。
今回は簡易的な掲示板作るための最低限のデータベースとテーブルを作成した。

**データベース作成**

`````sql
mysql> create database (データベース名);
Query OK, 1 row affected (0.07 sec)
`````

**データベース選択**


`````sql
mysql> use (データベース名)
Database changed
`````

**テーブル作成**

`````sql
mysql> CREATE TABLE bbs(
    ->   id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    ->   name VARCHAR(255) NOT NULL,
    ->   title VARCHAR(255),
    ->   body TEXT NOT NULL,
    ->   date DATETIME NOT NULL,
    ->   pass CHAR(4) NOT NULL
    -> )DEFAULT CHARACTER SET=utf8;
`````


これで完成。
PHPは問題なかったため掲示板は問題なく動作しました。
同じ間違いは二度と犯さないようにしよう。
Github Actionsで始める ChatOps

# はじめに

Kubernetes のリポジトリを眺めていると Github の PR 上で bot に対してコマンドを実行するのをよく見ますよね。例えば[こういうもの](https://github.com/kubernetes/kubernetes/pull/85651#issuecomment-558777342)です。 

<img width="826" alt="スクリーンショット 2019-11-27 19.27.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100565/0d5b281c-4f1a-e79a-37ce-3f3b0a312bae.png">

Kubernetes のプロジェクトでは PR 上でのテストやラベル付けなどを行っていますが、自分たちはこれを見て日々の運用作業を PR や issue 上で ChatOps で実現したいと思いました。
Github上で行うと Chat 上に比べて後から探しやすいといったメリットがあると思っており、それを実現できないかと考えていました :thinking: 

これを実現する方法としてまずに思いつくのは Kubernetes プロジェクトで利用している [Prow](https://github.com/kubernetes/test-infra/tree/master/prow) を利用する方法です。ただ Prow で実施する場合 Prow 自体のデプロイ・その後の管理をする必要があり、~~そのあたりが面倒になってしまい~~そこまでのコストを掛けて実現するべき運用作業もないため今まで実現には至っていませんでした。。。

手軽に実現できるツールはないかと調べていて Argo Events + Argo Workflow などいくつかを試していましたがあまりしっくりとくるツールが見つからない日々が続きました。そんなときに登場したのが [Github Actions](https://github.co.jp/features/actions) です。

Github Actions はよくある CI ツールとは違って Github の細かいイベントでトリガーできるため一つの yaml ファイルを追加するだけで ChatOps ライクなことが実現できそうと思い試してみました。

# 試してみる

ChatOps で必要なイベントは issue や PR でのコメント作成または編集になります。
[公式ドキュメント](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows#issue-comment-event-issue_comment)を眺めてみるとこのように `issue_comment` というイベントがあります。
このイベントをトリガーにして、コメントの内容を条件にしてちょっとしたスクリプトを書くことで実現できそうです。

試しに /lgtm とコメントすると LTGM ラベルを付与するようにしてみます。


```.github/workflows/lgtm.yaml
name: LGTM action
on:
  issue_comment:
    types: [created, edited]
jobs:
  build:
    name: LGTM action
    runs-on: ubuntu-latest
    steps:
    - name: Run action
      env:
        GITHUB_REPOSITORY: ${{ github.repository }}
        ISSUE_PAYLOAD: ${{ toJson(github.event.issue) }}
        ISSUE_NUMBER: ${{ github.event.issue.number }}
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        labels=$(echo "${ISSUE_PAYLOAD}" | jq '.labels[]|.name' | jq -s . | jq -c '.|.+["LGTM"]|unique')
        curl -X PATCH -d '{"labels": '${labels}'}' -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/repos/${GITHUB_REPOSITORY}/issues/${ISSUE_NUMBER}
      if: startsWith(github.event.comment.body, '/lgtm')
```

*今回はスクリプトの中身は重要ではないので簡単なものにしています。パーサーやアクションをちゃんと書けば色々なことが実現できると思います*

上記のような yaml ファイルをリポジトリのデフォルトブランチ(大抵は master ブランチ)にpushします。[^1]
その後 issue にコメントしてみると

![スクリーンショット 2019-12-03 13.50.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100565/3aa06a29-c5f6-e6bb-fdb9-cfe5b4e01cd6.png)

無事ラベルが付与されました :tada: 

[^1]: スケジュールや issue のようなリポジトリに直接紐付かないイベントはGithubのデフォルトブランチに存在する workflow ファイルを見てジョブを実行するようです。

# おわりに

この記事では Github Actions を使って yaml ファイル一つで ChatOps を実現する方法を紹介しました。今回は簡易的なものでしたがスクリプト次第で様々なことができると思うので色々試してみたいと思います。現在自分のチームでも cherry-pick や簡単なデプロイを今回の方法で実現していたりします。
Google Chrome Remote Desktopが接続できなくなった - サーバーから紹介が返ってきました

# Google Chrome Remote Desktopが接続できなくなった。

つい最近までGoogle Chromeの[Remote Desktop](https://remotedesktop.google.com/access/) (https://remotedesktop.google.com/access/) が使えていたのだが、急に使えなくなってしまった。

## 「サーバーから紹介が返ってきました」と表示されていた。

![サーバーから紹介が返ってきました.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16128/ae6018e5-aff4-4473-0d7f-9f17828bc577.png)

※「紹介」って「照会」じゃねぇのかよ！

Remote Desktopを受けている方のPC、つまりサーバ側に、図の様なメッセージが一定時間ごとに表示されていた。
そこで「サーバーから紹介が返ってきました」をググって、解決策を見つける事ができた。

## 解決策

`C:\Program Files (x86)\Google\Chrome Remote Desktop` の下を `*.exe` で検索し、
「`remoting_desktop.exe`」を見つけて、プロパティを開いて以下の操作をする。

![rdp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16128/41f3da42-e62c-ec48-d72c-65e877c5a3f2.png)

「すべてのユーザーの設定を変更」をクリック。
　　↓

![rdp2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16128/a4ee8ebf-5ef4-d07e-81fe-7ae652387c70.png)

「管理者としてこのプログラムを実行する」をチェックして、「OK」クリック。

これで解決できた。
git submoduleのinitとupdateは同時に実行可能（git submodule update --init）


```shell
$ git submodule update --init
```

https://git-scm.com/docs/git-submodule#Documentation/git-submodule.txt-update--init--remote-N--no-fetch--no-recommend-shallow-f--force--checkout--rebase--merge--referenceltrepositorygt--depthltdepthgt--recursive--jobsltngt--ltpathgt82308203
0円から始めるVTuber

#本記事でできること
- 3Dモデルの作成
- フェイストラッキングで口パクと上半身の動きをつけた動画の作成
- 動画に字幕を付ける
- 作成した動画をエンコードする（YouTubeにアップできる形式の動画にする）

**とりあえず**VTuberデビューすることができます！

低クオリティながら最低限のことはできるのかなと考えています。
**高クオリティを目指す方には参考にならない記事だと思います。**

本記事では、例として歌ってみた動画を作成します。

#前提
- カメラとパソコンを所有している（カメラ付きラップトップでもOK）
- ネットに接続できる
- やる気がある！

以上を満たしていれば、
初期投資0円でVTuberデビューすることができます！

#使用ソフト
(Cake Walk)
セシル変身アプリ
hitogata
OBS
AviUtl

#さっそく作業を始めていこう！

##0.音源を作る
使用ツール：Cake Walk

歌ってみた動画を作成するので、まず音源を作ります。
##1.モデルを作る

使用ツール：セシル変身アプリ


##2.顔と上半身の動きをトラッキング

使用ツール：hitogata

##3.モデルの動きを録画する
使用ツール：OBS

録画範囲にhitogataの3Dモデルウィンドウを選択する。

##4.動画と音声をくっつける
使用ツール：AviUtl

いい感じに使えるように、ググってプラグインを色々入れましょう。

##5.動画に字幕を付ける
使用ツール：AviUtl

##6.エンコードする
使用ツール：AviUtl
プラグイン：x264guiEx

いい感じに動画ができたらエンコードします。
YouTubeに適した形式でビデオ圧縮を行いましょう。

##YouTubeにアップロード
以上でアップロードする動画が完成です。
おつかれさまです。

余力がある方はサムネイルを作りましょう！
（私は疲れたのでYouTube自動生成のサムネにしました。）

#おわりに
本当にお疲れさまでした！！！

ざっくりとした説明でしたが・・
皆様のVTuberデビューのお役に立てれば幸いです。
師走を駆け抜けろ！！ダッシュリレーゲーム with IchigoJam

### はじめに
スペースキー連打でキャラクターが走る IchigoJam BASIC を使ったゲームです。 
IchigoJam を複数台ジャンパー線で繋げばリレー形式にもできてしまいます。 
シンプルなだけに、大人も子どもも本気になれる。ちょっとしたワークショップにいかがでしょうか。
<img width="453" alt="スクリーンショット 2019-12-03 0.44.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188535/94bd3727-9d6e-f338-cf03-45f2b0f37fa3.png">

### 必要なもの
- IchigoJam （リレーをするなら複数台必要）
- キーボード／モニター等一式
- ジャンパー線 (IchigoJamを4台つなぐなら8本　GND-GND, IN1-OUT1を接続)

![ichigojam-connect.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188535/172fb09a-4067-d04f-3dfa-526a7a64124e.png)


### シングルダッシュ
```
5 ' DASH GAME SINGLE
10 CLS:CLT:C=0:P=0
20 LC 31,11:?CHR$(#FF)
30 'IF IN(1)=0 GOTO 30 ELSE CLT:LED1
40 GSB@DISPRUNNER
50 GSB@DISPTIME
60 IF !BTN(32) GSB180:CONT
70 IF BTN(32) GSB180:CONT
80 C=C+1:P=C/2
90 IF !SCR(P+2,11) GOTO40
100 GSB@DISPRUNNER
110 LC 12,11:?"!!GOAL!!":CLK
120 OUT1,1:WAIT5:OUT0
130 END
140 @DISPRUNNER
150   LC P,11:?" ";CHR$(#FB)
160 RTN
170 @DISPTIME
180  T=TICK()
190  LC0,0:?"TIME:";T/60;".";T%60/6
200 RTN
```
シングルプレイは下記からWebブラウザでも遊べます。
http://ur0.work/Xz1S
RUN もしくは F5キー でゲームスタート。

### マルチダッシュ（リレー）
#### 第一走者
```
5 ' RELAY DASH GAME FOR START
10 CLS:CLT:C=0:P=0
20 LC 31,11:?CHR$(#FF)
40 GSB@DISPRUNNER
50 GSB@DISPTIME
60 IF !BTN(32) GSB180:CONT
70 IF BTN(32) GSB180:CONT
80 C=C+1:P=C/2
90 IF !SCR(P+2,11) GOTO40
100 GSB@DISPRUNNER
110 LC 12,11:?"!!GOAL!!":CLK
120 OUT1,1:WAIT5:OUT0
130 IF IN(1)=0 GSB@DISPTIME:GOTO130 ELSE END
140 @DISPRUNNER
150   LC P,11:?" ";CHR$(#FB)
160 RTN
170 @DISPTIME
180  T=TICK()
190  LC0,0:?"TIME:";T/60;".";T%60/6
200 RTN
```
- LINE130で第一走者は他のIchigoJamgのプレイヤーがゴールし一周するまで合計タイムをカウントしたまま待つ
- 最後のIchigoJamのプレイヤーがゴールするとIN1への入力が発生しチームとしてゴールとなる

#### その他の走者
```
5 ' RELAY DASH GAME FOR OTHER
10 CLS:CLT:C=0:P=0
20 LC 31,11:?CHR$(#FF)
30 IF IN(1)=0 GOTO 30 ELSE CLT:LED1
40 GSB@DISPRUNNER
50 GSB@DISPTIME
60 IF !BTN(32) GSB180:CONT
70 IF BTN(32) GSB180:CONT
80 C=C+1:P=C/2
90 IF !SCR(P+2,11) GOTO40
100 GSB@DISPRUNNER
110 LC 12,11:?"!!GOAL!!":CLK
120 OUT1,1:WAIT5:OUT0
130 END
140 @DISPRUNNER
150   LC P,11:?" ";CHR$(#FB)
160 RTN
170 @DISPTIME
180  T=TICK()
190  LC0,0:?"TIME:";T/60;".";T%60/6
200 RTN
```
- LINE30でIN1の入力待ち（スタート待ち）
- 接続されている隣のIchigoJamのプレイヤーがゴールするとIN1への入力が発生しスタートとなる

### こどもたちとのワークショップ
夏にこどもたちと一緒にやったらこうなりました。熱くて楽しい。
https://www.facebook.com/pcn.takefu/videos/1081691295368381
年末まで毎日webサイトを作り続ける大学生 〜46日目 Cookieを使う、その他〜

##はじめに
こんにちは！@70days_jsです。

Cookieを使ってみました。
その他色々JavaScriptの機能を使ってみました。

今日は46日目。(2019/12/3)
よろしくお願いします。

##サイトURL
https://sin2cos21.github.io/day46.html

##やったこと
1. documentオブジェクトを利用する
2. onselectionchangeイベントと、getSelectionを利用する
3. cookieを利用する


では1からいきます。

###1. documentオブジェクトを利用する

ざっとこんな感じです。↓

![スクリーンショット 2019-12-03 13.39.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/4684d7d0-1bc8-2530-75a7-0006faf4d276.png)

```html
<div id="test"></div>
```

```javascript
// 最終更新日 lastModified
test.innerHTML += '最終更新日: ' + document.lastModified + '<br>';

// ドメイン名 domain
test.innerHTML += 'ドメイン名: ' + document.domain + '<br>';

// タイトル　title
test.innerHTML += 'タイトル名: ' + document.title + '<br>';

// プラグイン数 plugins
for (var i = 0; document.plugins.length > i; i++) {
    plugins += document.plugins[i] + ',';
}

test.innerHTML += 'プラグイン数: ' + plugins + '<br>';
```

documentオブジェクトは色々な情報が取得できて便利ですね。
当たり前ですが、どれもdocumentの後にプロパティ名をつけるだけで呼び出せます。

###2. onselectionchangeイベントと、getSelectionを利用する
名前だけじゃ分かりづらいですね。
onselectionchangeイベントは選択範囲の変更時に起きるイベントです。
getSelectionは選択範囲の文字列を調べるメソッドです。
gif↓
![test2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/54b8bd8d-c195-8c4e-0c4b-01a25e269130.gif)

あらかじめ用意しておいた文字列を選択すると、その文字列をinnnerHTMLに加えていくように書いています。

```html
    <div id="field2">
        <div id="charSelect">選択した文字列: </div>
        何だろう
        。
        どうしてか
        、
        僕は
        今日
    </div>
```

```javascript
// 選択範囲に変化があったときに起こるイベント　onselectionchange
document.onselectionchange = function () {
    // 選択された文字列を調べる　getSelection()
    let select = document.getSelection();
    charSelect.innerHTML += select;
}
```
onselectionchangeイベントもdocumentから取っています。

###3. cookieを利用する
では最後にcookieです。↓
![test3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/0c989080-db2b-3a16-a034-c0af01854bbd.gif)

太郎と名前を入力すれば、それをnameに入れてcookieで記録するようにしています。
もし、nameに値があれば、h2タグに値をいれて名前を表示します。

```html
<h2 id="myName"></h2>
...

<div id="field3">
    <button id="test2">cookieを作るボタン</button>
    <div id="cookieField"></div>
</div>
```

```javascript

test2.addEventListener('click', test3);

function test3() {
    let name = prompt('名前を入力してください。');
    document.cookie = 'name=' + name;
    document.cookie = 'your_type = shy';
    cookieField.innerHTML += 'クッキー: ' + document.cookie + '<br>';
    takeCookie();
    myName2();
}

function takeCookie() {
    if (document.cookie) {
        let cookie = document.cookie.split(';');
        cookie.forEach(function (value) {
            let content = value.split('=');
            cookieField.innerHTML += 'クッキーの値だけ: ' + content[1] + '<br>';
            if (content[0] == 'name') {
                cookieName = content[1];
            }
        })
    }
};

let myName = document.getElementById('myName');

function myName2() {
    if (cookieName) {
        myName.innerHTML = 'Hey, ' + cookieName + 'さん!';
    }
};
```

どうでもいいことを色々書いているので長くなっていますが、要はdocument.cookieで値を代入していて、cookie.forEachで値を取り出しているだけです。
cookieは一連の文字列なので、;で区切ってやります。
その後に=で区切って名前だけを取り出します。

###感想
最近眠れなくて脳がまともに働きません。プログラムミスかな？
冗談です。

最後までお読みいただきありがとうございます。明日も投稿しますのでよろしくお願い致します。
[Android] 加速度センサのサンプリング周波数が知りたいとき

端末依存で最大・最低・間隔が決まるので，確認用のコードを書いた。
メモです。

**Logcatに周期が[ns]で出力される**

```kotlin
package com.example.getrotationtest

import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.opengl.Matrix
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import kotlinx.android.synthetic.main.activity_main.*
import java.io.BufferedReader
import java.io.File
import java.io.InputStreamReader
import java.math.BigDecimal
import java.util.*
import kotlin.properties.Delegates
import kotlin.io.*
import kotlin.math.PI

class MainActivity : AppCompatActivity(), SensorEventListener {
    private var mManager: SensorManager by Delegates.notNull<SensorManager>()
    private var mSensor: Sensor by Delegates.notNull<Sensor>()
    private var maSensor: Sensor by Delegates.notNull<Sensor>()
    private var mgSensor: Sensor by Delegates.notNull<Sensor>()

    private var prevtime = 0L

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main);

        mManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

        mSensor = mManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)
        maSensor = mManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
        mgSensor = mManager.getDefaultSensor(Sensor.TYPE_GRAVITY)

    }

    override fun onSensorChanged(event: SensorEvent) {
        when (event.sensor.type) {
            Sensor.TYPE_ACCELEROMETER -> {
                Log.d("tag", (event.timestamp - prevtime).toString())
                prevtime = event.timestamp
            }
        }
    }


    //センサー精度が変更されたときに発生するイベント
    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
    }

    //アクティビティが閉じられたときにリスナーを解除する
    override fun onPause() {
        super.onPause()
        //リスナーを解除しないとバックグラウンドにいるとき常にコールバックされ続ける
        mManager.unregisterListener(this)
    }

    override fun onResume() {
        super.onResume()
        //リスナーとセンサーオブジェクトを渡す
        //第一引数はインターフェースを継承したクラス、今回はthis
        //第二引数は取得したセンサーオブジェクト
        //第三引数は更新頻度 SensorManagerから選択するか，usで指定する
        mManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_FASTEST)
        mManager.registerListener(this, maSensor, 238000)   // 加速度のセンサ
        mManager.registerListener(this, mgSensor, SensorManager.SENSOR_DELAY_FASTEST)
    }
}
```
MT4の文字化けを直す（Windows）

#問題
うちに勤めてる外国人が勝手に言語設定変えて、MT4が文字化けしました。
MT4のLanguage --> Japaneseで設定してもダメ。

#解決法
下のチェックボックスを外したら直りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447423/f695f578-07d1-6dbd-20dd-39b8cfbba4eb.png)
Javaによる任意の文字列作成コード


```java
import java.util.Random;

public class Test {
    public static void main(final String[] args) {
        final String romaji = "abcdefghijklmnopqrstuvwxyz";
        final String number = "0123456789";
        final String generator = romaji + romaji.toUpperCase() +number;
        System.out.println(getStr(generator, 10));
        System.out.println(getStr(generator, 10));
        System.out.println(getStr(generator, 10));
    }

    private static String getStr(final String input, final int length) {
        final Random random = new Random();
        final int num = input.length();
        final StringBuilder sb = new StringBuilder();
        final char[] chars = input.toCharArray();
        for (int i = 0; i < 10; i++) {
            sb.append(chars[random.nextInt(num)]);
        }

        return sb.toString();
    }
}
```
Flutter for Webでリンクを開く

Flutter 1.9でWebが統合されましたが、アプリ内でリンクを開くためには、ひと工夫必要だったので共有します。

# `url_launcher`
iOSやAndroidだけであれば、`url_launcher`で問題ありません。
しかし、`url_launcher`はplatform channelsを使ってネイティブのWebViewを呼んでいるので、Webでは動きません。

# `dart:html`
Webでリンクを開く方法として、`dart:html`を使う方法があります。

```dart
import 'dart:html' as html';

html.window.open(url, '');
```

しかし、`dart:html`をimportするとiOSやAndroidのビルドが失敗してしまいます。

# `url_launcher_web`
`url_launcher_web`は`url_launcher`と同じくFlutter謹製のプラグインです。
https://pub.dev/packages/url_launcher_web

使い方は非常に簡単で、`pubspec.yaml`に以下を記述するだけです。

```yaml:pubspec.yaml
...
dependencies:
  ...
  url_launcher: ^5.1.4
  url_launcher_web: ^0.1.0
  ...
```

あとは、`url_launcher`と同じです。

```dart
import 'package:url_launcher/url_launcher.dart';

launch(url);
```

iOSやAndroidだけでなく、Webでも外部リンクを開くことができます。

# サンプル
- [GitHub Trending](https://github.com/KiyohitoNara/GitHubTrending)
Unity 2018.4.12f1でVisual Studio Community(for Mac) ver.7.7.4を使ってると途中でUnityEngineのnamespaceが見つかりません(could not be found)と急に言われる。

表題の問題が発生し、コード補完もなにもあったもんじゃない状態になって途方にくれてましたが、インストール何度もし直したり、アップデートしようとするとVS自体が壊れるということで色々設定をいじってたところ、メニューバーの、

**Project > Solution Options**
で開いたダイアログの、

**Source Code > .NET Naming Policies**
の、

**Associate namespaces with directory names**
の下の、

**Use default namespace as root**
に、チェック入れたところとりあえず直りました。

ググっても全然情報ないので、備忘録代わりと、同現象で悩まれてる方の一助になればと思い記事に残してみます。
（理由も原理も、完全にこれで正しいかも疑問ですが。。）
${} テンプレートリテラルとは


### ${}テンプレートリテラルとは

ECMAScript 6 で新しく使えるようになった構文のひとつで、変数や式を組み込むための記号。

通常、文字列の中に変数を入れようとすると

```xxx.js
var foo = 'ート';
var bar = 'テンプレ' + foo + 'リテラル';
```

```xxx.js
var foo = 'ート';
var bar = `テンプレ${foo}リテラル`;
console.log(bar); // テンプレートリテラル
```

+演算子 を使わずに文字列を繋げていくことができます。
`${～}` の中には、式であれば何でも入れることができます！
メモリに関して

##計算
1日100万ページビュー
1日20時間アクセス

1,000,000(PV数) / 20(時間) = 50,000(ページビュー数/時間)
1時間に50,000PVアクセスがある。

Apacheの設定がKeepAlive Onの場合は数秒間接続が維持される為
仮に2秒とすると秒間ページビューが２秒間は重複する

>webページってcssとかjsとか画像とか1ページ読み込むだけでたくさん通信してるし、ECサイトなんかだと購入途中でつながりにくくなるのも嫌だからやっぱりある程度接続しててもらったほうがいいんじゃない？実際にお店で買い物をした場合で例えてみよう。
大行列の10人はいるお店で何かものを買おうとしたとき、商品を手にするたびに最後尾から並びなおすということがおきたらどうだろう？買う気失せますね（笑）そこで一時的にコネクションを維持しといてあげるよっていうのがKeepAliveだ。
[apache KeepAlive](http://kuniiskywalker.github.io/2014/04/12/2014-04-12-apache-keepalive/)

```
1時間 = 3600秒
50,000(時) / 3600(秒) * 2(keep秒)　＝27.77(1秒につきの同時PV数)
1回のプロセスで30MBの場合
30 * 27.7 = 831MB(秒)　＊同時接続を前提
```

上記で秒毎の同時アクセス数が計算できる。
>ところで、Apacheの設定が KeepAlive Off の場合、１ページビューは１接続ではありませんので要注意です。
ページを構成する画像 jpg,gif,png や css, js のリンクの数だけ、もしアフェリエイト広告や外部リンクの埋め込みがあればその総数だけApacheへリクエスト数（＝接続数＝プロセス数）が発生します。
[Webサイトのアクセス数増加と必要メモリ](https://www.very-cute.net/wp/83/)


>キャッシュには 2 種類があり、cache で示されるページキャッシュと buff で示されるバッファキャッシュが存在します。 ページキャッシュはファイルシステムに対するキャッシュであり、ファイル単位でアクセスするときに使用されるキャッシュです。
例えば、ファイルへデータを書き込んだときは、ページキャッシュにデータが残されるため、次回の読み込み時には HDD にアクセスすることなくデータを利用できます。 もうひとつのバッファキャッシュはブロックデバイスを直接アクセスするときに使用されるキャッシュです。
[メモリとキャッシュ](https://qiita.com/kunihirotanaka/items/70d43d48757aea79de2d)


＊間違いや本来はこういう考え方だよ等あればコメントを頂けると幸いです。
GROUP BYでの重複削除において、複数の条件を優先順位付で設定する

この記事は[MicroAd Advent Calendar 2019](https://qiita.com/advent-calendar/2019/microad)の3日目の記事です。

# はじめに
あるキーに対してレコードが重複する場合に、重複を削除したいことがあります。

よく使われる方法に`GROUP BY`で絞り込む方法や、`WHERE`句に一意になるような条件を記述する方法などがあるかと思います。

今回、少し工夫が必要な場面に遭遇したので、その解決策を紹介できればと思います。

# 状況
重複レコードに対して、以下のような優先順位でレコードを1つに絞り込みたい。なお、条件Cまでを判定すれば必ずレコードが一意に定まるものとします。

1. 条件Aを満たす
2. （条件Aでは1つに絞り込めない場合）条件Bを満たす
3. （条件A・条件Bでは1つに絞り込めない場合）条件Cを満たす

**「レコードを絞り込むための条件に優先順位があり、それぞれをその順番通りに処理したい」**という状況です。

面倒な点としては、「1つに絞り込めない」パターンとして「その条件を満たすものが複数存在する」場合と「その条件を満たすものが一つもない」場合の両方があり、`WHERE`や`HAVING`では条件を表現しづらいです。

重複行をまとめるための`GROUP BY`をうまく使いたいですが、`id >= hoge`のような条件を直接指定することはできません。

# 解決策

条件を満たしているかどうかを`0`または`1`の値で表現し、複数の条件を優先順に文字列連結して表現します。
これをカラムに設定し、次のように`GROUP BY`します。

```sql
SELECT
  key
  ,MAX(priority)
FROM (
  SELECT
    key
    ,CONCAT(
      -- 条件を満たしていれば1, 満たしていなければ0
      IF(condition_A, '1', '0'),
      IF(condition_B, '1', '0'),
      IF(condition_C, '1', '0')
    ) AS priority
  FROM
    xxx
) t
GROUP BY key
```

条件を`0`と`1`で表現したものを文字列連結にして`MAX`を取ることで、存在する中で最も優先度の高いパターンのものが選択されます。

条件をカラムに落とし込むことで`GROUP BY`時に条件を適用させることが可能で、`IF`の部分に記述できる条件であれば何でも適用可能です。また、例えば「`x`の値が最大」という条件であれば`IF`を使わず直接`x`の値を文字列連結するなど、応用も可能かと思います。

# おわりに

`GROUP BY`での重複削除において、複数の条件を優先順位付で設定する方法を紹介しました。

参考になれば幸いです。
Docker Destop for Windows の起動に失敗する

Visual Studio2019のasp.net coreでDockerにチェックを入れた場合
自動的にDocker Destop for Windowsをインストールしてくれますが
私の環境では

ユーザー設定変数 "ErrorActionPreference" または共通パラメーターが Stop に設定されているため、実行中のコマンドが停止しました。

とか言って起動しません

で、いろいろ当たってみたら

https://qiita.com/k_akimoto/items/182418e2d200616e7db6

が有効でした


https://social.technet.microsoft.com/Forums/windows/en-US/ee5b1d6b-09e2-49f3-a52c-820aafc316f9/hyperv-doesnt-work-after-upgrade-to-windows-10-1809?forum=win10itprovirt

コピーしておきます
Windows セキュリティを起動する（アプリの名前です）
アプリとブラウザーコントロールをクリック
一番下にあるExploit protectionの設定をクリック
プログラム設定のタブを選択
C:\WINDOWS\System32\vmcompute.exeを選んで編集をクリック
制御フローガード(CFG)のシステム設定の上書きのチェックを外して適用
Macで古いpyenv環境を除却してupdate

pyenvが古いようなので更新しようと思ったができない。
`witch`で確認したところ以下のような表示。なんだったか思い出せない。

```zsh
sot528@mac ~ % which pyenv
pyenv () {
	local command
	command="${1:-}"
	if [ "$#" -gt 0 ]
	then
		shift
	fi
	case "$command" in
		(activate | deactivate | rehash | shell) eval "$(pyenv "sh-$command" "$@")" ;;
		(*) command pyenv "$command" "$@" ;;
	esac
}
```

# 原因
昔、pyenvの環境を構築した際にbrewが対応しておらず手動で行っていた。

# 対応
ルートディレクトリに構築していたので、それを削除してbrewで入れ直す。

```zsh
rm -fr ~/.pyenv
brew install pyenv
```
Reactで特定の条件を満たす行の背景色を変えたい


## やりたいこと

値により行の背景を変えたい。ここではgenderがfemaleならピンクにする。
下記のような感じ。

![スクリーンショット 2019-12-03 13.15.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/e1a9ec7c-3ed8-0b2a-616a-2447a56d35b0.png "スクリーンショット 2019-12-03 13.15.05.png")



## 基本方針？

基本的には条件に応じて三項演算子等を使ってstyleやclassNameを切り替えるのが基本。

条件 ? A : B;

条件がtrueならA、falseならBを実行。

## CSSを切り替える

まず、CSSを切り替えてみる。
ループにて表を描画しながら、genderがfemaleなら背景を変えるような操作。

```
<tbody>
    {
        this.state.listData.map(member => (
            <tr key={member.docId} style={member.gender === "female" ? { background: "#ffe4e1" } : {}}>
                <td>{member.docId}d</td>
                <td>{member.email}</td>
                <td>{member.gender}</td>
                <td><img src={member.avatarUrl} height="30" width="30" alt="" /></td>
                <td><Link to={`/show/${member.docId}`}><Button size="sm" color="primary">詳細</Button></Link></td>
                <td><Link to={`/edit/${member.docId}`}><Button size="sm" color="success">編集</Button></Link></td>
            </tr>
        ))
    }
</tbody>
```


## Classを切り替える

classの場合も基本は同じ。

あらかじめ、

```css
.female {
  background: #ffe4e1;
}
```

のようなcssが定義されているものとして、下記のようにclassを切り替える。

```
<tbody>
    {
        this.state.listData.map(member => (
            <tr key={member.docId} className={member.gender === "female" ? "female" : null}>
                <td>{member.docId}d</td>
                <td>{member.email}</td>
                <td>{member.gender}</td>
                <td><img src={member.avatarUrl} height="30" width="30" alt="" /></td>
                <td><Link to={`/show/${member.docId}`}><Button size="sm" color="primary">詳細</Button></Link></td>
                <td><Link to={`/edit/${member.docId}`}><Button size="sm" color="success">編集</Button></Link></td>
            </tr>
        ))
    }
</tbody>
```

なお、もっとエレガントにclass名を制御したい場合は、[こちら](https://qiita.com/senou/items/6db926b8fcf5cdec3bf0)の記事が参考になります。
以上。
CentOS7でDropboxをまだ粘る

#(dropbox 85.4.155対応版 まとめメモ。)
引用元、参考元
>https://blog.haijiso.com/post/182703584881/dropbox%E3%82%92centos-7%E3%81%A7%E5%8B%95%E3%81%8B%E3%81%992019%E5%B9%B42%E6%9C%88%E6%99%82%E7%82%B9%E3%81%AE%E6%83%85%E5%A0%B1

>https://qiita.com/la_float/items/a846a391874b452047ca

の記事に加えて以下の手順でまだまだ使えそう。
動作は保証対象外。

##もともとの環境が整ってる人用 (81.4.195まで使えてた人)
追加で必要なもの。
<pre>
libatomic
python3-pygpgme
</pre>

上記をyumか何かでインストールしないと
<pre>
$ dropbox update
Note: python3-gpg (python3-gpgme for Ubuntu 16.10 and lower) is not installed
そのあとフリーズ
</pre>
という感じで怒られる。

インストール後は
<pre>
$ cd ~/.dropbox-dist/dropbox-lnx.x86_64-85.4.155
$ ln -s /usr/lib64/libatomic.so.1 #←これが追加必要
$ dropbox start
</pre>
で行けるはず。

## 一からの手順 (glibc 2.25の場合)
まず、`nautilus-dropbox-2019.02.14-1.fc21.x86_64`をインストール。
ただし、その前に、python3, python3-gobject を入れておく必要あり。
なお、yum の `python3 (python36)` だと依存関係でエラーが出るので、追加で空の `python3`, `python3-gobject` を入れておく。
SPECファイルサンプル (gobjectの例。テキトーでOK)
<pre>
Name:           python3-gobject
Summary:        This is a dummy package just for resolving dependency problems.
Version:        3.22.0
Release:        dummy.0
Group:          Development/Languages
License:        public domain
Packager:       hogehoge <hoge@fugafuga>
Source0:        %{name}-%{version}.tar.gz
Source1:        README
BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)

%description
This is a dummy package just for resolving dependency problems.

%prep
%setup

%build

%install

%clean
[ "${RPM_BUILD_ROOT}" != "/" ] && rm -rf ${RPM_BUILD_ROOT}

%files
%defattr(-,root,root)
%doc $RPM_SOURCE_DIR/README
</pre>

上記完了後、一度、`dropbox update`で怒られておく（というか、dropboxの最新版をダウンロードしておく）必要あり。
###**怒られ方**
<pre>
$ dropbox update
の後に
（略）
, "ImportError: /lib64/libc.so.6: version `GLIBC_2.18' not found (required by /home/hogehoge/.dropbox-dist/dropbox-lnx.x86_64-85.4.155/libdropbox_apex.so)\n"] (error 3)
</pre>
という感じ。
### glibcインストール
#### まず、rootで
<pre>
 # yum install centos-release-scl
 # yum install centos-release-scl patchelf
 # yum-config-manager –enable rhel-server-rhscl-7-rpms
 # yum install devtoolset-7
</pre>
#### 一般ユーザで
<pre>$ scl enable devtoolset-7 bash
$ tar zvxf glibc-2.25.tar.gz
$ cd glibc-2.25
$ mkdir build
$ cd build
$ ../configure –prefix=/opt/glibc-2.25
$ make
 # make install
</pre>
### dropbox関係設定
#### dropboxを使うアカウントで
<pre>
$ patchelf --set-interpreter /opt/glibc-2.25/lib/ld-2.25.so  ~/.dropbox-dist/dropbox-lnx.x86_64-85.4.155/dropbox
$ patchelf --set-rpath /opt/glibc-2.25/lib ~/.dropbox-dist/dropbox-lnx.x86_64-85.4.155/dropbox
$ cd dropbox-lnx.x86_64-85.4.155
$ ln -s /lib64/libgcc_s.so.1
$ ln -s /usr/lib64/libstdc++.so.6
$ ln -s /lib64/libz.so.1
$ ln -s /lib64/libgthread-2.0.so.0
$ ln -s /lib64/libglib-2.0.so.0
$ ln -s /usr/lib64/libatomic.so.1 #←今回の追記
</pre>
最後に.bash_profile に
<pre>
export LD_LIBRARY_PATH=/home/shared/.dropbox-dist/dropbox-lnx.x86_64-85.4.155
</pre>
を追記してログアウト、再ログイン
<pre>
$ dropbox start
</pre>
で終わり。
## そもそも CentOS7 で粘るかどうか。
[ Android ] 戻るボタン無効化

Androidで端末の戻るボタンを無効にする方法について述べる。

##方法
とても簡単でActivityクラスの**onBackPressed()**をオーバライドし、処理を書かなければ完了である。

~~~java
    @Override
    public void onBackPressed() {
    }
~~~

##参考サイト
以下のサイトがとても参考になった。
https://minpro.net/onbackpressed-android
Notionでプロフィール画像を設定する


アルプ株式会社でエンジニアをしています、集約のエンティティ@pictinyです。
これは[Notion Advent Calendar 2019](https://qiita.com/advent-calendar/2019/notion) 3日目のエントリです。
2日目は[Notionでよく使うショートカット](https://qiita.com/pictiny/items/bb1b30739546ba762629)でした。

# ユーザアイコン

Notionでは共同編集時に他のユーザのカーソル位置にプロフィール画像が表示されます。
また、ページ中でユーザにメンションを飛ばす場合にもプロフィール画像とユーザ名が合わせて表示されます。

<img width="614" alt="ユーザアイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/d76838b3-63a8-87e4-d25e-63e597aaff9f.png">

プロフィール画像を未設定の場合はユーザ名のイニシャルが表示されるので、識別が難しくなってしまいます。

## 設定方法

[Update account information](https://www.notion.so/Update-account-information-87076204f7f5480db33c35e85c46968b)

サイドバーにある Settings&Members の MyAccount から設定できます。

<img width="452" alt="MyAccount" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/57d704e2-3373-2ca5-daee-c20de4af38e9.png">
Go言語　理解度チェックテスト１

Go言語入門者向けの簡単なチェックテストについて解説します。

まずはテスト１！

```golang

package main

func main() {s
	as := []struct{ N int }{{N: 10}, {N: 20}}
	for _, a := range as {
		a.N *= 10
	}
	println(as[0].N, as[1].N)
}
```

この表示結果はいくつになるでしょうか？

実行結果は以下になります。

```
$ go run main.go 
10 20
```
リーダブルコード大喜利

ITエンジニアは小説家、新聞記者、二宮金次郎に次いで読量の多い人種だと思っています。
技術書を読み、記事を読み、仕様の行間を読み、だれが書いかわからない難解なコードを読み…
とても疲れます。
疲れた時は、ちょっと休憩してリーダブルコードを読む事をお勧めします。
#なぜリーダブルコード？
「読むのに疲れたのにまた読むのかよ」というのはごもっともな意見ですが、

- それほど頭を使わない
- 為になる
- 挿絵で笑える

という理由でとても程良いのです。
あと個人的な意見ですが、エンジニアなら**暗記するほど読んだ方がいい**と思っています。
読みやすいコードは皆を幸せにしますので。
#まだ読んでない方へ
「リーダブルコード　より良いコードを書くためのシンプルで実践的なテクニック」は、読みやすいコードとは何かを徹底的に叩き込んでくれる本です。
言語には依存しません。
是非、読んでみてください。
#すでに読んだ方へ
「大昔に読んだのでほとんど覚えていない」と言う方は、時々思い返してみると良いと思います。

では、ちょっと思い返してみましょう。
テスト形式だと大袈裟なので、大喜利形式で思い返してみましょう。

これから、実際の出来事を元にお題を出します。
回答を考えて下さい。
その後、お題に関連するリーダブルコードの原則を思い返します。

それでは行きます。

##お題①
以下のようなコードがあります。

```javascript
const date = new Date(); // 今日の日付を取得
const kind = [4,5]; 
kind.forEach(function(value) {
    // date.getDay()の値が4のとき、金曜日。5のとき、土曜日。
    if(value === date.getDay()){  
        weekEnd();
    }
});
```
今日が金曜日か土曜日だったら`weekEnd();`をコールするという簡単な処理です。
新人のAさんは、これに日曜日も追加するように言われました。
どのように書き換えたでしょう？

それではお考えください！

…
……
………

回答です。

```javascript
const date = new Date();
const kind = [4,5]; // date.getDay()の値が4のとき、金曜日。5のとき、土曜日。 
const nichi = [6]; // date.getDay()の値が6のとき、日曜日。
kind.forEach(function(value) {
    if(value === date.getDay()){
        weekEnd();
    }
});
nichi.forEach …
```
やっちゃいましたね。
kindを種類と読まずkindo(金土)と誤読したわけです。
Aさんが悪いのではなく、読みにくいコードが引き起こした不幸な出来事です。
以下、これに関連した原則です。

 **名前に情報を詰め込む（２章）**
 **誤解されない名前を付ける（３章）**

気になったら読んでみましょう。
では次です。


##お題②
Bさんは以下のようなクラスを書きました。

```PHP
class Account{
function __construct(){
$this->name = "取引先";
}
function show() {
echo $this->name;
}
}
```
先輩から、コードを見やすくする為に
「コメントを書いたほうがいいよ」
「インデントを揃えたほうがいいよ」
と言われました。

その通りにしましたが、逆にわかりにくくなりました。
それはなぜでしょう。

それではお考えください！

…
……
………

回答です。

```PHP
// 2019/11/12 CHG START
//class Account{
    class Account{
// 2019/11/12 CHG END
// 2019/11/12 CHG START
//function __construct(){
//$this->name = "取引先";
//}
        function __construct(){
            $this->name = "取引先";
        }
// 2019/11/12 CHG END
// 2019/11/12 CHG START
//function show() {
//echo $this->name;
//}
         function show() {
             echo $this->name;
         }
// 2019/11/12 CHG END
// 2019/11/12 CHG START
//}
    }
// 2019/11/12 CHG END
```
あ、そう理解したんだ。

以下、これに関連した原則です。

**コメントすべき事を知る（５章）**
**コメントするべきでない事を知る（５章）**

「コメントのためのコメントをしない」はなぜか好きな言葉です。
#まとめ

記憶は感情と結びつくと定着しやすいらしいです。
覚えたいと思ったら、その対象に対して笑ったり怒ったり悩んだりすれば良いわけですね（適当）
他にも息抜きに使える程よい本があったら教えてください。
Vim初心者向けに矢印キーを無効にするプラグインを作ってみた

この記事は[TUT Advent Calendar 2019](https://adventar.org/calendars/4174)の記事です。

# はじめに
私の通っている大学でVimを使ってる人をたまに見るのですが、結構な頻度で矢印キー(カーソルキー)を使ってる人を見かけます。
そこで、そんな人たちがhjklキーでの移動に矯正できるように「disarrow.vim」というプラグインを作成しました。
https://github.com/Inazuma110/disarrow.vim

このプラグインを導入すると、矢印キーを押すと警告の表示がでます。
![](https://raw.githubusercontent.com/Inazuma110/disarrow.vim/master/screenshot/disp_warn.png)
ちなみにこのメッセージ文は[VIM Adventures](https://vim-adventures.com/)から引用しています。

# Requirements
Floating windowを使うので、Neovim 0.4.0以上が必要になります。
初心者向けと謳っていますが、単にaptでInstallしてもこのバージョンは入らないはずです。
https://github.com/neovim/neovim/wiki/Installing-Neovim を参照して新しめなバージョンをInstallしてください。

# Install
[dein](https://github.com/Shougo/dein.vim)を使ってtomlファイルで管理しているなら

```vim
[[plugins]]
repo = 'Inazuma110/disarrow.vim'
```

dein以外のプラグインマネージャーを使ったことがないので他のプラグインマネージャーでのInstall方法については割愛しますが、特別な操作はいらないはずです。

# Configuration
警告文を日本語にしたい場合は、vimrcにて

```vim
let g:disarrow#lang = 'ja'
```

とします。

# 最後に
Vimscript初心者なので、書き方の問題やバグなどありましたらこの記事のコメントやGitHubのIssueやPRなどで教えてください:bow:
DNSレコードについて学ぶ（AWS_ALIASレコード）

#概要
Route53の勉強しているときに、DNSレコードに不明点があったのでメモ

#各種レコード
###Aレコード
Aレコードはドメイン名と対応するIPアドレスを **ドメイン名:IPアドレス = 1:n**で定義する。
同じIPと別ドメイン名を並べて定義すれば IPアドレス:ドメイン名 = 1:n できる。

###CNAMEレコード
CNAMEレコードはすでにAレコードで定義されてるドメイン名と別名を定義する。なのでここは ドメイン名:参照ドメイン名 を書くことで IPアドレス:ドメイン名 = 1:n を定義することができる。

###ALIASレコード
AWSが考案したレコード
一見Aレコードのようだが、CNAMEを介してIP解決するのに比べ、
・無駄なDNSクエリの削減
・apex zoneに対応
している。

**イメージ**

| Type       |       IP |    Name    |
|:-----------------|:------------------|:------------------|
| A            |  1.2.3.4           | example.co.jp               |
| CNAME        |             |  example.co.jp = example2.co.jp            |
| A（ALIAS）        |             |  ALIAS example.co.jp            |


#その他
びっくりするくらいレコードの種類って多いんですね。。。[[wiki]](https://en.wikipedia.org/wiki/List_of_DNS_record_types)

参考にしたサイト
[Amazon Route 53のALIASレコード利用のススメ](https://dev.classmethod.jp/cloud/aws/amazon-route-53-alias-records/)
PHP基礎 Part5

# 概要
PHPの独学で学んだことをアウトプットしていく

# 前回の内容
[PHP基礎 Part4]
[PHP基礎 Part4]:https://qiita.com/k__aizawa/items/68dbdec2500cf94eaae4

## for文
繰り返しで処理を行いたい時に用いる文法
基本的な形は、以下の通り

```php:sample.php
<?php
  for ($i=1; $i <= 5; $i++){  // ()の中に変数を定義し、繰り返す条件と変数の更新を入れる
    echo $i;                  // 結果の出力
  }
// 結果:12345
?>

```

## while文
for文と同じような繰り返しで処理を行いたい時に使用する文法

```php:sample.php
<?php
  $i = 1           // 変数の定義
  while ($i <= 5){  // 繰り返す条件の設定 
    echo $i;       // 結果の出力
    $i++;          // 変数の更新
  }
// 結果:12345
?>

```

for文は終了タイミングや実行回数が決まっている時に使用し、
while文は終了タイミングが決まっていない時や設定した条件を満たす場合に使用するくらいの認識。

## break文
繰り返し処理の中断を命令する
for文、while文とif文を組み合わせて使用する

```php:sample.php
<?php
  for($i = 1; $i <= 10; $i++) // 変数の定義
    if ($i == 5){             // breakの条件設定
      break;                  // if文の条件を満たす場合、中断処理
    }
      echo $i;                // if文の条件を満たさない場合、結果の出力
  }
// 結果:1234
?>

```
## continue文
繰り返し処理のスキップを命令する
break文同様、for文、while文とif文を組み合わせて使用する

```php:sample.php
<?php
  for($i = 1; $i <= 10; $i++) // 変数の定義
    if ($i % 2 == 0){         // continueの条件設定
      continue;               // if文の条件を満たす場合、スキップ
    }
      echo $i;                // if文の条件を満たさない場合、結果の出力
  }
// 結果:13579
?>
```

## foreach文
配列や連想配列を用いた繰り返し処理を命令する
書き方は以下の通り

1.配列を用いた繰り返し処理

```php:sample.php
<?php
  $languages = array("日本語","英語","フランス語");
  foreach ($languages as $value){
    echo $languages;

// 結果:日本語英語フランス語
?>
```
2.連想配列を用いた繰り返し処理

```php:sample.php
<?php
  $scores = array(
       "国語" => 68,
       "数学" => 83,
       "英語" => 92
  );

  foreach ($scores as $key => $value){
    echo $key.":".$value;

// 結果:国語:68数学:83英語:９２
?>
```

## 次回
* 関数
VBAと共に去りぬ：自動化の前にやること

1. フォルダの構造を決める
(言語の開発、通常業務、ローカルorクラウド色々あるだろうが所定の位置を決める)
2. 勉強する(特に最初は関数,framework,packages,その他ツールでなにができるか)
利用:車輪の再発明を防ぐため
VBA初期にありがちなのは関数で用意されている処理を自分で作ってしまうこと

3. コードをガリガリ書かなくても済むか?を確認する。
(コードが書くのが楽しくなるとそれが目的化してしまう。それを防ぐ。
例えば、目的が「雨に濡れないこと」なら、傘を持っていくかの判断をするために気象予報の情報を取ってきて判断するプログラムを書くくらいなら、超軽量の折りたたみ傘をかばんに入れておけばいいのではないか?という考察。
ある処理を自動化する前に、その処理をしなくて済む方法を"コードを書く"以外でできないか?考える。)
JavaScript 関数定義

#関数（メソッド）の定義

```js
function 関数名（）{
 //行う処理
}
```

変数有り版

```js
function 関数名(引数A){
 console.log(引数A);
}

let sample = "事件ですよ"

関数名（sample）;
```

定義した変数と呼び出す際に使う引数は同名
引数として渡された引数Aと行う処理に渡す引数は同名




#無名関数

```js
let sample = function(){
    console.log('元気ですか？');
}

sample();　　//元気ですか？が出力
```

function()で関数名が無いので無名関数となっております。
他の値を代入し易く、使い勝手が良いです
jQueryのready関数とload関数の実行順に気をつける

あるHPでjQueryを使ってアニメーションを動かしていた。正確に言うと、アニメーションのトリガーとして、特定のタグに属性を追加するというような処理をしていた。  

が、どうもChromeやSafariではちゃんと動くのに、Firefoxでは動いたり動かなかったりするという症状が出ていた。  

調べてみるとjQueryの書き方とバージョンの問題のようだった。  
症状が出ていた処理は、以下のように`$(function(){})`（ready関数）の中に、`$(window).on()`（load関数）が書かれていた。

``` javascript
$(function(){
  // DOMツリー構築完了後の処理
  $(window).on('load', function(){
    // 画像・動画などの関連データが読み込まれた後の処理
  });
});
```

確かに処理の順番を理解していれば、この書き方がおかしいことに気づく。

>readyは画像などが表示されるより前に実行され、loadは画像などが表示された後に実行されます。  
  
  
jQuery2.0だと、上の書き方でも正常に動いてくれたが、jQuery3.0以降は、`$(window).on()`の処理は`$(function(){})`の外に書かなければいけないとのこと。

``` javascript
$(function(){
  // DOMツリー構築完了後の処理
});

$(window).on('load', function(){
  // 画像・動画などの関連データが読み込まれた後の処理
});
```

## 参考  
* [$(window).on (‘load’)関数が動作しない時はjQueryのバージョンをチェック！](https://wemo.tech/109)
* [$(function(){}) と $(window).on('load',function(){}) の違い](https://qiita.com/mimoe/items/74cb3a01a30162759fdd)
* [【翻訳まとめ】jQuery 3.0 アップグレードガイド](https://qiita.com/fmy/items/345a264a1cf2e2a73f62)
GCEを削除しても静的IPが削除されてなくて課金され続けてた

GCEの最小インスタンスは無料で使用することができますが、独自ドメインを使用するには静的IPの割当が必要となり、
静的IPの割当は課金が発生します。

使用している間は課金されるとわかってて使用していたのでいいのですが、使用をやめたときにGCEインスタンスの削除はして静的IPの削除がされていなくて課金され続けていたので今後同じことをする人がいないように書いておきます。
請求書を見て発覚しました
ちなみに課金額は一ヶ月で800円ほどでした


解除方法
コンソール画面からは解除できず、GoogleCloudShellから削除することができました
（他に方法あるのかな？インスタンス削除前ならできるとか）
- Cloud Shellを起動
- 静的IPのリスト確認
```
gcloud compute addresses list
```
- 削除コマンド実行
```
// NAME, REGIONには確認した名前とリージョンを入れる
gcloud compute addresses delete NAME --region=REGION
```
- 削除されたことを確認
```
gcloud compute addresses list
```
Nodebrew 本体が削除できなかった話

[Nodebrew本体を削除する方法](https://qiita.com/tonkotsuboy_com/items/f5d17f0b9698554a7716) に従い、Finder から削除したのに

```bash:terminal
$ nodebrew -v
```

でバージョンが表示され続け、消せていないようだった。

## 解決法
Homebrew で入れた nodebrew が残っているのが原因だったよう。

以下のコマンドを実行すると、 `nodebrew -v` でもバージョンが表示されなくなり、nodebrew の削除が完了した。

```bash:terminal
$ brew uninstall nodebrew
```

### 参考にした記事
[brew uninstall nodebrew](https://medium.com/@nagofox/brew-uninstall-nodebrew-8b10254c747f)
タスクと日付入力だけで自動でガントチャートをつくる【Google Spread Sheet】

備忘録

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25036/092d4956-4c14-5527-fc6a-9ec446aba925.png)


横軸に日付を入力。「日付」の入力形式であること。
終了日と開始日を入れるとカレンダーに自動で色がつくように。

カレンダーを全選択して、条件付き書式のカスタム数式を選択する。
`=AND(NOT(ISBLANK($B4)),$C4<=F$2,$D4>=F$2)`
B列(タスク一覧)が空欄でない場合、C列(開始日)がF$2以前で、D列(終了日)がF$2以降の場合、TRUEを返す。
Next.jsをつかってSPAをSSRしてみた感想

こちらは [Next.js Advent Calendar 2019](https://qiita.com/advent-calendar/2019/next-js) ３日目の記事です。

---

ReactのSPAをNext.jsでSSRしてみて気づいたことをまとめてみました。

まだNext.jsやNuxt.jsでSSRやったことない人や、これからやろうか検討している人への情報共有的位置づけです。

## 目次

- SPAをSSRするとは？
- どのような構成になったか？
- どのような実装をおこなったか？
- SPAをSSRしてどうなったか？
- 気づいたこと
- まとめ

## SPAをSSRするとは？

SPAの弱点である初回アクセス時の読み込み時間を短縮するために、サーバサイドでレンダリングを行いブラウザ上に素早く画面を表示させる手法。
初回表示後の画面遷移やアクションは通常のSPAと同じように機能する。

クライアントにおける初回表示のフローは、通常のSPAとSSRした場合とで以下のようになる。

**通常のSPA**

1. サーバからバンドルされたJSファイルを取得
2. Reactコンポーネントの初期化
3. ローディング表示
4. APIリクエスト&レスポンス
5. 表示

**SSRした場合**

1. サーバからデータが挿入されたDOMとバンドルされたJSファイルを取得
2. 表示 (裏側で初期化がはしる)

通常のSPAではバンドルファイル取得後に順を追って初期化していくが、SSRすると取得したものをそのまま表示できるので、SPAなのにパッと画面が表示される。

## どのような構成になったか？

通常のSPAではバンドルJSファイルをS3やFirebaseHostingなんかに置いてサーバレス構成にもできたが、SSRを行う場合はNode.jsのWebサーバをたてることになる。自分の場合は以下のような感じ。

- Next.jsで実装したアプリをExpressと組み合わせてWebサーバを構築
- GAEとかGKEのコンテナ上でサーバを立ち上げる
- サーバのルーティングもクライアントのルーティングもNext.jsが内部でやってくれる

## どのような実装を行ったか？

基本的にNext.jsの作法に乗っかっていく感じ。公式リポジトリのexamplesがかなり充実しているので、主なケースは参考にしつつ実装できる。

ReactアプリをSSRする場合は具体的に以下のような改修を行っていく。

- componentDidMountやuseEffect(マウント時)で宣言していた処理をgetInitialPropsという関数で宣言する
- クライアントとサーバで違う処理を行う必要があるときはpropsのisServerを参照して処理を分ける
- Next.jsのルーティングシステムに合わせた構造にする(pagesディレクトリ配下にコンポーネント整備)
- サーバサイドからのAPIリクエストに使用する認証token(Cookie)をreqから取得する
- サーバにはwindowやdocumentがないので、ライブラリの初期化等で必要な場合は動的インポートを使用してSSRをエスケープする
- などなど……

## SPAをSSRしてどうなったか？

初回表示がかなり速くなり、思わず「おおおぉ〜」と声がでた。

- ロード完了まで5秒ほどかかっていた画面が、1秒かからなくなった
- APIアクセスもサーバ同士なのでなんか速そう
- Next.jsのコード分割 & 動的インポートの機能をさらに活用していけばもっと速くなりそう
  

## 気づいたこと

通常のSPAでは(サーバレス構成にすれば特に)Webサーバについて気にする必要がなかったので、フロントエンドパワーがあればそれだけで完結する話が多かったように思う。

SSR構成にすればサーバ内の処理やリソースについても思いを巡らせる必要があるので、難易度も必要な工数も増すが、ある程度SPA開発に慣れていてサーバサイドに対しても明るいエンジニアであれば楽しんでいける領域だと思う。

Next.jsはSSRだけでなく静的ジェネレートやAMP、PWAについてもサポートしているので、Webアプリの理想郷を追求していける面白いフレームワークだと思う。


## まとめ

- SSRはやっぱり速かった
- フレームワークの恩恵により、実装は意外と簡単だった
- サーバサイドをいかに攻略していけるかがポイント
- 技術力さえあれば最高のWebアプリケーションが作れると思う！

以上です。ここまで読んでいただき、ありがとうございました。

---

2019年のアドベントカレンダーは３つ参加してます。よかったら他の記事も見てください。

- [Next.js Advent Calendar 2019](https://qiita.com/advent-calendar/2019/next-js) 3日目 …… Next.jsをつかってSPAをSSRしてみた感想(この記事)
- [React Advent Calendar 2019](https://qiita.com/advent-calendar/2019/react) 7日目 …… [Reactの歴史](https://qiita.com/mqtsuo02/items/4bace06c85f5f1872db6)
- [Go4 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/go4) 12日目 …… [Goでライフゲームを実装してみた](https://qiita.com/mqtsuo02/items/9a08c33354d1b299aea9)

P.S. @tkdnさん: カレンダーへご招待いただきありがとうございました。
AdventCalender 12/2 サーバーを使わないデータツールの用途検証


お久しぶりです、サクリバーです。


今回は、12/2のadvent calenderになります

### 今回の内容

今回はプログラムと違って、システム設計的なのを考える機会があったので、取り組んでいた部分の一部内容になります。

### お題内容

https://lifepepper.co.jp/china/firewall/
https://www.komazawa-u.ac.jp/~kazov/2020/present/3-miku-jouhoukakusa.pdf

ツイッターの時事問題で、グレートファイアーウォールのような
IPあどれすなどで通信制限やネットワーク構築をしないような地域で
新しいものを入れてみたいなーという妄想とお話から

#### システム概要

ゲームセンターや空き地やイベント会場に配置するVRや機器系のシステム。
クラッシュしたときとか故障した時だけやり取りがある。

#### 前提条件
1.サーバーは持たない
2.インターネットにつながっていない or 低回線

#### この記事で対応部分

1.クラッシュした時間帯の記録がEXCELで見れるようにCSVでファイルに出力

#### 実装内容

対応した時のツール
Talend(無料内容）...プログラミングは特殊な時にJavaで数行のみ

今回は、端末から出力されたログファイルから、クラッシュレポートと
ゲームセンターで遊んだ時のハイスコア情報を出力するイメージ図になります!(^^)!

<img width="960" alt="クラッシュ機能_フロー.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45396/dc8040ae-024b-8c59-df2f-f23272156215.png">


ファイルの振り分けも、ノードで行って「行名.項目名」で設定するようになっています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45396/589edb70-e16b-1598-50bb-7f736c7d3c99.png)

後は、実行ボタンをクリックするとデータの変換処理が実際に行われます


ビルドボタンは、夕方以降対応（別件が入ったため)

### ビルドしました

以下の結果が緑色で表示されます。

・ログファイルでの実行時間と件数
・クラッシュファイルレポート: 2件
・ハイスコア更新日時レポート：37件

![Talend_12_02_report_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45396/35867ef3-e9cf-1a4c-5485-f1d9583f9deb.png)

クラッシュファイルレポートのファイルを開いてみると、2件の日時だけが表示されているのを確認できました。

![game_center_crash_report.csv - Excel 2020_12_08 22_18_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45396/538284b6-a9d0-3f91-594f-e4c8cffe85ea.png)

今回用意したデータは以下のようなファイルになります
![Talend_12_02_report_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45396/c4303d43-52cc-dce5-f894-1ab74f0ee555.png)


作ったテストデータは以下になるので、データを考えるの面倒だなーというひとは使ってもらえたら幸いです。
https://1drv.ms/u/s!AsyQbkaMcG0jiAp5UZgdaC8YiNNF?e=mOri5A

実行動画を見てみたい人は。以下のURLを見てみてください

https://youtu.be/Eg93snho4VM
USB起動 Ubuntu ディープラーニング

###以前の記事
[Ubuntuディープラーニング環境構築（インストール準備)](https://qiita.com/aiiika/items/4ae527e915015b334fd9)
[Ubuntuディープラーニング環境構築（インストール編)](https://qiita.com/aiiika/items/cd4d35e89652b49fbffc)
[Ubuntuディープラーニング環境構築（マルチブート)](https://qiita.com/aiiika/items/7f623840b31767ff9f48)
###バックアップツールとしてのPinguybuilder
カスタマイズしたUSB起動Linuxを作成するのに、以前はremastersysを使っていました。
元々、バックアックシステムなのですが、カスタマイズされたOSのUSBから起動できます。

| Ubuntuバ－ジョン | バックアップシステム| 
|:-----------------|------------------:|
| 12.04            |ubuntu-default-builder |
| 14.04            |remastersys | 
| 16.04            |Pinguybuilder| 
| 18.04            |Pinguybuilder|

[Pingubuilderのダウンロード](https://sourceforge.net/projects/pinguy-os/files/ISO_Builder/)

~~2019/12/03執筆時現在最新はpinguybuilder-menu-based_5.2-1_all.debでした。~~
pinguybuilder_5.1_8_all.debを使用します。
これをダウンロード・インストールします。

```terminal
sudo apt install gdebi
sudo gdebi /somewhere/pinguybuilder_5.1_8_all.deb
```
Pinguybuilderを起動して、settingタブを押します。
一番上のusernameは、起動した時のusernameなので、最低ここだけはカズタマイズしたOSのusernameと合わせておきます。
CD LabelやFilenameは好みで設定して構わないでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496711/6af99684-e2f0-6500-144e-6953884652b9.png)
あとはActionタブのDistボタンを押すだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496711/42d94c43-9911-1ff4-2ece-64355affd906.png)
作成するのに、たいへん時間がかかります。
/home/Pinguybulder/Pinguybuilder/custom-$1.isoが出来ていますが、以下の注意が必要です。

- /home/以下はバックアップされませんので、/etc/skel/内に必要なファイルは入れておきます（例えば、.mozzila等）。
- isoファイルの大きさは4GB以内(FAT16の制限）
- 何度も作り直すと、出来上がるisoファイルの大きさは大きくなります（原因不明。なるべく一度で全作業を終了させます。

###ディープラーニング用環境作成
ここは
[Ubuntuディープラーニング環境構築（マルチブート)](https://qiita.com/aiiika/items/7f623840b31767ff9f48)
と重なる部分ですが、今回作成した環境をもう一度書いてみます。

```terminal
sudo update
sudo upgrade
sudo apt install fcitx-mozc
```
言語設定を変更(fcitx)、指示に従い言語不足ライブラリーをインストール

```terminal
sudo timedatectl set-local-rtc true
sudo install gbebi
sudo gdebi pipguibulder................deb
sudo apt install python3-pip
sudo pip3 install --upgrade pip
pip install jupyter
pip install matplotlib
pip install pandas
pip install sklearn
pip install pillow
pip install tensorflow==1.14
pip install keras
pip install --user chainer
pip install torch
pip install torchvision
```

それ以外にjuliaをインストールするまでは4GBの収まりました。
但し、ubuntuは最小インストールとして、LibreOfficeはインストールしていません。

###UEFI仕様のマシンで起動しない場合・他（別記事の予定）
- UEFI対応
- desktopフレーバーの変更
- 記録が取れるようにする(casper-rw)