OmniAICreator/Qiita-1.07M huggingface dataset:
JsでHTML文の表記を変える

#WHY
javascriptの練習がてらinnerHTMLで遊んでいた内容をアウトプットさせていただきます。
基本的なinnerHTMLの動きは理解できるとおもいます。
※今回はJQueryは使用しません

##jsファイルを反映させましょう。
html文の<b>bodyの最後</b>に記述します。

```html
<script type="text/javascript" src="test.js"></script>
```

##html文の記述を変えよう
https://qiita.com/totacho/items/e019473ad1fea29593b2
で作成したhtmlファイルを少し改造します。

```html
<!-- 省略 -->
<h2 class="heading-name">メールで予約</h2>

<div class="price">
 　<div>TAX</div>
 　<div class=price-margin id="tax-price"></div>
 　<div>円</div>
</div>
<div class="price">
　 <div>利益</div>
 　<div class=price-margin id="before-price"></div>
 　<div>円</div>
</div>
<!-- 省略 -->
```

ブラウザを見てみましょう
<img width="500px" alt="taxprice.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/a2cfaf95-62c6-99de-337e-1f9c3254df30.png">
フォーム部分がこのようになってます。

priceのとこに額を打ち込むと

- TAXのとこにprice額の10%の額
- 利益のとこに打ち込んだprice額からTAXの額を引いた額

を表示させていきます。

##Javascriptに記述しよう
まずこのように書いてみましょう。

```javascript
function taxCalc (){
  const formPrice  = document.getElementById("input-price");
  formPrice.addEventListener("keyup", () => {

    const price = formPrice.value
    const tax = price*0.1
    const beforePrice = price - tax
    console.log(tax)
    console.log(beforePrice)
  });
}

```

taxCalc関数を定義して、htmlからId("input-price")の<b>要素</b>を取得しています。
そしてその要素に文字が打ち込まれるたびにイベント発火をさせる記述をかいています。

```javascript
function taxCalc (){
  const formPrice  = document.getElementById("input-price");
  formPrice.addEventListener("keyup", () => {
```

続いて「.value」でフォームの<b>値</b>を取得、代入し、
それぞれTAXと利益の値を計算していき、コンソールで確認してみます。
<img width="500px" alt="taxprice2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/65d42b7b-3fc1-9c80-5f64-2b3b70fa5f38.png">

コンソールに10%の額と利益額が順番に表示されました！
つづいてこれをHTML文へそのまま記述するようにします。

##innerHTML
html要素の中身を変化させることができます
console.logを削除し、以下のように記述しましょう

```javascript
const taxPrice = document.getElementById('tax-price');
const profitPrice = document.getElementById("before-price");
taxPrice.innerHTML = tax;
profitPrice.innerHTML = beforePrice;
```
変化させたい要素を取得し、変数に代入します。
その変数に<b>innerHTML</b>を使いそれぞれ表示したい値の入った変数を指定すると、、

<img width="500px" alt="taxprice3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/a3d2d601-e4f0-6214-a08d-47dd689616ec.png">

ブラウザで確認がとれました！
きちんと表示されました！

-----
このようなアニメーションを作れるのがJsの醍醐味ですし、便利さなど追求していくならこのような機能は必須だと思います!!
引き続きたまにはこう言う風に遊びながら学習続けていこうと思います！
PC-9801でCD-ROM

PC-9801FA2にSound Blaster 16(CT3720)が入っていてCD-ROMドライブ(CDG-MX2)があり使えるようにしてみました。接続ケーブルは37ピンで内部でIDEの40ピンに変換されています。

ドライバはCreative MediaサイトにSBCD98.EXEとしてありました。

もちろんPC-9801からインターネットへのアクセスはできませんので、ファイルは一旦Windows 7でダウンロードします。

Windows 7でダウンロードしたファイルをRLoginの「SFTPファイルの転送」機能でFreeBSDのホストにコピーして[XMODEM](https://qiita.com/yamori813/items/7609bea3ad4a59f1493e#cct98%E7%B7%A8)でPC-9801のフロッピーに転送しました。

フロッピーが内蔵のPCはもうありません。USBタイプのフロッピードライブはいくつかあるのですが、今は手元にはありません。

フロッピーは「SB16 CDROM」というボリュームラベルにしておく必要があります。SB16とCDROMの間にスペースが必要なので注意が必要です。

SBCD98.EXEは自己解凍ファイルなので実行して解凍しておきます。

```
A>DIR B:

 ドライブ B: のディスクのボリュームラベルは SB16 CDROM 
 ディレクトリは B:\

LOCKCD   EXE     8460  93-10-23    1:00
DISK     ID        77  94-03-01    1:20
INSTALL  EXE    59548  94-03-08    1:20
CTCCW    DLL    53488  94-01-26    3:10
MSCDEX   EXE    25361  93-09-30    6:20
QCD      BAT       32  93-10-23    1:00
QCD      EXE    69040  93-10-23    1:00
README   COM     2637  93-10-23    1:00
README   TXT     2575  97-02-21   11:04
SBCD     SYS    14048  94-02-25    4:17
SETUPCD  EXE    38914  93-10-23    1:00
TESTCD   EXE    33404  93-10-23    1:00
UNLOCKCD EXE     8460  93-10-23    1:00
       13 個のファイルがあります.
   925696 バイトが使用可能です.

```

C-BUSのボードのディップスイッチ（赤）のデフォルトは1,2,3だけがONで20D2hになります。

インストールサイズは350Kくらいで、フロッピーにもインストールできます。
Bドライブにシステム(MS-DOS 5.0)入りのディスクを用意して

```
A>INSTALL B:
```

を実行するとBドライブのディスクにファイルがコピーされてドライバーが組み込まれます。


```
A>DIR B:

 ドライブ B: のディスクのボリュームラベルはありません.
 ディレクトリは B:\

COMMAND  COM    48416  91-11-18    0:00
SB16         <DIR>     21-02-17   10:30
AUTOEXEC BAT       40  21-02-17   11:24
CONFIG   SYS       47  21-02-17   11:27
        4 個のファイルがあります.
   826368 バイトが使用可能です.
```

このディスクで起動するとDドライブでCD-ROM(ISO9660)が読めます。

インストーラーが設定する内容は以下のようになります。

```:CONFIG.SYS
DEVICE=A:\SB16\DRV\SBCD.SYS /D:MSCD001 /P:D2
```

```:AUTOEXEC.BAT
A:\SB16\DRV\MSCDEX /V /D:MSCD001 /M:15
```

CD-RWは読めませんでした。CD-Rもときどき読めない事があります。古いものなので仕方ありませんね。
ディスク容量が足りなくなった時

Dockerを使って開発したりアプリ開発したりしているとギガがすぐに無くなるので自分用のメモ

## 調査&削除方法

### GUIから調査&削除

メニューバーの一番左のAppleのログを押して、
「このMacについて」>「ストレージ」>「管理...」と遷移して、
容量の大きいデータを調査し、適宜削除を実行する

### Terminalから調査&削除

ディレクトリの各階層に移動して1GB以上容量を食っているディレクトリを列挙

```bash
du -sh ./* | grep -E '[0-9]+\.?[0-9]+G'
```

だいたいいつも `~/Library` 以下に容量を食っているディレクトリがある(気がする)

### よくやるやつ

不要なDockerのデータを削除

```bash
docker system prune
```

実行すると、以下のように削除される対象が表示されるので、問題がなければ「y」を押して削除実行

```
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all dangling images
  - all dangling build cache
  
Are you sure you want to continue? [y/N]
```

不要なiOSのSDKを削除

```bash
cd ~/Library/Developer/Xcode/iOS DeviceSupport
# ex. 13.1.1を削除
# rm -rf ./13.3.1\ \(17D50\)
```

不要なiOSのビルドイメージを削除

```bash
cd ~/Library/Developer/Xcode/DerivedData
# ex. すべて削除
# rm -rf ./*
```

不要なiOSのシミュレータを削除

```bash
# 事前に確認
xcrun simctl list
# unavailableなものを削除
xcrun simctl delete unavailable
```

不要なiOSシミュレーターのキッシュを削除

```bash
cd ~/Library/Developer/CoreSimulator/Caches
# ex. すべて削除
# rm -rf ./*
```

不要なAndroidのsdk imageを削除

```bash
cd ~/Library/Android/sdk
# ex. android-26を削除
# rm -rf ./system-images/android-26
```

## まとめ

開発機は256GB無理！！
512GB以上にしよう
【GCP】BeyondCorp enterpriseの売り分けを考える

<table>
	<tr>
		<th>ユースケース</th>
		<th></th>
		<th></th>
		<th>下記表のどの契約パターンが適しているか(Noを記載)</th>
		<th>コスト</th>
		<th>導入までの流れ</th>
	</tr>
	<tr>
		<th>特定の役員や部署だけBeyondCorp (remote access?)を使いたい</th>
		<td>GCP内のアプリにアクセス</td>
		<td>IPのみで認証/認可(無料部分)する</td>
		<td>GCP利用中であれば、2、3、4（BCEなくてもOK）</td>
		<td>Beyondcorp enterprise利用料</td>
		<td>・GCP with KDDIを申し込む・WSent+GCP with KDDIを申し込む</td>
	</tr>
	<tr>
		<th></th>
		<td></td>
		<td>デバイスの情報など(有料部分)も認証/認可でつかう</td>
		<td>GCP利用中であれば、1、3、4、5、6</td>
		<td>Beyondcorp enterprise利用料</td>
		<td>・BCentのフォームに登録→英語でのやり取り→契約</td>
	</tr>
	<tr>
		<th></th>
		<td>Goolge Cloud のSaas（GoogleWorkspaceのアプリとか）にアクセス</td>
		<td></td>
		<td></td>
		<td>Beyondcorp enterprise利用料 + GKE</td>
		<td>・BCentのフォームに登録→英語でのやり取り→契約</td>
	</tr>
	<tr>
		<th></th>
		<td>他社Saasにアクセス</td>
		<td></td>
		<td>1</td>
		<td>Beyondcorp enterprise利用料 + GKE</td>
		<td>・BCentのフォームに登録→英語でのやり取り→契約</td>
	</tr>
	<tr>
		<th></th>
		<td>オンプレミスのウェブアプリに導入</td>
		<td></td>
		<td>1</td>
		<td></td>
		<td>・BCentのフォームに登録→英語でのやり取り→契約</td>
	</tr>
</table>

↓いかについては、基本的に考え方は同じだと思うが、何か懸念点はあるか？
<table>
	<tr>
		<th>全社的にBeyondCorp (remote access?)を導入したい</th>
		<th>GCP内のアプリにアクセス</th>
		<th>IPのみで認証/認可(無料部分)する</th>
	</tr>
	<tr>
		<th></th>
		<td></td>
		<td>デバイスの情報など(有料部分)も認証/認可でつかう</td>
	</tr>
	<tr>
		<th></th>
		<td>Goolge Cloud のSaas（GoogleWorkspaceのアプリとか）にアクセス</td>
		<td></td>
	</tr>
	<tr>
		<th></th>
		<td>Saasにアクセス</td>
		<td></td>
	</tr>
</table>

小規模ではないので、アカウント数や接続先の情報など詳細な情報が必要になりそう。

【契約パターン】
<table>
	<tr>
		<th></th>
		<th></th>
		<th>以下サイトのベース機能https://cloud.google.com/beyondcorp-enterprise/pricing</th>
		<th></th>
		<th>以下サイトの有料機能https://cloud.google.com/beyondcorp-enterprise/pricing</th>
	</tr>
	<tr>
		<th></th>
		<td></td>
		<td></td>
		<td>Context Aware Accessの使用</td>
		<td></td>
	</tr>
	<tr>
		<th>No</th>
		<td>契約パターン</td>
		<td></td>
		<td></td>
		<td></td>
	</tr>
	<tr>
		<th>1</th>
		<td>Beyondcorp enterpriseのみ</td>
		<td>●</td>
		<td>×</td>
		<td>●</td>
	</tr>
	<tr>
		<th>2</th>
		<td>GCPのみ</td>
		<td>●</td>
		<td>×</td>
		<td>×</td>
	</tr>
	<tr>
		<th>3</th>
		<td>Google workspace enterpriseのみ</td>
		<td>●</td>
		<td>●</td>
		<td>×</td>
	</tr>
	<tr>
		<th>4</th>
		<td>Cloud Identity premiumのみ</td>
		<td>●</td>
		<td>●</td>
		<td>×</td>
	</tr>
	<tr>
		<th>5</th>
		<td>GCP + Google workspace enterprise</td>
		<td>●</td>
		<td>●</td>
		<td>×</td>
	</tr>
	<tr>
		<th>6</th>
		<td>GCP + Google workspace enterprise + Beyondcorp enterprise</td>
		<td>●</td>
		<td>●</td>
		<td>●</td>
	</tr>
</table>



※GCP + Google workspaceでIAP connetctor実装しても、オンプレミスへの接続はできないと思われる。フォームから問い合わせるように、GCPサポートから言われた。
Flutter on the Web でモバイルの時だけいろいろ消える

# あらすじ

Flutter on the Web でアプリケーションを作成して、Serverにアップロードしました。
モバイルとデスクトップで挙動が違いましたが、ビルド設定を変えたら対応できました。

# 詳細

PC版Chromeでは正常に見れましたが、モバイルでいくつかのWidgetが消えてました。
モバイル版でも、「PC版サイトを見る」ボタンまたはチェックボックスを使うと、ちゃんと動きました。
具体的に消えていたのは、Appbar の Bottom に入れた Tab のタイトルや、Appbar title のSVG画像などです。

# コマンド

`flutter` の `build` コマンドで、`canvaskit` を指定すると正常に表示されることが分かりました。

```bash
flutter build web --web-renderer canvaskit --release
```

`canvaskit` の代わりに `html` や `auto` を指定すると表示されなくなりました。
vscodeでのビルドタスクを見ると、
下記のようにデフォルトでは `auto`になっています。

```json-doc:.vscode/tasks.json
{
	"tasks": [
		{
			"type": "flutter",
			"command": "flutter",
			"args": [
				"build",
				"web",
				"--web-renderer=auto"
			],
			"group": {
				"kind": "build",
				"isDefault": true
			},
			"problemMatcher": [],
			"label": "flutter: flutter build web"
		}
	]
}
```

# これでいいと思う

- `auto` を `canvaskit` に変える
- `args` に `--release` を足す
- `"group": {"kind": "build","isDefault": true},`で、ショートカットキーが使える
  - Win : `Ctrl`+`Shift`+`B`
  - Mac : `Shift`+`⌘`+`B`

```json-doc:.vscode/tasks.json
{
	"tasks": [
		{
			"type": "flutter",
			"command": "flutter",
			"args": [
				"build",
				"web",
				"--web-renderer=canvaskit",
				"--release"
			],
			"group": {
				"kind": "build",
				"isDefault": true
			},
			"problemMatcher": [],
			"label": "flutter: flutter build web"
		}
	]
}
```

# 参考

[Webレンダラー | Flutter](https://flutter.dev/docs/development/tools/web-renderers)

# まとめ

- まだbetaだけど、今のところsvgでしかバグに遭遇してない
- SVGがちょっとめんどい（別記事を書こうかな）
- 副産物というかcanvaskitにするとちょっと速い
- そして`--release`にするとちょっと速い
- flutter 最高
- flutterで~~サボろう~~クロスプラットフォームしよう！

**Excelsior!**
setIntervalで実行する関数内にintervalIdを渡してclearIntervalしたい

setIntervalは戻り値にintervalIdを返し、これをclearIntervalに渡すことで繰り返し処理を停止する事ができる。

intervalIdをグローバルな変数として定義しておくことで可能。

```javascript

javascript:
  let intervalId = 0
  let ii = 0
  const getRequestedSharing = () => {
    console.log('getRequestedSharing', intervalId, ii++)
    if (ii > 5) {
      clearInterval(intervalId)
    }

  }
  document.addEventListener('turbolinks:load', () => {
    intervalId = window.setInterval(getRequestedSharing, 3000)  //3000ミリ秒ごとに実行
  })
```

#### 参考
− [JavaScript \- clearIntervalを実行したときの挙動｜teratail](https://teratail.com/questions/95780)
- [WindowOrWorkerGlobalScope\.setInterval\(\) \- Web API \| MDN](https://developer.mozilla.org/ja/docs/Web/API/WindowOrWorkerGlobalScope/setInterval)
ELBのアクセスログをログアカウントのS3に集約する

documentのメモ

[Application Load Balancer のアクセスログ](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-logging-bucket-permissions)

Redshiftとかと同様ELBを保持しているAWSの特定のアカウントからのアクセスをバケットポリシで許可するひつようがあるので注意。
PowerShell でも "sudo vim" がしたい！

管理者権限でファイルをいじりたいときって結構あるけど、Windows だとめんどくさくね？

と思ったのが事の発端。なんか調べたら簡単にできたし、快適になったので紹介します。

## TL;DR

環境構築には下記コマンドを実行します。

```
# scoopのインストール
> Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')

# vimのインストール
> scoop install vim

# gsudoのインストール
> scoop install gsudo
```

実行方法は下記のとおり。

```
> gsudo vim
```

## インストールしたツールの紹介

### scoop

scoop は Windows のパッケージ管理ツール。Linux で言う apt、yum。

同じようなツールに chocolatey があるけど、操作が楽なので自分はこっち派です。

### vim

言わずと知れたエディタ。有名すぎて紹介することがない。

### gsudo

管理者権限でコマンドを実行するコマンド。UNIX のコマンドでいう `sudo` と `su` を混ぜた感じ。
ちなみにパスワード入力は必要無くて、 `このアプリがデバイスに変更を加えることを許可しますか？` といつもの警告が出るだけです。
使い方は下記。

```
gsudo   # sudo su と同等
gsudo {{ コマンド }}   # sudo {{ コマンド }} と同等
```

## 最後に

「中二病でも恋がしたい！」はいいぞ！
Amazon SNSでiOSプッシュ証明書の更新

## SNSでは一年ごとに証明書の更新が必要
iOSでは認証keyが導入されたため、本来であれば毎年証明書を更新するという作業は発生しないのですが、AWSのSNSは認証keyに対応していないため、従来どおり証明書を更新してアップロードするという作業が必要となってきます（ここの認識間違っていたら教えてほしいです…）。
一年に一回なので忘れがちになるので以下手順をメモしておきます。

## キーチェーンから証明書ファイルの作成
keycahin Access.appを起動する。
上部メニューの
キーチェーンアクセス→証明書アシスタント→認証局に証明書を要求
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290902/6d006af0-7d4f-bcd8-818c-ab46361c9c93.png)
メールアドレスの入力
通称はそのまま
要求の処理を「ディスクに保存」「鍵ペア情報を指定」
あとは続けて、`.certSigningRequest`ファイルをダウンロード

## Apple Developer Programから.cerファイルの作成
Apple Developer Programから「Certificates, Identifiers & Profiles」を選択
左メニューのCertificatesをクリック、プラスボタンから証明書を追加する。
↓「Apple Push Notification service SSL (Sandbox & Production)」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290902/83a8d33f-479c-6095-d621-ec92440f6805.png)

あとは対象のapp IDを選択してaps.cerファイルをダウンロードする

## .p12ファイルの作成
aps.cerをファインダーからダブルクリックしてキーチェーンアクセスに登録。
キーチェーンアクセスの左メニューから証明書を選択して証明書一覧から先ほど作成したと思われる証明書を選択する（Apple Push Services: {app_id}形式）。
右クリックから「〜を書き出す」をクリック
.p12形式を選択（このとき左メニューで証明書を選択していないとp12形式が選択不可になっているかも）して.p12ファイルを作成

## Amazon SNSの設定
あとは現在のAmazonSNSからモバイルプッシュ通知を選択して該当のプラットフォームアプリケーションを選択し編集する
p12ファイルをアップロードして、パスワードを入力していた場合は入力して変更を保存して完了
よく使うNavigationBar関連メモ


```Swift

//タイトル
self.navigationItem.title = "タイトル"
//タイトルの色
self.navigationController?.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.blue]
//戻るボタンを隠す
self.navigationItem.setHidesBackButton(true, animated: true)
//左右にボタン追加
let leftButton = UIBarButtonItem(barButtonSystemItem: .stop, target: self, action: nil)
let rightButton1 = UIBarButtonItem(barButtonSystemItem: .undo, target: self, action: nil)
let rightButton2 = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: nil)
self.navigationItem.leftBarButtonItem = leftButton
self.navigationItem.rightBarButtonItems = [rightButton1, rightButton2]
//ボタンアイテムの色
self.navigationController?.navigationBar.tintColor = .red
//バーの色
self.navigationController?.navigationBar.barTintColor = .gray
```
![Simulator Screen Shot - iPhone 8 Plus - 2021-02-17 at 11.39.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644086/50a802df-317e-ea49-85d0-0da50615b10a.png)
Bootstrapの導入

Bootstrapとはそこそこデザインの良いWebの画面を作成するためのフレームワークです。

これを使うことによってCSSを触らなくてもデザインを整えることができます。

それでは導入方法を説明しいきます！

⚠︎WebpackerがRails5.1から標準でサポートされている状態です。

#1　BootstrapをWebpackerで導入
まずはconsoleで

```
gem 'webpacker', '~> 4.0'
```

をやりますが、先ほど説明した通り、Rails5.1以降標準でサポートされているため、デフォルトでGemが追加されています。


それではGemfileにwebpackerというgemがあることを確認できたらjQueryとBootstrapを導入します。


```
yarn add jquery bootstrap popper.js
```

次にconfig/webpack/environment.js に以下のコードを追加してください。

```
const { environment } = require('@rails/webpacker')

module.exports = environment

  const webpack = require('webpack')
  environment.plugins.append(
    'Provide',
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      Popper: ['popper.js', 'default']
    })
  )
```
#2 Bootstrapのstyleをimport

次に、app/javascript/stylesheets/application.scssにBootstrapのstyleをimportする記述を追記します。
このapp/javascript/stylesheetsディレクトリ及び、app/javascript/stylesheets/application.scssファイルは存在しないので以下のコマンドで作成します。


```
mkdir app/javascript/stylesheets
touch app/javascript/stylesheets/application.scss
```

作成したら、app/javascript/stylesheets/application.scssファイルに以下のコードを追加してください。

```
@import '~bootstrap/scss/bootstrap';
```
#3 application.jsにコードを追加

yarn でインストールしたBootstrapのパッケージを利用できるようにimportします。

次にapp/javascript/packs/application.js に以下のコードを追加してください。

```
  import 'bootstrap';
  import '../stylesheets/application';
```

#4 レイアウトに stylesheet_pack_tag を追加

app/views/layouts/application.html.erb に以下のコードを追加してください。


```
<!DOCTYPE html>
<html>
  <head>
    <title>Kanban</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

    <%# ここに追加する %>
    <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

  </head>

  <body>
    <%= yield %>
  </body>
</html>
```

以上がBootstrapの導入法です！
【Python】Excelファイルを読み込み、csvを出力するプログラム

#はじめに
Pythonは機械学習や画像解析といった難しいことによく使われるといったイメージを持たれがちだが、実はエクセルを操作するなどといった身の回りの簡単な仕事にも気軽に使うことができる。
Pythonを身に着けることができればあらゆるITのシーンで活躍できるので是非ともマスターしたい。
この記事では誰かのそういったきっかけになれるよう、簡単なエクセル連携のサンプルプログラムを掲載しようと思う。

#プログラム詳細
エクセルファイルの「Sheet1」シートを読み込み、下記のセルの値を抜き出してcsvファイルを作成する。

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789979/769355ec-82ca-9a72-5598-b84ec852fae6.png)


#サンプルプログラム
```Python:Sample.py
# エクセルを操作するライブラリ
import xlrd
import pprint

# open_workbokでエクセルデータを取り込み
wb = xlrd.open_workbook('C:/folder/test.xlsx')
# sheet_by_nameでシートを指定
sheet = wb.sheet_by_name('Sheet1')

# 読み込み範囲を設定(今回は0～4の5セル分)
count = 0
EndPoint = 4

# CSVの出力先パスを設定
CSVPath = 'C:/folder/test_result.csv'

# 書き込みモードでCSVのパスをオープン
f = open(CSVPath,'w')

while True:
    # 縦のセルの情報を順番に取得していく
　　# 処理の最後でcountを+1し、次のセルに移る
    cell = sheet.cell(count, 0)

　　# countの値がEndPointと同じ値になったら、そのセルの値もcsvに出力してからループを終了
　　# 末尾にカンマはつけない
    if count == EndPoint:
        print(f.write(cell.value))
        break

　　# セルの値と末尾にカンマをつけてcsv出力
    print(f.write(cell.value + ","))
    count += 1

# csvのパスをクローズ
f.close()
```

#出力結果(csvの中身)
```
りんご,みかん,ぶどう,メロン,もも
```
RailsでJSが読み込めない時の対処法

#導入
現在、Railsを使ってアプリケーション開発をおこなっている最中です。
動きのあるビューのために、Java Scriptを呼び出したところエラーにぶつかりました。Java Scriptは基礎学習を終えたレベルです。
今回は"忘備録"として記事に残しておきます。


#環境
ruby '2.6.5'
rails '6.0.0'

#エラー内容
![スクリーンショット 2021-02-17 10.48.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/792954/ab33d8f5-f523-2949-8f1a-f00ea79409cf.png)
こちらのエラー内容は、jsファイルが見当たらないということらしいです。

#解決策
```ruby:view/layouts/applocation.html.erb

  <%= javascript_include_tag 'application' %>
                     ↓(変更)
  <%= javascript_pack_tag 'application' %>

```

これは、Rails6.0.0で「webpacker」が追加されたことにより、includeからpackに変更する必要があります。

#忘備録(導入手順)
ここからはRailsにJSを導入する手順をまとめておきます。

##手順
まず、導入する全体の手順を確認します。
![スクリーンショット 2021-02-17 11.18.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/792954/8d52e367-2579-12d6-ea66-0c52421b519c.png)
Angular CLI 機能

Angular CLIは簡単なコマンドを利用してAngularプロジェクトのScaffoldingを生成、実行、ビルドでき、Angularの様々な構成要素を追加できる指令方式のインターフェースです。

サポートする機能は以下のとおりです。

- Angularプロジェクト作成

- Angularプロジェクトにcomponent、directive、pipe、service、class、interfaceなどの構成要素を追加

- Live Reloadをサポートする内蔵開発サーバーを使用したAngularプロジェクトの実行

- UnitE2Eテスト環境対応

- デプロイのためのAngularプロジェクトpackaging



インストールと削除方法です。

$ npm install -g @angular/cli

$ npm uninstall -g @angualr/cli

$ npm cache verify

$ npm install -g @angular/cli@latest

インストールの確認はngversion指令で確認することが出来ます。



基本指令は以下の通りです。

- プロジェクト作成

$ ng new <project-name>

Angularの基本構造、名入れ規則、コード規則などを遵守してプロジェクトを作成します。

- プロジェクト実行

$ cd <project-name>

$ ng serve [--open] [-- port xxxx]

- 構成要素を作成

$nggenerateを利用しています。 

- Component作成

$ ng generate component (ng g c) <component-name>

srcappフォルダに<component-name>フォルダを作成します。

フォルダの中に4つのファイルが生成されます。

component.html, component.css, component.ts, component.spec.ts

Root component「src/app/app.module.ts」に新しく生成されたcomponentを登録します。

コンポーネントをインポートして@NgModuleのdeclarationsに登録します。

* componentのselectorの名前はkebab-case規則で作成され、基本接頭辞はappです。

- Directive作成

$ ng generate directive highlight

- Module生成

$ ng generate module todos

- サービス作成

$ ng generate service data

- Class作成

$ ng generate class user

- デプロイのためのビルド

$ ng build [--prod]



ありがとうございます。
Shopifyのliquidでは四則演算ができない

## 四則演算とは
足し算・引き算・掛け算・割り算のことです。

## やりたいこと
- 割引金額を算出したい
- 割引率を算出したい

## できなかった
こんな感じで算出したかったけどできなかった。

```liquid
{%- assign deff_price = product.compare_at_price_max - product.price -%}
{{ deff_price }}
```

## Shopifyのliquidでの計算方法
Shopifyの計算では以下の[Math filters](https://shopify.dev/docs/themes/liquid/reference/filters/math-filters)を使います。

- plus（足し算）
- minus（引き算）
- times（掛け算）
- divided_by（割り算）

金額を表示するときは[Money filters](https://shopify.dev/docs/themes/liquid/reference/filters/money-filters)も便利。

`product`から出している金額の違いは[The product object](https://shopify.dev/docs/themes/liquid/reference/objects/product)を参照。

### 割引金額を算出
```liquid

{% if product.compare_at_price_max > product.price %}
    {{ product.compare_at_price_max | minus: product.price}}
{% endif %}
```


### 割引率を算出

```liquid

{% if product.compare_at_price_max > product.price %}
    {{ product.compare_at_price | minus: product.price | times: 100.0 | divided_by: product.compare_at_price }}%
{% endif %}
```

#### 割引率を四捨五入
`round `フィルターをつけたら四捨五入できます。
[round フィルター](https://shopify.dev/docs/themes/liquid/reference/filters/math-filters#round)

```liquid

{% if product.compare_at_price_max > product.price %}
    {{ product.compare_at_price | minus: product.price | times: 100.0 | divided_by: product.compare_at_price | round }}%
{% endif %}
```

## 参考
https://shopify.dev/docs/themes/liquid/reference/filters/math-filters
https://shopify.dev/docs/themes/liquid/reference/filters/money-filters
https://qiita.com/keninph1/items/350fd307e8c073ae6551
https://www.shopify.com/partners/blog/shopify-filters
40代おっさんVPCを勉強してみた③

#40代おっさんVPCを勉強してみた③

##本記事について
本記事はAWS初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

##AWS作成図
![vpc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/b9dc8ad4-bba8-2910-9975-96abff578ad3.png)

##構築手順
❶　VPCを作成する
❷　VPCの中にサブネットを作成する　
❸　インターネットゲートウェイをVPCに割り当てる
❹　ルートテーブルにインターネットゲートウェイへのルートへのルートを追加

❶～❷はこちらを参照してください。
https://qiita.com/kou551121/items/2535fe3de57a5c813687

###3.インターネットゲートウェイをVPCに割り当てる

![インターネットゲートウェイ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/5d7c52c3-911a-8bba-5311-77e36270e059.png)

インターネットゲートウェイ（赤枠）をクリックしてください。
インターネットゲートウェイの画面に遷移しましたら
![インターネットゲートウェイの作成.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/1790e245-4ee0-6900-d32f-48cf4e7e4c44.png)

インターネットゲートウェイの作成をクリックしてください！

![インターネットゲートウェイの名前.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/e2c6f85a-4c6c-d8b2-e920-e4fc599518da.png)

名前タグに名前を入れてください（どのVPCとつながっているかわかりやすいものが良いと思います。）
終わったら下のほうにあるインターネットゲートウェイの作成をクリック！！

![VPCにアタッチ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/491a4fae-0217-37a6-0dd9-e96712d99cbf.png)

赤枠を見るとDetachedになっています！！
上の緑枠にVPCのアタッチとありますが、これを使ってアタッチしてもよいですがアクションのほうを使用してみます！！

![アタッチ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/c7d6be32-686e-9a22-2d16-9bb788794fa6.png)

赤枠のVPCにアタッチをクリック
↓の写真に画面遷移
![VPCアタッチ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/0447daa0-3b01-875d-ac88-584c453e9730.png)
赤枠に使用可能なVPC選択（これはVPCのIDでTest-VPCである）
選択後はインターネットゲートウェイのアタッチをクリック
![アタッチ確認.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/54decd79-92e0-0b1a-9f3f-71d17c159c35.png)
赤枠でアタッチできているが確認できます！！
状態もAttachedに変わっています！！

###4.ルートテーブルにインターネットゲートウェイへのルートへのルートを追加

VPCダッシュボードからサブネットをクリック
![レ点チェック.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/e5f9db23-e081-b511-3846-a576db3c19b6.png)
Test-subnet-publicにレ点チェック（赤枠）

その後下にルートテーブル（青枠）でるのでそちらをクリックすると↑の写真のようになります！！
写真を見るとデフォルトのルートができています。こちらは削除、変更はできません（10.0.0.0/16）！！
ルートテーブル：rtb-0a031c49911f47b89と出ています。そこをクリックしてください！！
![ルートテーブル.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/3d39a145-d463-2280-e93a-e6aaab0dcfc3.png)
赤枠をクリック
その後ルート編集（青枠）がでるのでそれをクリックしてください
![ルートテーブルの追加.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/36a53e79-1dc3-cc6a-9700-5f1ab13bb3ee.png)
ルートの追加（赤枠）をクリック
送信先に0.0.0.0/0（青枠）を入れてください。
ターゲットにインターネットゲートウェイのIDを入れてください。
これで0.0.0.0/0（すべての通信）がインターネットゲートウェイに行くよと言う意味になります。
終わったらルートの保存を押してください。
サブネットのTest-subnet-publicを確認すると
![ルーとテーブル確認.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/153e4dbe-cbf7-1638-5bcb-5e6b8829407b.png)
赤枠のところで追加された項目を確認できます。

##最後に
これで構築手順➍まで終わりました。気づいた方もいらっしゃると思いますが作成図が完成していないので次からはEC2も含めて説明を行い完成させたいと思います。

またこの記事はAWS初学者を導く体系的な動画学習サービス「AWS CloudTech」の課題カリキュラムで作成しました。
https://aws-cloud-tech.com/
Laravelでコロナ禍での体調管理を意識した簡単な体調記録アプリを作ってみた

#コロナ禍での体調管理を意識した体調記録アプリを作ってみた

##はじめに
　HTML/CSSってなに？ってところから始まりプログラミング学習歴約1年の私が就職活動のポートフォリオのひとつとして作成したアプリの紹介。
Laravel勉強し始めてチュートリアル的にタスクアプリを勉強した後のアプリ開発第二段のお話。

##開発した経緯
　Laravelを勉強し始め、何か作ってみたいと考えていた。新型コロナウイルスが流行しており、日々の体調管理が必須となっていたため、コロナチェックを意識して体温、体調の記録アプリを作ってみた。

##開発環境
* windows10
* XAMPP 7.4.14 (PHP 7.4.14)
* Laravel Framework 6.20.7
* HTML/CSS、BootStrap、JavaScript(jQuery)
* サーバーはVPS

##完成したアプリはこちら

[体調管理アプリCondition](https://condition.sono-portfolio.work/)
↑現在は停止中
[GitHub](https://github.com/N0S0/Condition)

* トップページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615830/11b71189-4278-1da6-9b3c-df8af09e3a12.png)

* 記録一覧ページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615830/c44a24b0-86a4-7259-0856-794725886306.png)

* カレンダーページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615830/882ac5d4-ed7f-ab92-974b-40dd38a1f7a9.png)

* ユーザー情報ページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615830/6617d034-2e41-ae7f-572d-4faae1443b78.png)

* 記録ページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615830/f78e538a-dd69-ff53-41d4-fdaabaa5f1ba.png)

* その他
レスポンシブ対応。

##制作時間
取り組んだ期間的には1か月ほどかかってるけど、時間的には約80Hほど。Laravel初心者頑張った。

##機能
* ユーザー登録、削除
* ログイン、ログアウト、ゲストログイン(emailログインからユーザーネームログインへと変更)
* パスワード変更
* 体温と体調の記録、編集、削除
* カレンダーへの記録表示
* 記録がある場合はカレンダーから詳細ページへ移動

ゲストログインしたときに記録したデータはログアウトすると削除されるように設定中。

##記録項目について
　一応、新型コロナウイルス流行初期のころに言われていた下記あたりを記録項目に入れた。

* 体温
* 体調(味覚異常、嗅覚異常、咳・痰、倦怠感)

あと、女性は生理前や生理中に体温がやや上がるためチェック項目を入れた。妊娠中も体温が上がるらしいので追加すれば良かったかも。

##余力があれば追加したい、追加したかった機能
* 4日以上、症状が続いたときのアラート(これは判断基準が変わっているから追加するか微妙なところ)
* 体温のグラフ表示
* リマインダー機能(ってあるの？)

あとは記録したことだけをシェアするような機能があっても良いかもしれないなとも思っている。

##公開準備
　ConoHaVPSを使用しました。ここの部分はかなりチート実施。詳しい方に教えてもらいながら公開。

##難しかったところ、工夫したところ、反省点
* 難しかったところ

　なにせ経験が浅く、アプリ開発に慣れていなければLaravelにも慣れていないものだから何もかもが難しかった。MVCって何？とかmodel...？contoroller？え、コマンドラインで動かさなきゃダメなの...？みたいなところから始まってどこに何を書けば良いのかやりながら感覚的に掴んでいくスタイルとなってしまった。JavaScriptファイルを分けてコンパイルして使うはずが、コンパイル部分で詰まりに詰まって結局、ソースコード直書き状態なのでこのあたりは特にいただけない部分かも。

* 工夫したところ

　工夫した点はカレンダー表示したところ。カレンダーで記録の有無がわかれば良いなと思って作った。記録がある日はその日付の数字をクリックするとカレンダーから体温、体調記録の詳細にも飛べるようになっている。

* 反省点

反省点1：なんちゃって基本設計までしかせずに作り始めてしまったため、あとから簡易詳細設計としてクラス図を作ったが、ファットコントローラーだったり、同じようなクラスがあったりとわりとぐちゃぐちゃだったので反省。でも詳細設計って、ソースコード書けないとそこまで落とし込めないんだよな...と自分の能力の低さに悲しくなった今日この頃。

反省点2：バリデーションが...という状況。

反省点3：今回2台のPCで開発していて、環境(バージョン)が違うまま進めていたため、途中でそのあたりでも躓いてダウングレードするとか悩みに悩んだ。また、開発環境ではうまくいってるのに本番環境ではうまくいかないなんてこともあり、発狂しそうになりながらPCに向かっていた。これを機にdockerの勉強をしたらこういうことがなくなるのかなと思う。
RxJavaで連続的なAPI呼び出し後のエラー処理方法

RxJavaで連続的にAPIを呼び出して発生するエラーを処理するための方法です。

APIを繰り返し呼び出した場合にエラーが発生する場合、Exception処理を行うためonErrorResumeNextを利用できます。

この関数を利用すると、エラーが発生した時に他のObservableが流れ続けるようにできます。 
エラーを返すためにonErrorで処理を分離することもできます。

実例:
repo.getAuth("xxx")
    .onErrorResumeNext { Single.error(AuthError("${it.message}")) }
    .flatMap { repo.getPayment(it.token) }
GoogleAppsScriptでgmailをLINEに転送

こちらの記事のスクリプトを改造しました。

* [Gmailの新着通知をLINEで受け取る by Google App Script｜uyu666｜note](https://note.com/yuut6/n/nb3528b53ddfa)
* [[Gmail to LINE]GASで新着メールをLINEに転送する - Qiita](https://qiita.com/Damon/items/bbe6350ef1a4a10fe397)

[こんなサービス](https://line-email.dqc.jp/)もあるみたいなので、自分でやる必要もないのですが、ちょっと凝った応用をしたかったり、あまりよく知らない企業のサービスにメールを転送するのが嫌な場合もありますよね。

## 変更点
* 前回実行時に処理したメールの message ID を覚えておき、同じメールを二度転送しない
* スレッドの最後のメールだけでなく、全てのメールを転送

## コード
```js
const lineToken = "自分で取得したトークンに置き換えてね"; // LINE Personal Token
const query = "label:転送したいメールのラベル" // gmailの検索クエリ
const thresholdInMinutes = 60; // 何分前のメールまでチェックするか(同じメールは二度転送しないので、スクリプトの実行間隔より長くて良い)

const scriptProps = PropertiesService.getScriptProperties();

function sendToLine(message){
  const payload = { message };
  const options = {
   method: "post",
   payload: payload,
   headers: { Authorization: `Bearer ${lineToken}` },
  };
  UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options);
}

function getPrevMessgeIds() {
  try {
    return JSON.parse(scriptProps.getProperty("messageIds") || "[]");
  } catch (error) {
    console.log("getPrevMessageId: error:", error);
    return [];
  }
}

function fetchMails() {
  const now = new Date().getTime();
  const threshold = now - (60 * 1000 * thresholdInMinutes);

  const threads = GmailApp.search(`(${query}) after:${Math.floor(threshold / 1000)}`);
  const threadMessages = GmailApp.getMessagesForThreads(threads);
  const prevMessageIds = getPrevMessgeIds();
  console.log("prev message ids", prevMessageIds);
  const lineMessages = threadMessages.flatMap((messages) =>  {
    return messages.filter((message) => {
      return threshold <= message.getDate().getTime() && prevMessageIds.indexOf(message.getId()) < 0;
    }).map((message) => {
      return `\n[from] ${message.getFrom()}\n[subject] ${message.getSubject()}\n\n${message.getPlainBody()}`;
    });
  });
  const messageIds = threadMessages.flatMap((messages) => {
    return messages.map((message) => message.getId());
  });
  console.log("current message ids", messageIds);
  scriptProps.setProperty("messageIds", JSON.stringify(messageIds));
  return lineMessages;
}

function main() {
  const messages = fetchMails();
  console.log(`${messages.length} message(s) found`);
  messages.forEach(sendToLine);
}
```
WebGLファイルをlocalで実行方法

1. File -> Build Settingsに移動します。
2. Build Settings画面からWebGL項目を選択し、Switch Platformボタンをクリックします。
3. Buildボタンを押します。
4. Build WebGL画面の保存パスを選択します。
5. Buildが成功したら、保存パスに移動してindex.htmlを次のファイルに置換します。
6. XAMPPプログラムをインストールします。
7. configファイルを開いて252行に移行します。
8. Document RootをBuildファイルが保存されたパスに変更します。
9.httpd-sslファイルを開いて36行に進み、Listen 443ポートを停止します。
10.XAMPPプログラムでApacheサーバーを起動します。(startボタンクリック)
11. web browserでlocalhostを入力して実行します。
Python モジュール・パッケージ 検索・ロードの仕組み

:::note warn
2020年に書いた個人的なまとめです
:::

# モジュール・パッケージ 検索の仕組み
- ![module_install.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/56201d85-363b-799f-f90c-04189e3fddb6.png)

- 公式
  - https://docs.python.org/ja/3/reference/import.html#searching
- [import path](https://docs.python.org/ja/3/glossary.html#term-import-path)
- sys.path
    - モジュールを検索するパスを示す文字列のリスト
    - https://docs.python.org/ja/3/library/sys.html#sys.path

# モジュール・パッケージ ロードの仕組み
- モジュールがPython モジュールだった場合、ローダーはモジュールのグローバル名前空間 (module.__dict__) で、モジュールのコードを実行すべき
    - [5. インポートシステム — Python 3.9.1 ドキュメント](https://docs.python.org/ja/3/reference/import.html#loaders)
- サブモジュールをロードするのにどのようなメカニズムでも、バインディングはサブモジュールオブジェクトを親モジュールの名前空間に配置します
    - [5. インポートシステム — Python 3.9.1 ドキュメント](https://docs.python.org/ja/3/reference/import.html#submodules)
【Python】フォーマット済み文字列リテラル

#フォーマット済み文字列リテラルとは
いわゆる「文字列補完」。
Pythonでは「f-string」「f文字列」などと呼ばれることもある。
フォーマット済み文字列リテラルは、文字列を囲むクォーテーションの前に「f」を前置して、その内部で「{式}」と記述することで、その部分にその式の値(変数の値など)を埋め込むことができる。

#サンプルプログラム
```Python:Sample.py
name = 'snake.com'

# {}内に記述した変数の値や式の計算結果が補完される。
print(f'name = {name}')
print(f'1 + 2 * 3 = {1 + 2 * 3}')
```

#出力結果
```
name = snake.com
1 + 2 * 3 = 7
```

***
また、「書式指定文字列」も使用可能(「:」以降に記述される)
※書式指定文字列の参考URL:https://docs.python.org/ja/3/library/string.html#formatstrings

#サンプルプログラム
```Python:Sample.py
# 「右寄せ（>）、正負両方の値で符号を付加（+）、8桁幅（8）、3桁ごとにカンマ（,）を挿入（,）、10進数（d）」
print(f'2 ** 12 = {2 ** 12 :>+8,d}')

# 「0bを前置（#）、4桁ごとにアンダースコア（_）を挿入、2進数（b）」
print(f'2 ** 12 = {2 ** 12 :#_b}')
```

#出力結果
```
2 ** 12 =   +4,096
2 ** 12 = 0b1_0000_0000_0000
```
HTMLタグの英語の意味

HTMLを勉強してるとタグの種類がいっぱいあって訳わからん状態でしたが、タグの英語の意味を知ったら覚えやすかったので備忘録として残しておきます。
初投稿になるので、温かい目で見てやってください。

# HTMLで使うタグ一覧
|  要素  |  意味  | 説明 |
| ---- | ---- | ---- |
|  &lt;a&gt;  | 「anchor」|リンクの出発点や到達点を指定する|
|  &lt;b&gt;  | 「bold」 |フォントを太字にする|
|  &lt;br&gt;  | 「break」|改行を表す|
|  &lt;div&gt;  | 「division」|囲った部分をブロックレベル要素としてグループ化する|
|  &lt;hr&gt;  | 「horizontal rule」|水平の横線を引く|
|  &lt;li&gt;  | 「list item」 |リストの項目を表示する |
|  &lt;ol&gt;  | 「ordered list」 |順序のある番号付きのリストを表示する|
|  &lt;p&gt;  | 「paragraph」|段落を指定する|
|  &lt;td&gt;  | 「table data」 |テーブルセルの内容を指定する|
|  &lt;th&gt;  | 「table header」|表の見出しやタイトルとなるヘッダセルを作成する|
|  &lt;tr&gt;  | 「table row」|表の行部分（横方向）を指定する|
|  &lt;ul&gt;  | 「unordered list」 |順序がない箇条書きのリストを表示する|

# 参考URL
https://html-coding.co.jp/annex/dictionary/html/
Android 10 搭載の一部端末で ListView の項目を選択できない障害について調べたら……

# 障害発生
　
業務で Android アプリの保守をしていたら、Android 10 搭載の一部端末で ListView をタップしてもしばらく反応しないという障害が発生しました。

障害が発生し始めたのは、TabActivity を(ようやく) ViewPager2 に置換してから。当該画面は Activity から Fragment に作り替えられました。

以前との違いを調べれば原因が分かるはず、とリーダーから指示されて調べたのですが……

# これは選択できなくて当然なのでは

調べて、原因が判明するまでに、Android Studio のデバッガで Android システムの Java クラス内部まで見る必要がありました。

原因はこうです。

Activity から Fragment に作り替えたことにより、ListView を含む Fragment が ViewPager2により Windows にアタッチしたりデタッチしたりされるようになりました。

ListView の親クラス AbsListView がWindow からデタッチされたときに呼び出される `onDetachedFromWindow()` で、Adapter への参照を持つインスタンス変数 mAdapter が `mAdapter != null` の場合に次の処理が実行されます。

```Java
if (mAdapter != null && mDataSetObserver != null) {
    mAdapter.unregisterDataSetObserver(mDataSetObserver);
    mDataSetObserver = null;
}
```

これにより `mDataSetObserver == null` が保証され、Window からデタッチされている間はデータの変更が反映されなくなります。

その後で AbsListView が Window にアタッチされたときに呼び出される `onAttachedToWindow()` で、Adapter への参照を持つインスタンス変数 mAdapter が `mAdapter != null && mDataSetObserver == null` の場合に次の処理が実行されます。

```Java
if (mAdapter != null && mDataSetObserver == null) {
    mDataSetObserver = new AdapterDataSetObserver();
    mAdapter.registerDataSetObserver(mDataSetObserver);

    // Data may have changed while we were detached. Refresh.
    mDataChanged = true;
    mOldItemCount = mItemCount;
    mItemCount = mAdapter.getCount();
}
```

データの変更が View に反映されていないことを示すインスタンス変数 mDataChanged が `mDataChanged == true` になります。この変数が true の間は、リストの項目が古いので、タップが無視されます。

ところが、障害が起きている端末では、いくら待っても、この変数が false に変わらないのです。そのためタップを繰り返しても無視されてしまいます。

インスタンス変数 mDataChanged が `mDataChanged == false` になる契機の一つは、View に Layout が実行されることです。しかし Window にアタッチされたのに Layout は実行されません……

どうしてそんなことになるのか、頭を抱えました。

# なぜ多くの端末で項目を選択できるのか

障害が発生していない端末で挙動を調べるようリーダーに指示されて、調べた結果が下記のスクリーンショットです。本当に商用のアプリのデバッグ中に記録したスクリーンショットで、アプリの詳細や開発環境が露見する箇所はぼかしています。

![screenshot_for_qiita_20210217.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49698/15659ff7-1d26-1bb7-f3c6-ea72c25dd168.png)


このスクリーンショットは Pixel 4a で ListView を1回タップした後の処理の途中です。

タップなので、ポインティングデバイスには DOWN と UP のイベントが発生します。しかし、その間に、人間にとってはタップのつもりが、端末内部では MOVE のイベントが発生しています。

MOVE のイベントが発生すると ListView はスクロールさせる必要が生じます。そこに、次のようなコメントがあります。

```
// Re-sync everything if data has been changed
// since the scroll operation can query the adapter.
```

データが変更されていれば同期させると言います。そして View の子を Layout しています。

ListView がスクロールされる際、その事前条件を満たすための処理が実行されることにより、データが ListView に反映されるため、以降は項目を選択できるようになるのです。それまでデータが ListView に反映されていないことはインスタンス変数 `mDataChanged == true` によって証拠が残っています。

ListView の項目を選択できることが、タップ中に MOVE イベントが発生することに依存しているのです。

障害が発生していた端末では、タップ中に MOVE イベントが発生しないことがありました。頻度はまちまちです。MOVE イベントが発生しなかったタップは、ListView の状態が整わず、無視されていました。

僕には、これがバグとは断定できません。Google が端末メーカに、タップ中に MOVE イベントを発生させるよう要求していれば、この仕様で動作します。端末メーカがどのような指示を受けているのか知らない僕は、是非を断ずることができません。

ただ、障害を起こした端末が存在します。また、UI パーツの初期化完了がポインティングデバイスのイベントに依存している仕様は、すぐには受け入れがたいものがあります。

# 直近ではどうしたか

まずはアプリのバグを直さなければいけません。

対処として、問題の ListView を含む Fragment の onResume() で ListView に requestLayout() を呼び出すようにしました。Layout は瞬時に終わっているようで、利用者から見て問題なく ListView の項目を選択できるようになっています。

# これからの話は……

上記の挙動が、Android 9 以前と、Android 11 でどう変化しているのか、調べていません。僕は言い出しっぺですが、余力がありません。
ubuntu20.04LTSにGoogle Chromeをインストールする

# はじめに

ubuntu20.04LTSにGoogle Chromeをインストールしたのでメモ


# 環境

Utuntu20.04.1 LTS


# パッケージリストに追加

```bash 
sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
```

# 公開鍵を登録

```bash
sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
```


# パッケージリストを更新

```bash
sudo apt update
```


# インストール　

```bash
sudo apt-get install google-chrome-stable
```



# 起動

```bash
google-chrome
```




# 参考

https://qiita.com/pyon_kiti_jp/items/e6032eb6061a4774aece
【Python】ジェネレーターをシンプルに理解する

#ジェネレーターとは
「何らかの値を連続的に生成する」反復可能なオブジェクトであり、ジェネレーター関数を用いて定義する。
ジェネレーターはリストやタプルなどと同様に、反復処理に利用できる（ジェネレーター関数の実際の戻り値は反復可能な「ジェネレーター」オブジェクトになる。

#単純なジェネレーター
「引数に指定された値未満の整数列を返す」反復可能オブジェクトを返す。
まずgen関数の出力が先行し、yieldで返された値が呼び出し元のcntに渡され、print(cnt)される。
通常のforループなら呼び出し元に戻るまでにループし尽くすが、yieldすることで一旦戻っている。

#サンプルプログラム
```Python:Sample.py
def gen(n):
    for num in range(n):
        print("generated")
        yield num

for cnt in gen(10):
    print(cnt)
```

#出力結果
```
generated
0
generated
1
generated
2
generated
3
generated
4
generated
5
generated
6
generated
7
generated
8
generated
9
```
いつものvimrc備忘録

## 概要
vim をメインエディタとして使っています。
いつもとりあえずこの設定を ~/.vimrc に設定し、ベースとして使用してます。



## ~/.vimrc


```
set fenc=utf-8
set nobackup
set noswapfile
set autoread
set hidden
set showcmd
set number
set virtualedit=onemore
set smartindent
set visualbell
set showmatch
set laststatus=2
set wildmode=list:longest
nnoremap j gj
nnoremap k gk
syntax enable


set expandtab
set tabstop=2
set shiftwidth=2


set ignorecase
set smartcase
set incsearch
set wrapscan
set hlsearch
nmap <Esc><Esc> :nohlsearch<CR><Esc>
set clipboard=unnamedplus
```
データテーブルの連結ー横方向1（完全外部結合）

テーブルとテーブルの連結には、縦方向（行が増える）と横方向（列が増える）の場合があります。
縦方向の場合は__集合__、横方向の場合は__結合__と言います。

結合には以下のパターンがあります。
　完全外部結合：共通しないレコードをすべて含めて列を増やす。
　右(左)外部結合：右(左)側のテーブルの共通しないレコードを含めて列を増やす。
　内部結合：共通するレコードを対象として列を増やす。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287001/7dd9c91b-0bd0-2f40-4a6c-0acc0e219818.png)
今回は、__完全外部結合__について、SAS プログラムと SQL、および Python (Pandas) をそれぞれ用いた例を紹介します。

行いたい操作は下記です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287001/c698ade8-c989-12c5-6953-1a4ed4f5f956.png)
A列をキーとして、値が一致するしないに関わらずすべてのレコードを取り出して、横方向に連結します。

####① SAS プログラムでの完全外部結合

~~~sas
data table_3;
  merge table_1 table_2;
  by a;
run;
~~~
__<font color="Blue"> merge </font>__ ステートメントで横に重ねることができます。
__<font color="Blue"> by </font>__ に続く変数がキーとなります。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287001/4227c148-1b6a-049c-94e5-020ee96777b0.png)


####② SQL での完全外部結合

~~~sql
 create table  table_3 as
 select coalesce(table_1.A, table_2.A) as A, B, C 
 from table_1 full join table_2  on  table_1.A = table_2.A ;
~~~
<font color="Blue"> __SELECT__ </font> 取り出す変数名  <font color="Blue">__from__</font> データセット1 <font color="Red">__full join__</font> データセット2  <font color="Blue">__on__</font> 結合条件

SELECT文で <font color="Blue">__coalesce__</font> という関数を使ってます。与えられた引数のうち、NULLでない最初の引数を返します。
coalesce 関数につきましては、詳しくは下記リンクを参照下さい。
　https://doruby.jp/users/akio0911_on_rails/entries/SQL_coalesce_
　https://tech.adseed.co.jp/sql-coalesce
また、結合する2つのデータセットで同じ変数名を持っている場合、「データセット名.変数名」と書きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287001/9a634536-ed7f-bbd5-fa8c-74bc93adbd72.png)

####③ Python (Pandas) での完全外部結合
~~~python
import pandas as pd
table_1 = pd.DataFrame({'A': [1, 2], 'B': ['AA', 'BB']})
table_2 = pd.DataFrame({'A': [2, 3], 'C': [10, 20]})
table_3 = pd.merge(table_1, table_2, on = "A", how="outer")
~~~
__<font color="Blue"> .merge </font>__で結合、on にキー列を指定、how で様式（完全外部なので "outer"）を指定します。

出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287001/eb388a57-94c2-856b-19b9-68f4ecb2af2e.png)
ちなみに how の様式指定では、 "inner" が内部結合、"left" ("right") が左 (右) 外部結合となります。

####関連記事
[データテーブルの連結－縦方向 1（異なる列名をそのまま残す場合）](https://qiita.com/MomonekoView/items/78f51b7385bec42d08ed)
[データテーブルの連結－縦方向 2（異なる列名を統合する場合）](https://qiita.com/MomonekoView/items/e63b54b0ae1849c3ddd1)
[データテーブルの連結－縦方向 3（積集合と差集合）](https://qiita.com/MomonekoView/items/14fe790b6993c2b3dad3)
[データテーブルの連結－横方向 2（内部結合）](https://qiita.com/MomonekoView/items/5d067363c506a0ab2013)
[データテーブルの連結－横方向 3（左右の外部結合）](https://qiita.com/MomonekoView/items/434d8bceab29606568e9)
[データテーブルの連結ー交差結合](https://qiita.com/MomonekoView/items/d57a2adf97b10e4549d1)
ASP.NET Core Razor Pages で Hello World アプリケーションを作成する

ASP.NET Core Razor Pages で Hello World アプリケーションを作成してみましょう。これから ASP.NET Core Razor Pages を利用される方の参考になりましたら幸いです。この記事では、Visual Studio 2019 を利用して作業を進めていきます。

###アプリケーションテンプレートの選択方法

Visual Studio 2019 を起動し、「新しいプロジェクトの作成」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142487/2ad79be6-9006-fc38-74ec-31f23c9091bf.png)

「ASP.NET Core Web アプリケーション」を選択し、「次へ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142487/961aaa1a-fff0-7b52-6976-f605215c7af8.png)

プロジェクトに「RazorPages_HelloWorld」という名前を付けて、「作成」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142487/d197ceb9-f78e-5464-698b-8a23a7fd3f27.png)

「ASP.NET Core Web アプリ」を選択し、「作成」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142487/e55d3596-6c90-f49d-bee5-7c6d1bd400c5.png)


ここまでの手順を経ることで、アプリケーションテンプレートから、ASP.NET Core Razor Pages アプリケーションを作成することができました。


###アプリケーションの実行

それではアプリケーションに変更を加えない状態で、アプリケーションを実行してみましょう。F5 を押下する、もしくは、「デバッグの開始」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142487/69a7c457-bae8-fbb7-c84c-7897cbda11c0.png)


すると、アプリケーションが実行され、次の画面が表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142487/a3d7adf4-8d19-2718-3cbc-2490650ed1e1.png)


###Hello World の表示

続いて、「Welcome」と表示されている個所を、「Hello World」に書き換えてみましょう。書き換えの対象ファイルは、Pages フォルダ配下の Index.cshtml です。


8行目の h1 タグ内を Welcome から Hello World に書き換えます。その上で、アプリケーションを再起動してみます。


```html:Index.cshtml
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">Hello World</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
```
<br/>


Hello World が表示されました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142487/0d209bc6-14c0-b584-6ac0-1d3e3c4f4b02.png)


今回 IDE は Visual Studio 2019 を利用しましたが、ASP.NET Core Razor Pages アプリケーションは Visual Studio Code を利用して作成することもできます。興味のある方は、Visual Studio Code での手順についても調べてみてください。

この記事に関して何かご質問・ご不明な点がありましたら、お気兼ねなく[インフラジスティックス](https://jp.infragistics.com/about-us/contact-us)までお問い合わせください。
laravel6 現在実行可能なphp artisanコマンドを出力する

# 目的

- 実行可能な`$ php artisan`コマンドを出力する方法をメモ的にまとめる

# 方法

- アプリ名ディレクトリで下記コマンドを実行する。

    ```terminal
    $ php artisan list
    ```
MySQLの日付・日時をテストデータ用にランダム生成

###参考
[日付および時間関数](https://dev.mysql.com/doc/refman/5.6/ja/date-and-time-functions.html#function_adddate)


###MySQLの関数を使用する

####日付を扱う関数

```
ADDDATE(date,INTERVAL expr unit)
ADDDATE(expr,days)
```

```sql
mysql> SELECT ADDDATE('2008-01-02', 31);
// 結果 → '2008-02-02'

mysql> SELECT ADDDATE('2008-01-02', 31);
// 結果 → '2008-02-02'
```

第１引数 ： 基準の日付
第２引数 ： 基準の日付に加算する日数

####第２引数に渡す日数をランダム数にする

```sql
mysql> SELECT ADDDATE('2008-01-02', 31*rand());

[結果]
2021-02-06
2021-02-08
2021-02-20
```

rand()は`0 < rand() < 1.0`の範囲のランダムな浮動小数点値を生成するので、

```
0 <= rand() * 31 < 31
0 <= rand() * 100 < 100
```
という感じになります。

注意点としては右の不等号はイコールが含まれないので、整数で取得することを考えると実質は次のようになります

```
0 <= rand() * 31 <= 30
0 <= rand() * 100 <= 99
```

こっちのほうがわかりやすいですよね～


####日時を扱う関数

```java
ADDTIME(expr1,expr2)
```

>ADDTIME() は expr2 と expr1 を加算し、その結果を返します。expr1 は時間または日付時間式であり、expr2 は時間式です。




```sql
mysql> SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002');
        -> '2008-01-02 01:01:01.000001'
mysql> SELECT ADDTIME('01:00:00.999999', '02:00:00.999998');
        -> '03:00:01.999997'
```

expr2は時間式ということですが、整数でも渡せます。

```sql
SELECT ADDTIME('2021-02-01 00:00:00', 100);
 -> 2021-02-01 00:01:00

SELECT ADDTIME('2021-02-01 00:00:00', 10000);
 -> 2021-02-01 01:00:00

125812 -> 12:58:12
のように変換されて加算してくれる
```

しかし秒数で加算したほうが感覚的にはわかりやすいですよね。というときには`SEC_TO_TIME`を使います。

```sql
SELECT ADDTIME('2021-02-01 00:00:00', SEC_TO_TIME(10000));
 -> 2021-02-01 02:46:40

引数の10000を秒として処理してくれるので、
10000秒 -> 2時間46分40秒に変換してくれる

わかりやすく3600秒（1時間）を渡してあげると
SELECT ADDTIME('2021-02-01 00:00:00', SEC_TO_TIME(3600));
 -> 2021-02-01 01:00:00

```

####後はSEC_TO_TIMEにランダム数を渡して上げれば良い

```sql
SELECT ADDTIME('2021-02-01 00:00:00', SEC_TO_TIME(floor(rand() * 3600)));
 -> 2021-02-01 00:39:05
※floorで整数を渡すようにしています
```

rand() * 3600 で一時間以内の時間を返してくれます。

rand() * 3600 * 24 なら２４時間以内ですね。

１年とかにしたいけども、限界値を超えるのでできないみたいです。

秒で渡すのではなく、日数も渡せるはずなので可能だと思います。（まだ不勉強）



とりあえず簡易的なテストデータとして日付や日時を扱う分はある程度範囲が限定されていても良いかな思います。


###ちなみ・・・

javaからPreparedStatementでパラメータを渡すときに

```java

ps.setString("SELECT ADDTIME('2021-02-01 00:00:00', SEC_TO_TIME(floor(rand() * 3600)))");

```
としてもうまくいきませんでした。value (?)のように?に後から渡すんじゃなくて、
SQL分にそのまま文字列で書いちゃえば実行できました。

原因というか、なぜなのかよくわかりませんが。。。分かる方がいらっしゃいましたらコメントお願いしますm(__)m
【Python】スライスを使った降順表現

#はじめに
Pythonで配列の要素を逆順に並びかえる場合は、スライスを使って実装することができる。
降順に並び替える際にもこの手法はかなり便利である。
配列の操作をする場合によく使われるライブラリ「numpy」には「reverse」に相当する機能が存在していないが、スライスを使うことで簡単に逆順を表現できる。
ここでは、ランダムな数字が格納された配列aを降順ソートするサンプルプログラムを紹介していく。

#アプローチ手順
numpyの「sort」を使って昇順に並び替えたあと、「[::-1]」で逆順に並び替える。

#サンプルプログラム
```Python:Sample.py
import numpy as np

a = [2,5,4,12,8,3,6,0]

x = np.sort(a)[::-1]

for item in x:
  print(item)
```

#出力結果
```
12
8
6
5
4
3
2
0
```
[git] merge vs rebase

Gitのmergeとrebaseを使い分ける方法について、Bitbucketの[マージとリベース](https://www.atlassian.com/ja/git/tutorials/merging-vs-rebasing)という記事がとても参考になったので要点を紹介します。

# ルール

- PRを出す前にrebaseを行い、乱雑な履歴をクリーンアップする。
- PRを出した後はrebase禁止。

> コードレビュープロセスの一環としてプルリクエストを使用する場合は、プルリクエストを作成した後に git rebase を使用しないでください。プルリクエストを行うとすぐに、他の開発者があなたのコミットを見ることになります。つまり、それは パブリック ブランチです。履歴を書き換えると、Git とチームメイトはフィーチャーに追加された後続のコミットを追跡できなくなります。
> 
> 他の開発者の変更は git merge で取り込む必要があり、 git rebase ではありません。
> 
> このため、プルリクエストを送信する前に、対話式リベースを使用してコードをクリーンアップすることが一般的に勧められます。
rails6 ujsをwebpacker化する


rails-ujsで怒られていたのでujsをwebpacker化する手順を残しておきます。

#Gemfileの編集#

・Gemfileに'webpacker'を追加する

```Gemfile
gem 'webpacker'
```
・Gemfileに以下の記述があれば削除

```
gem 'jquery-rails'
```
###補足～gemの削除方法～###
①bundleにで削除

```terminal
$ bundle exec gem uninstall GemName
```

②Gemfileから削除

③Gemfile.lockから削除
terminalにて
bundle update or bundle installでGemfile.lockの中身を更新する

#webpackerのインストール#
```terminal
$ ./bin/rails webpacker:install
```

#rails-ujsのインストール#
```terminal
yarn add @rails/ujs
```

私はこれで怒られることはなくなりましたが
至らない点がきっとあると思うので
またわかり次第追記をしていこうと思います
M1 MacにgRPC PHPをインストールするまで

# 手順が多い。
し、めんどくさい。
ちょくちょくエラーが出る。
ただ、なんとかなったので備忘録的に残そうと思う。

gRPCが必要になった理由はfirestoreをいじりたかったから。

この記事では主に
https://cloud.google.com/php/grpc?hl=ja#macos
を参考にしている。

# 始める前に
僕みたいにスタバで空き時間に始めようとしない方がいい。
果てしない時間がかかる。
特にgRPCのインストールは長い。

# PECL
```
$ curl -O https://pear.php.net/go-pear.phar
$ sudo php -d detect_unicode=0 go-pear.phar
```

そう簡単には行かなかった。

インストールしようとすると$php_dirがなんだかんだと言われるのでインストール時の1の
```
1. Installation base ($prefix)
```
のパスを/usrから/usr/localに変えてあげる。

# Composer
```
$ curl -sS https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer
```

よし。

#gRPC
```
$ sudo pecl install grpc
```

厄介だ。
phpizeがないとかなんとか言われる。
これは

```
$ xcode-select --install
```
でXcode commandline toolsをインストールした後、

```
$ brew install autoconf
```
brewを使ってautoconfをインストールすると解決する。

### エラーは続くよどこまでも

```
#include <php.h>
         ^~~~~~~
1 error generated.

make: *** [src/php/ext/grpc/byte_buffer.lo] Error 1
ERROR: `make' failed
```

えぇ...

```
$ brew install php@7.4
```

疲れてきたので、もうこれ打って黙らせる。
php@7.2を使いたかったが、arm無理っす。と言われたので7.4に。
もしかしたら他に方法があるかもしれない...。

そして、

```
$ sudo pecl install grpc
```

ひたすら待つ。
...使えるようになった。

#おわり
色々なサイトで調べてここまで辿り着きました。
インターネットって便利。
ありがとうございました。
huskyのpre-commitが動かない→バージョンを下げるとうまくいった


タイトルがすべてです。`version 5.x`で動かなかったので`version 4.3.8`まで落としたらうまくいきました。

# 参考にしたサイト
https://wp-kyoto.net/how-to-resolve-husky-not-working-issue/

pre-commitが動いてないのが丸わかりだったので、このサイトを参考に
`ls .git/hooks`
を実行すると`*.sample`しか見えなかったんですね。
なので、何度か再インストールしてみたのですが、駄目。

結局4.3.8まで落とせばうまくいきました。うまくいったときのディレクトリはこんな感じ

```bash:shell
$ ls .git/hooks/
applypatch-msg*     husky.sh            post-commit*        post-update*        pre-commit*         pre-rebase*         sendemail-validate*
commit-msg*         post-applypatch*    post-merge*         pre-applypatch*     pre-merge-commit*   prepare-commit-msg*
husky.local.sh      post-checkout*      post-rewrite*       pre-auto-gc*        pre-push*           push-to-checkout*
```

ver.5で実行速度が上がったりdependenciesが減ったり、まずファイルサイズが小さくなってるようなのですが、それより実行できるかどうかを選ばせてください……