OmniAICreator/Qiita-1.07M huggingface dataset:
【GASが原因】Backlogにスプレッドシートで一括起票できなかった場合の対処方法

# 記事概要

私はBacklogにスプレッドシートで一括起票をしようとして、「Backlogからデータを取得（STEP1）」をやっていた際に以下のようなエラーが表示されました。

> 「ストレージからの読み取り中にサーバーエラーが発生しました。エラーコード: PERMISSION_DENIED」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2210620/3aab69d4-be65-956d-2cec-92f824a0282e.png)

私と同様に上記のようなエラー文章が表示されてしまい
「Backlog公式ページの案内どおりに作業したのに進められない」
「エラーの対処方法が公式ページに記載されていない」
と混乱・憤慨している方にオススメの記事です。

なお、本記事では以下の公式ページに記載の内容は割愛します。

- [Google スプレッドシートを使って、Backlogに課題を一括登録しよう](https://support-ja.backlog.com/hc/ja/articles/360042820873?ref=blog20180723&_ga=2.49566822.1796755940.1641346310-1847199938.1629075331)
    - これを見れば登録方法はすべてわかる
- [Googleスプレッドシートによる課題一括登録でエラーが発生して課題を登録できません](https://support-ja.backlog.com/hc/ja/articles/360041599494-Google%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7%E3%83%BC%E3%83%88%E3%81%AB%E3%82%88%E3%82%8B%E8%AA%B2%E9%A1%8C%E4%B8%80%E6%8B%AC%E7%99%BB%E9%8C%B2%E3%81%A7%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E7%99%BA%E7%94%9F%E3%81%97%E3%81%A6%E8%AA%B2%E9%A1%8C%E3%82%92%E7%99%BB%E9%8C%B2%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%9B%E3%82%93)
    - 登録時に表示されるエラーが記載されているので、基本はこちらでエラーは確認する

# 結論

本件は以下の記事によるとBacklog云々の話ではなく、`GAS`（`GoogleAppsScript`）で開発を行う際に発生するエラーだそうです。

> GASのログインユーザーと実行のログインユーザーが違うとき。
> 引用：[Google Apps Scriptで「ストレージからの読み取り中に ... エラーコード: PERMISSION_DENIED」と出る件。](https://zenn.dev/cyber_hacnosuke/articles/c8f68622efc534)

私の場合は複数のGoogle Accountでログインしていました。具体的には、プライベート用がデフォルトになっていて、一括登録で利用したい仕事用のアカウントはログインしている状態でした。

そこで、一度すべてのGoogleアカウントからログアウトして、仕事用のアカウントだけでログインして、「Backlogからデータを取得（STEP1）」をやり直したら成功しました。
[めんどくさがりな人向け] docker + rails 即行資源

下記の方を対象に簡単な資源を用意しました。
・ローカル環境汚さずにrailsしたいな
・dockerの設定めんどくさいな
・動確用にテンプレートほしいな

# 前提
docker公式に記載されているrailsの利用手順に沿い、テンプレートを用意しています。
https://docs.docker.com/samples/rails
dockerは予めインストールしておいてください。

# 即行資源
https://github.com/higak926/drf

資源をcloneし、READMEに従いビルドして起動すると即railsが利用できます。
<font color="red">※ rubyやrailsのバージョンを指定しなおしたい方は適当にDockerfileのrubyやGemfileのrailsのバージョンを変更してください
</font>

それでは良い開発を😄
pythonのdequeに、append、pop、popleftしてみた際の備忘メモです。

pythonのdequeに、append、pop、popleftしてみた際の備忘メモです。

（listと比べて計算量がO(1)である事がメリットのようですが、要素にアクセスするのが困難っぽいので、アクセスが必要な場合は[リスト](https://qiita.com/seigot/items/9268ca84fec8b7a6ea33)を使った方が良さそう。
でも大きなサイズのdequeの要素にアクセスしたい時があると思うが、その際はどうするのがいいんだろうか？？？？）

```python:test_deque.py
from collections import deque

d = deque()

# append
d.append('a')
d.append('b')
d.append('a')
d.append('ccccc')
d.append(1)
d.append(2)

# print
print("--- print")
print(d)
## -> deque(['a', 'b', 'a', 'ccccc', 1])

# count
print("--- count")
print(d.count('a'))
## 2

# index
print("--- index")
print(d.index(1))
## 4

# pop
print("--- pop")
print(d.pop())
print(d)
## -> '2'

# popleft
print("--- popleft")
print(d.popleft())
print(d)
## -> 'a'

# copy
print("--- copy")
d2 = d.copy()
print(d2.popleft())
print(d2.popleft())
print(d2.popleft())
print(d2.popleft())
print(d)
```

実行する

```
python test_deque.py
--- print
deque(['a', 'b', 'a', 'ccccc', 1, 2])
--- count
2
--- index
4
--- pop
2
deque(['a', 'b', 'a', 'ccccc', 1])
--- popleft
a
deque(['b', 'a', 'ccccc', 1])
--- copy
b
a
ccccc
1
deque(['b', 'a', 'ccccc', 1])
```

# 参考
[pythonのlistに、先頭inseart、終端にinseart、classもinseartしてみた際の備忘メモ](https://qiita.com/seigot/items/9268ca84fec8b7a6ea33)
[Pythonのデータが「deque」の使い方](https://qiita.com/ryosuke0825/items/bbc5c0673e6c6c958d66)
[dequeから範囲を指定して値を取得](https://teratail.com/questions/172345)
[Pythonで各要素にO(1)でランダムアクセスできるdeque(両端キュー)を書いてみた](https://prd-xxx.hateblo.jp/entry/2020/02/07/114818)
身近な業務改善に挑戦！

　【日常業務改善を行いたい】
　ちょっとした業務改善を行うアイデアを考えてみた。
　現在、ECサイトでユニフォームを販売する会社に勤めている。受注後発注（お客様より注文を受ける→メーカー在庫確認→生産）のフローをとっているため、在庫の更新を毎週金曜日に行っている。

　金曜日は週末前ということでお客様対応などイレギュラーな業務が多くなっている。また、メーカーからの在庫表もバラバラに時間に受信するため、そろい次第、在庫更新を行う。
そのため、ついつい忘れてしまい、業務終了間際に慌てて、在庫更新を行うことが多い。

そこで金曜日の決まった時間に通知メッセージをOutlook上に送付すれば在庫更新忘れが減るのではないかと考えた。

　【改善したいこと】
金曜日の決まった時間に在庫更新を行うことを忘れないようにしたい。

　【作成したもの】
PowerAppsで自動化したクラウドフローを作成。
毎週金曜日、15時に自動で自分のOutlookへメール送信設定をおこなった。
下記作成画面コピー。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2494868/9fb39323-b73a-b5cf-ab23-40c873c5cfeb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2494868/1ea1381b-0a3c-35ba-6aae-db7d3a01a5a1.png)


テストの実施を行ったらみごとメール送信完了。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2494868/24486dd3-8579-c956-0b4e-e9a062eb7aa2.png)



メッセージ送信成功！！

初めて作成して、動作完了確認できてすごくうれしい！


　【使用ツール】
・PowerApps
・Outlook

【難しかったところ】
機械音痴な私でも比較的簡単に作成できた。
ただ、初めのほうはアカウントのログインが連携したいものでなかったりしたため、うまくいかなかった。そのためログイン情報の確認という初歩的なところから見直すなどして気を付ける。

【今後に向けて】
現在、契約期間がバラバラなものを12社分管理している。契約期間1ヵ月前に、担当者にお知らせメールを行うフローをエクセル連携などして作成してみたい。
pythonのlistに、先頭inseart、終端にinseart、classもinseartしてみた際の備忘メモ

pythonのlistに、先頭inseart、終端にinseart、classもinseartしてみた際の備忘メモです。
（listはアクセスにO(N)の計算量が掛かるようなので、配列サイズが大きい場合はdeque等を使う事をおすすめします。ここではN=1000未満の大きさを扱うことを想定）

```python:test_list.py
l=[]

### 先ずは先頭にinsertしてみる
l.insert(0, 1)
l.insert(0, 2)
l.insert(0, 3)

# print
print("--- print")
print(l)

# pop
print("--- pop")
print(l.pop(0))
print(l.pop(0))
print(l.pop(0))
print(l)
l.clear()


### 次に、終端にinsertしてみる
l.insert(len(l), 1)
l.insert(len(l), 2)
l.insert(len(l), 3)

# print
print("--- print")
print(l)
for i in range(len(l)):
    print(l[i])
l.clear()


### classをいれてみる
print("--- class")
class Point:
  def __init__(self, x, y):
    self._x = x
    self._y = y
    
  def output(self):
    print('Point(%d, %d)' % (self._x, self._y))

P1 = Point(1,1)
P2 = Point(2,2)
P3 = Point(3,3)
l.insert(len(l), P1)
l.insert(len(l), P2)
l.insert(len(l), P3)
print(l)

# popしてみる
PP1 = l.pop(0)
PP2 = l.pop(0)
PP3 = l.pop(0)
print(PP1._x, PP1._y)
print(PP2._x, PP2._y)
print(PP3._x, PP3._y)
```

実行する

```
python test_list.py
--- print
[3, 2, 1]
--- pop
3
2
1
[]
--- print
[1, 2, 3]
1
2
3
--- class
[<__main__.Point object at 0x10acfc278>, <__main__.Point object at 0x10acfc2e8>, <__main__.Point object at 0x10acfc320>]
1 1
2 2
3 3
```

# 参考
[Pythonのデータが「deque」の使い方](https://qiita.com/ryosuke0825/items/bbc5c0673e6c6c958d66)
[dequeから範囲を指定して値を取得](https://teratail.com/questions/172345)
[Pythonで各要素にO(1)でランダムアクセスできるdeque(両端キュー)を書いてみた](https://prd-xxx.hateblo.jp/entry/2020/02/07/114818)
Git user.nameとかuser.emailを設定する前にコミットしてしまった場合の回避策（未pushの場合）

# 概要

- Gitにてuser.nameとかuser.emailを設定せずコミットしてしまった時の対処法をメモ的にまとめる

# ご注意

- 下記の方法はリモートリポジトリへ内容を反映する前だけ有効です。
- pushしちゃった後はこの方法ではだめです。
- この記事は参考文献の湊川 あいさんの記事を元にしております。当該の参考文献の内容のほうがわかりやすいです。

# 方法

1. 当該のローカルリポジトリにてuser.nameとuser.emailを設定する。
1. 下記コマンドを実行して直前のコミットをなかったことに（ステージングエリアに戻す）

    ```terminal
    $ git reset --soft HEAD^
    ```

1. 下記コマンドを実行して再度コミットを行う。

    ```terminal
    $ git commit 
    ```

# 参考文献

- [第6話 git reset 3種類をどこよりもわかりやすい図解で解説！【連載】マンガでわかるGit ～コマンド編～](https://www.r-staffing.co.jp/engineer/entry/20191129_1)
新しくモジュールを作ったときにbuild.gradleを3行で済まし、カスタマイズをDSLで行う1

:warning: この記事の方法はモチベーションや仕組みの話としては問題ありませんが、カスタマイズの部分がうまく動かないので、以下を参考にしてください。 :warning: 

https://qiita.com/takahirom/items/0e95d1c1eb6de4f01b0c

これはGradleのプロジェクト全般で利用できると思います。

AndroidやKotlin Multiplatformの開発でたくさんモジュール作って開発していると、毎回build.gradleをレビューしたりとか大変ですよね？

例えばAndroidだと以下のような長い定型文を書く必要があります。

```kotlin
plugins {
    id("com.android.library")
    id("org.jetbrains.kotlin.android")
}

android {
    compileSdk = 32

    defaultConfig {
        minSdk = 21
        targetSdk = 32

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles("consumer-rules.pro")
    }
...
// ながい。。
```

build.gradle.ktsやbuild.gradleでは以下だけ書けばよくしたいですよね？

```kotlin
plugins {
    id("my.custom.library")
}
```

あと例えばあるモジュールではJetpack Composeというライブラリが必要とか、カスタマイズが必要なときはDSLで設定すればいいだけにしたいですよね

```kotlin
plugins {
    id("my.custom.library")
}

myCustomExtension {
    useCompose.set(true)
}
```

**この記事ではPrecompiled script pluginsによる方法を紹介します。**

https://docs.gradle.org/current/userguide/custom_plugins.html#sec:precompiled_plugins

といってもすごく簡単です。

## Precompiled script pluginsによる実装方法

ここにコードはおいてあります。

https://github.com/takahirom/android-gradle-plugin-common-logic-sample

```kotlin:buildSrc/build.gradle.kts
plugins {
    `kotlin-dsl`
}
repositories {
    google()
    mavenCentral()
    gradlePluginPortal()
}

// rootのclassspassで書いていたものをここに書く
dependencies {
    implementation("com.android.tools.build:gradle:7.1.0-rc01")
    implementation("com.android.tools.build:gradle-api:7.1.0-rc01")
    implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31")
    testImplementation("junit:junit:4.13")
}
```

```kotlin:buildSrc/src/main/kotlin/my.custom.library.gradle.kts

// プラグインを普通に適応
plugins {
    id("com.android.library")
    id("org.jetbrains.kotlin.android")
}

// カスタマイズしたいもののextensionを書く
abstract class MyCustomPluginExtension {
    abstract val useCompose: Property<Boolean>

    init {
        useCompose.convention(false)
    }
}

// extensionを使えるようにする
val extension = project.extensions.create<MyCustomPluginExtension>("myCustomExtension")

// 普通にAndroidのブロックを書く
android {
    compileSdk = 32

    defaultConfig {
        minSdk = 21
...
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    buildFeatures {
        // extensionの値を使う
        compose = extension.useCompose.get()
    }
}

dependencies {
    implementation("androidx.core:core-ktx:1.7.0")
    implementation("androidx.appcompat:appcompat:1.3.0")
    implementation("com.google.android.material:material:1.4.0")
...
}
```

基本的には書きたいものをbuildSrcの下にファイル名を気をつけて置くだけでした。特殊な記法などを使う必要がなく、思ったよりかんたんでした。

そこまでこの仕組みに詳しくはないのでなにかツッコミどころなどありましたら教えて下さい :pray:
Pythonで処理に時間がかかっているコード行を特定する

>
> 自分用メモ
>

### 1. コードにライブラリをインポートする

```py
from cProfile import Profile
# コードエディタに記述する
```

### 2. ターミナルでコマンド実行する

```sh
$ python3 -m cProfile sample.py

> 248 function calls (247 primitive calls) in 3.079 seconds
> Ordered by: standard name
> ncalls  tottime  percall  cumtime  percall filename:lineno(function)
> 1       0.000    0.000    3.079    3.079   sample.py:2(<module>)

```
PHPExcelとPhpSpreadsheetの比較



PHPでのExcel操作に関し、PHPExcelとPhpSpreadsheetを比較したので覚え書き。

## 概要

### 共通点

- いずれも[PHPOffice](https://github.com/PHPOffice)シリーズのひとつ
- スプレッドシートファイルフォーマットの読み込み/書き込みができるライブラリ

### [PHPExcel](https://github.com/PHPOffice/PHPExcel)

- 2015年に最終バージョン1.8.1をリリースした後、2017年非推奨 →　2019年にアーカイブされた

### [PhpSpreadsheet](https://github.com/PHPOffice/PhpSpreadsheet)

- PHPExcelの後継で、互換性はなく、品質がよくなっている
- 名前にSpreadsheetとあるが、Excelファイルの操作も可能

## 比較

表でその違いを比較してみました。

|  | PHPExcel | PhpSpreadsheet |
| ---- | ---- | ---- |
| リポジトリ | https://github.com/PHPOffice/PHPExcel | https://github.com/PHPOffice/PhpSpreadsheet |
| PHPのバージョン | 5.2以上<br/>（[changelog.txt](https://github.com/PHPOffice/PHPExcel/blob/1.8/changelog.txt)の内容から、～5.6と思われる） | 7.3以上<br/> （2022/01/23現在:PHP対象バージョンのサポート終了後6ヶ月までメンテナンスされる） |
| ドキュメント | [概要](https://github.com/PHPOffice/PHPExcel/tree/1.8/Documentation/markdown/Overview)<br/>[サンプルコード](https://github.com/PHPOffice/PHPExcel/tree/1.8/Examples) | https://phpspreadsheet.readthedocs.io/en/latest/ |
|対象ファイル（読み）|BIFF 5-8 (.xls) Excel 95とそれ以上のバージョン<br/>Office Open XML (.xlsx) Excel 2007とそれ以上のバージョン<br/>SpreadsheetML (.xml) Excel 2003<br/>Open Document Format/OASIS (.ods)<br/>Gnumeric<br/>HTML<br/>SYLK<br/>CSV|BIFF 5 (.xls) Excel 95<br/>BIFF 8 (.xls) Excel 97とそれ以上のバージョン<br/>Office Open XML (.xlsx) Excel 2007とそれ以上のバージョン<br/>SpreadsheetML (.xml) Excel 2003<br/>Open Document Format/OASIS (.ods)<br/>Gnumeric<br/>HTML<br/>SYLK<br/>CSV |
|対象ファイル（書き）|BIFF 8 (.xls) Excel 95とそれ以上のバージョン<br/>Office Open XML (.xlsx) Excel 2007とそれ以上のバージョン<br/>HTML<br/>CSV<br/>PDF|BIFF 8 (.xls) Excel 97とそれ以上のバージョン<br/>Office Open XML (.xlsx) Excel 2007とそれ以上のバージョン<br/>Open Document Format/OASIS (.ods)<br/>HTML<br/>CSV<br/>PDF|

## まとめ

原則PhpSpreadsheetを使うべきだが、動作環境のPHPのバージョンや読み書きしたいファイルフォーマットのバージョンによっては、PHPExcelにせざるを得ない場合がある（現動作環境、そうせざるを得ないので非常に歯がゆいです・・）
身近な課題の自動化に挑戦 Power Automate Desktopで社内データベース(IBM i)にクエリを送信する

私が働く会社では、朝の定形業務として社内の物流系データベース(IBM i)にクエリを送信しデータを抽出するルーティンワークが多数転がっています。クエリを送信する部分はシステム内の機能にあるマクロで自動化はできますが、システムの起動～サイン・オンの部分の自動化はできていませんでした。最近RPAでの自動化に向けた機運が社内で高まってることもあり、Power Automate Desktopを利用してシステム起動～クエリ送信までを一気通貫で自動化し今後のRPA推進に役立てようと考えました。

#そもそもIBM iとは。
>IBM i(アイ・ビー・エム アイ)は、IBM Power Systems(旧・AS/400)及び、IBM PureSystemsに搭載されているオペレーティングシステムである。1988年にIBMのミッドレンジコンピュータ向けに開発されたOSであり、かつてはOS/400、i5/OSと呼ばれていたが、2008年にIBM iに改称した。
引用元:https://ja.wikipedia.org/wiki/IBM_i
<img width="600" alt="A/S400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491573/ca0db605-bd31-7882-f55e-4042a0c2280b.png">

#使用アプリケーション
* Power Automate Desktop
* IBM i Access Client Solutions

https://powerautomate.microsoft.com/ja-jp/desktop/

#フロー全体
![Flow2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491573/672832b9-f514-195b-9aea-11701625e76b.png)

#作業手順
## 1. アプリケーションの実行
C:\Automate\商品供給システム.hodを起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491573/dae317b7-8f92-6a11-1157-140f74596180.png)


## 2. システムへのサイン・オン
アプリケーションの実行後、下記のようなウインドウがシステムの立上げ前に表示され、
処理が完了されるまでサイン・オンの画面は表示されない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491573/c1a62d17-6245-9cb8-530c-30e87d227251.png)
そのため画像の待機を実行し赤枠部を画像として表示されるまでアクションを待機。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491573/78e6e5a9-3d6c-1318-0cdd-ea08114da815.png)
この段階ではシステムのウインドウにフォーカスされていないため、ウインドウにフォーカス。
<img width="500" alt="A/S400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491573/ca0db605-bd31-7882-f55e-4042a0c2280b.png">
文字が入力される位置は起動時に、ユーザーIDの入力位置に設定されている。
キー送信を実行しユーザーIDとパスワードを入力する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491573/ebe64591-76f5-50a7-1811-26fc7aa0a13a.png)


## 3.目的のメニュー番号の送信とクエリの送信
メニュー番号をキー送信しクエリ送信画面を開く。
クエリが記録されているエクセルを開き、ページ１への範囲をコピーし、システムにフォーカスを合わせる。
※クエリは下記のようにエクセルでA1-A12までにまとめている。
　現在は手動作業なのでクエリの区切りは視覚化している。(1ページ6行までしか貼り付けられないため)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491573/d0f9e717-8fc1-f65e-f909-f64b46ad2b97.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491573/457a07d2-fb90-3c04-8b97-53032c745d78.png)

キー送信で、貼付け初期位置まで移動、Ctrl + V(クエリを貼付け)、Pagedown次ページ。
再度エクセルへフォーカスし、ページ２への範囲をコピー、システムにフォーカスを合わせ、
キー送信、Ctrl + V(クエリを貼付け)、Returnでクエリを送信する。

#まとめ
**成功はしたがPower Automate Desktopを使った自動化が正しいアプローチかは疑問が残る形となった。アプリケーションの特性上、処理の切り替わりに対しUI要素を利用することができず、次の処理までの待機は画像認識で画面の切り替わりを認識させる必要があったため自動化自体もかなり手間が掛かった。また、他のメニュー番号では後から打たれたクエリが優先されることもあり、根本的なシステム改善をしないと手放しで使える自動化にはならなかった。**
MacにGolangをasdfでインストールする

# はじめに
こんにちは。最近業務で使用するPCでMacbookを支給されてたWindows勢です。絶賛ショートカットを暗記中です:bow:

さて、今回はasdfでgolangをインストールしていこうと思います！

## 前提
1. asdfはインストール済み.

# MacにGolangをasdfでインストールする

asdfにgolangのプラグインを追加します.

```console
$ asdf plugin-add golang https://github.com/kennyp/asdf-golang.git
```

そしたらお好きなバージョンをインストールします:ok_hand:

今回は最新を入れます。

```console
$ asdf install golang latest
```

あとはglobalに設定して終わりです。

```console
$ asdf global golang latest
```

バージョンを確認します。

```console
$ go version

go version go1.17.6 darwin/amd64
```

# おわりに
無事インストールできました:ok_hand:

参考になりましたら幸いです！
Vue.js入門　Vue.jsでゲームを作る


# 理由・背景

Vue.jsを業務で使うことになったので学び中。
チュートリアルをたどってゲームを作りました。
少し改造しようと思ったけど作りが思ったのと違ったのでそのままです。

# やって見て

動画の主が歯切れよく進行するので飽きずに作ることができた。

# 元にした動画

https://www.youtube.com/watch?v=WjfpQlVem-8&list=PL4cUxeGkcC9gQcYgjhBoeQH7wiAyZNrYa&index=14&t=249s

## 構造

Basicフォルダ
- img
- app.js
- inde.html
- style.css

## コード

```javascript:app.js
Vue.component('greeting', {
    template: '<p>Hey there, I am a re-usable component</p>'
});

/* new Vue({
    el: '.test',
    template: '<p>I am a template</p>'
}); */

new Vue({
    el: '#vue-app',
    data:{
        health:100,
        ended:false
    },

    methods:{
        punch: function(){
            this.health -= 10;
            if (this.health <= 0){
                this.ended = true;
            }
        },
        restart: function(){
            this.health = 100;
            this.ended = false;
        }
    },
    computed:{
    }
});
```

```html:index.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>VueJS Tutorials</title>
        <link href="styles.css" rel="stylesheet" />
        <script src="https://unpkg.com/vue"></script>
    </head>
    <body>
        <div id="vue-app">
            <!-- bag image -->
            <div id="bag" v-bind:class="{burst:ended}"></div>
            <!-- bag health -->
            <div id="bag-health">
                <div v-bind:style="{width:health + '%'}"></div>
            </div>
            <!-- game controls -->
            <div id="controls">
                <button v-on:click="punch" v-show="!ended">Punch</button>
                <button v-on:click="restart">Restart</button>
            </div>

        </div>

    <script src="app.js"></script>
    </body>
</html>
```

```css:style.css
#bag{
    width:200px;
    height:500px;
    margin: 0 auto;
    background: url(./img/bag.png) center no-repeat;
    background-size: 80%;
}

#bag.burst{
    background: url(./img/bag-burst.png) center no-repeat;
    background-size: 80%;
}

#bag-health{
    width:200px;
    border: 2px solid #000;
    margin: 0 auto 20px auto;
}

#bag-health div{
    height:20px;
    background:crimson;
}

#controls{
    width:120px;
    margin:0 auto;
}
```

# 作成したゲームの画像
![スクリーンショット 2022-01-23 15.50.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271383/6ede9e0e-d9aa-8ce1-79de-8500ad55e434.png)
【PHP】 publicやprivateやアクセス修飾子ってなんぞや？疑問を解消してくれる記事

<h1>使い分ける際の判断基準を簡潔に。
<p>①値を変えたらだめなもの
②値を変えてもOKなもの

クラス(class)とは、言わば『設計書』。
繰り返し使う処理をまとめたものです。

<b>内部的に使う処理</b>は「private」にして<b>値を固定</b>にして、<font color="Red">外部からは変更できないようにします。</font>
(店で売っている商品の価格を消費者は自由に変えられない。)

<b>外部的に変更したい処理</b>は「public」にして<b>値を変動</b>できるようにして、<font color="Red">外部から変更できるようにします。</font>
(寿司の価格はprivateだけど、「刺身醤油とわさび」は自由に持って帰ってイイよ。個数は消費者に委ねるよ。って状態にする)



<h1>Publicとは？
<p>クラス内外問わず、どこからでもアクセス可能</p>

<h1>purotectedとは？
<p>そのクラスと子クラス(継承先のクラス)からのみアクセス可能

<h1>privateとは？

<p>そのクラス内でのみアクセス可能
型安全って(もくもく会でやったことアウトプット)

# 型

Python でも TypeScript のように型を定義というか注釈を行うことができる。
メリットとしては

- 可読性が上がる(関数において引数に何を入れるのか、戻り値は何を期待するのかがわかる)
- 評価を行う際に型安全を担保できる
- 実行前に型エラーを検出することでデバッグの手間を減らす

といったことが挙げられる。
ただし、python は動的型付け言語(実行時に型チェックを行う)なので`mypy`を入れないと厳密に検査はできない。

簡単な例。

```py
def add(x: int, y: int) -> int:
    return x + y
    # mypyを入れないと以下も実行できてしまう
    return 'terrible'

```

普通はやらないはずだがこういうやばいシチュエーションを未然に防げたりもする。

```py

class User:
    # 初期化とクラス変数定義
    def __init__(self, name: str)-> None:
        self.name: str = name
    # クラス変数の型を変えようとするやばい関数
    def change_name_type(self, id: int)-> None:
        self.name: int = id

if __name__ == '__main__':
    u: User = User("Takeshi")
    # やばい関数を実行しようとしてもIncompatible types in assignment (expression has type "int", variable has type "str")エラー
    u.change_name_type(1)
    print(type(u.name))


```

つまるところ

> 型はプログラムが構文的に正しくても式の意味が正しいかをチェックするための重要な要素

というところが肝なのである。
特に構文的に正しいことと意味として正しいかが必ずしもイコールではないという認識は私のようなひよっこには慣れないところ。
ちなみに構文的に正しいのを`well defined`といい、その狭義的な意味として`意味として正しい = well typed`なんていい方をするらしい。
意味として正しければ逆説的に構文的にも正しくなり得る……という理論ではあるが`well defined`と`well typed`とでは後者のほうが権限が強く、それは正しく定義されているけれど`well typed`ではないと見なされ弾かれてしまう問題がある。
こういうところを期待して型評価をやっているのだからいいのでは？ という疑問が当然出るが、それは`well typed`が完全であることが前提であるという話。
そもそも、`well typed`が万能であるなら Python のような動的型付けの言語は存在する理由の大きなところを喪失してしまう。
とはいえ、不正な動作をしない・可読性を上げるといった保証の担保のために型注釈を適切に行なって型安全を求めていこうという意識は重要であるということなのだろう。

## 最後に

業務に入ってからレビューで

- なぜ`split()`ではなく、`ast.literal_eval()`を使うのか？
- 速度的には`for()`のネストが早いのに`itertools.product()`を使うのか？

ということについて度々触れることがあり、その度に型を限定して安全に評価を行うことが大切ということを説かれました。
今回はその意味を自分の中で腹落ちさせるための回でした。

## 参考

[型安全性とは何か](https://postd.cc/what-is-type-safety/)
[Python で型検査しようぜ](https://kk-river108.hatenablog.com/entry/2019/03/10/163457)

## 番外

環境別に pip で管理しているライブラリのバージョンを分ける場合は venv で各環境作って pip install をしてそれぞれ base(共通ライブラリ)、production、local といったように分けて各環境の requirements に`-r base.txt`を仕込む。
あとは

```py

pip install -r production.txt # base.txtとproduction.txtのライブラリをインポート


```

とやれば環境ごとにライブラリのバージョンを別に管理できるようになる。
poetry とか使うとこのあたりは 1 ファイルで済むらしいが、venv が現状推奨されている環境ではありそうなのでこういったテクを覚えておきたいと思いました。

[実践例](https://github.com/cookiecutter/cookiecutter-django/tree/master/%7B%7Bcookiecutter.project_slug%7D%7D/requirements)
BGP概要ついてまとめてみました。

#はじめに
こんにちは、山田です。
今回は、BGPに概要ついて軽くまとめてみました。

#BGPとは
EGPはAS間で経路情報を交換するEGPである。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/828efbd7-e67f-93b0-44da-ef54c375cbac.png)

用語|概要|
---|---|
IGP|内部で使用するルーティングプロトコル|
EGP|外部で使用するルーティングプロトコル|
AS|ある管理組織にあるネットワークの集まり|
NOC(Network Operation Center)|ネットワークとネットワークを接続する。|
IX(Internet Exchange)|ネットワークの運用者や運用方針、利用方針が異なるネットワークを対等に接続するポイント。|
ISP(Internet Service Provider)|個人や会社などにインターネットへの接続を提供する会社。|]

##パスベクタ型ルーティングプロトコル
BGPは、パスベクタ型ルーティングプロトコル。
AS内のルート情報に付加された、パスアトリビュートを送信して最適経路を決める。デフォルトでは、ASが少ない経路をベストパスとして使用する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/0444b268-09f4-5b86-9992-d4700f03cb82.png)

上記の図だと、1.1.1.3をネクストホップとするASパスが、ベストパスになる。

##AS番号
BGPでは、インターネット上で各AS番号を識別するために番号を割り当てている。(AS番号)
主に下記の2種類がある。

|AS番号|AS番号の範囲|用途|
|---|---|---|
|グローバルAS番号|1 ～ 64511|インターネット全体で一意のAS番号|
|プライベートAS番号|64512 ～　65535|組織内部で自由に使用できるAS番号|

##メッセージと状態
BGPは4種類のメッセージをやり取り後、上記図記載のいずれかの状態になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/841872eb-336a-e66b-e51f-ca09f3eb52d4.png)

##IBGP,EBGP
BGPピア（BGPネイバー）にはIBGPピアとEBGPピアの2種類がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/bdcd2dfd-a8e7-0401-1d44-f8d1ad6ee605.png)
Webの勉強はじめてみた その24 〜テンプレートエンジン〜

N予備校の「プログラミング入門Webアプリ」を受講しています。
今回は第3章16節です。

<h2>テンプレートエンジン</h2>
:::note
テンプレートと文字列とプログラムを組み合わせることで、 静的なユーザーインタフェースのデータである HTML を動的に出力できるライブラリのこと
:::

静的なページに変数を入れてそれをベースにして動的なページにしようと言う認識。

<h2>PUGを使う</h2>

`Dockerfile`に記述

```Dockerfile
RUN yarn add pug@2.0.4
RUN yarn global add pug-cli
```

雛形となる`form.pug`

```pug
doctype html
html(lang="ja")
  head
    meta(charset="UTF-8")
    title アンケート
  body
    h1 どちらが食べたいですか？
    form(method="post" action=path)
      span 名前: 
      input(type="text" name="name")
      input(type="radio" name="favorite" value=firstItem)
      span #{firstItem} 
      input(type="radio" name="favorite" value=secondItem)
      span #{secondItem} 
      button(type="submit") 投稿
```

:::note warn
インデントを忘れると入れ子構造にならないので注意。
:::

文字列には`span`を使うか、`| 文字列`とする。
変数は、`#{変数名}`とする。

<h3>index.jsで動的なページにする。</h3>

```javascript
const pug = require('pug');
/**
 * アンケートの表示アイテムを変更する
 * @param {String} enURL アンケートURL
 * @param {Object} res HTTPレスポンス
 * @param {String} first アンケート内容1
 * @param {String} second アンケート内容2
 */
function enquetesChange(enURL, res, first, second){  
  res.write(pug.renderFile('./form.pug', {
    path: enURL,
    firstItem: first,
    secondItem: second
  }))  
}
```

`pug.renderFile`で`pug`ファイルがHTML形式に出力される。
`http.createServer`メソッド内で呼び出し。

```javascript
        const yaki_shabu = '/enquetes/yaki-shabu';
        const rice_bread = '/enquetes/rice-bread';
        const sushi_pizza = '/enquetes/sushi-pizza';

        switch(req.url){
          case yaki_shabu:
            enquetesChange(yaki_shabu, res, '焼肉', 'しゃぶしゃぶ');
            break;
          case rice_bread:
            enquetesChange(rice_bread, res, 'ごはん', 'パン');
            break;
          case sushi_pizza:
            enquetesChange(sushi_pizza, res, '寿司', 'ピザ');
          default:
            break;
        }                 
```

<h2>まとめ</h2>
例えば素のphpで書こうとするとちょっと面倒なところがかなり便利に書ける。
PUGってどれくらい使われてるんだろうか。
さて、次回はHerokuです。
formタグからGET, POSTされるとき何が起こっているのか

# はじめに
formタグのデータの扱いは、フレームワークがいろいろやってくれる部分ではあります。
例えば私が普段業務で使っているASP.NET Coreだと、コントローラー名やメソッド名をinputタグに属性として渡せば、どんなHTTPリクエストが送られているかなどはあまり意識しなくて済みます。

なので、根本的にはどうやってURIが作られ送信されているのか説明できませんでした。
私と同じような方のためになればと思いこの記事を書いています。

# formタグによるGET
以下のような書籍検索フォームがあるとします。
題名を入力して検索をかける仕様です。

```index.html
<form method="GET" action="http://example.jp/article">
    <label>題名：<input type="text" id="title" name="title"></label>
    <input type="submit" name="submit" value="検索">
</form>
```
formタグには、リクエストを送るために以下の二つの属性を指定する必要があります。

- method属性：HTTPメソッドを指定（GETかPOST）
- action属性：ターゲットとなるURIを指定

クエリパラメータの名前は、inputタグのid（上記の例ではtitle）になります。
したがって、id=titleのテキスト入力に"test-title"という文字列を入れて送信した場合、
http://example.jp/article?title=test-title というURIが生成されます。

ここで、サーバー側で著者名での検索処理が追加されたとします。
すると、クライアントはさらに著者名のパラメータをサーバーに渡す必要があります。
その場合、以下のようにformタグ中に新たにinputタグを追加することで対処します。

```index.html
<form method="GET" action="http://example.jp/article">
    <div><label>題名：<input type="text" id="title" name="title"></label></div>
    <div><label>著者：<input type="text" id="author" name="author"></label></div>
    <input type="submit" name="submit" value="検索">
</form>
```
id=titleのinputタグに"test-title"、id=authorのinputタグに"test-author"を入力して送信した場合、
http://example.jp/article?title=test-title&author=test-author というURIが生成されます。

このように、クライアントが入力した内容によってURIが生成されますが、
あくまでクライアントはサーバー側が用意するフォームに従ってURIを構築しています。

サーバー側の実装を変更して新たなクエリパラメータが必要になった場合でも、
フォームに新たなパラメータを埋め込むことで解決します。

# formタグによるPOST
aタグやlinkタグではGETしか送れませんが、formタグはPOSTも送ることができます。
formタグのmethod属性に、POSTを指定します。

```index.html
<form method="POST" action="http://example.jp/article">
    <div><label>題名：<input type="text" id="title" name="title"></label></div>
    <div><label>著者：<input type="text" id="author" name="author"></label></div>
    <input type="submit" name="submit" value="検索">
</form>
```
id=titleのinputタグに"test-title"、id=authorのinputタグに"test-author"を入力して送信した場合、
リクエストは以下のようになります。

```
POST /articleHTTP/1.1
Host: example.jp
ContentType: application/xwwwformurlencoded

title=test-title&author=test-author
```
リクエストメッセージのボディには、
application/xwwwformurlencodedの形式でフォームの内容が入っています。

# おわりに
基本に立ち返ることの重要性を実感する日々です。

# 参照
[Webを支える技術](https://www.amazon.co.jp/Web%E3%82%92%E6%94%AF%E3%81%88%E3%82%8B%E6%8A%80%E8%A1%93-HTTP%E3%80%81URI%E3%80%81HTML%E3%80%81%E3%81%9D%E3%81%97%E3%81%A6REST-WEB-PRESS-plus/dp/4774142042/ref=sr_1_1?adgrpid=102912038115&gclid=CjwKCAiAlrSPBhBaEiwAuLSDUDKhTT0zM2DU00UZ32QXw9FDB3C-Us2Wog5d8Zj4LEXHvB1QaBdFyBoCbuYQAvD_BwE&hvadid=556743317697&hvdev=c&hvlocphy=1009298&hvnetw=g&hvqmt=e&hvrand=3522719785153635406&hvtargid=kwd-394859824714&hydadcr=21894_13291924&jp-ad-ap=0&keywords=web+%E3%82%92+%E6%94%AF%E3%81%88%E3%82%8B+%E6%8A%80%E8%A1%93&qid=1643004410&sr=8-1)
備忘録：パーセントエンコーディング

# はじめに
DeepL APIを利用した翻訳を試していました。
公式ページによると、POSTリクエストのbodyにAuth Keyと翻訳したい文章を入力する様子。

```js
let text = "Hello, World"
let options = {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: 'auth_key=[authKey]&text=' + text + '&target_lang=JA'
  }
fetch('https://api-free.deepl.com/v2/translate', options)
  .then(response => response.json())
  .then(json => console.log(json.translations[0].text))
```

…あれ、&とか=を翻訳に含めたいときはどうすればいいんだ？
と分からなくなったのでググりました。

# 解決方法
`encodeURIComponent()`を使えばよかったらしい。

```js
let text = encodeURIComponent('Hello, World')
```

# テスト

```js
let rawText = 'hello & world'
let encondedText = encodeURIComponent(rawText)
let options = {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: 'auth_key=[authKey]&text=' + encondedText + '&target_lang=JA'
  }
fetch('https://api-free.deepl.com/v2/translate', options)
  .then(response => response.json())
  .then(json => console.log(json.translations[0].text))
// => ハロー＆ワールド
```
&が翻訳する文章として認識された。

# パーセントエンコーディング
HTTPリクエストのContent-Type:`application/x-www-form-urlencoded`はURLを解釈する時のルールであるらしい。
ここでは&や=はリクエスト内のname, valueペアを識別するための文字として使われる。
識別子としての意味を持たせず単なる文字列として&や=を扱いたいときは、それぞれ%26や%3Dに変換する必要がある。
この変換をパーセントエンコーディングという。
パーセントエンコーディングをJavaScriptで行うための関数が`encodeURIComponent()`。
似た関数に`encodeURI()`があるが、こちらはURL全体をエンコードする際に使われる。/などはエンコードされない。
今回のように、name=valueペアのnameかvalueのどちらかをエンコードする場合は`encodeURLComponent()`を使う。

# メモ
以下のようにURLのname=valueペアに+がある場合はスペースに変換される。

```
http://www.example.com/path/foo+bar/path?query+name=query+value
```

`encodeURLComponent()`を使う限りは+は%2Bに変換されている。
直接+が入ることはないので気にしなくてもよさそう。

https://stackoverflow.com/questions/2678551/when-should-space-be-encoded-to-plus-or-20
OGPジェネレータを作って「阿部寛のホームページ」をOGP対応してみた

# 阿部寛のホームページOGP
https://v1.ogp-gen.workers.dev/?url=http://abehiroshi.la.coocan.jp/

# 作ったもの
https://v1.ogp-gen.workers.dev/



# 作ろうと思ったきっかけ
最近の外部ページへのリンクはOGPが当たり前になってきていて
OGPがないURLのみの文字列は危険な感じがしていると思ったからです
まだ古いサイトなどはOGP対応していないところが多い感じです
ただ、OGP対応も面倒でOGPの画像を用意してmetaタグに設定しないといけかったり結構な重労働です
その問題を払拭すべく、このサービスを作りました


# 技術スタック
- フロントエンド
Vue.js

- バックエンド
Firebase
RealtimeDatabase 
python
CloudFlare Worker
WebNium

https://qiita.com/HawkClaws/items/48ab209b9cf1a7fcf073



#処理フロー
１．CloudFlare Worker
（最初にアクセスされる場所）
２．WebNium
（パラメータにurlがある、かつOGP画像作成済みではない場合、サイトのキャプチャを取得しStorageに保存）
３．CloudFlare Worker
（作成したOGP画像のURLをSSRしたものを返す）

#なんでCloudFlare Worker使ってるの？
処理フローに一応書いてありますが
SSRするためです
FirebaseHostingは静的ファイルしかホスティング出来ず
SPAだとmetaタグを書き換えたとしてもjavascript読み込んでくれない系のサービスだと
metaタグが書き換わらず、OGP情報が設定できないためです

###なんでCloud Functions使わないの？
クレカ登録とかが嫌な感じだからです
従量課金制でいつの間にかクラウド破産とかしたくないからです

以上。
Docker docker composeで管理しているDockerfileやdocker-compose.ymlを更新した後にやること

# 概要

- Dockerfileやdocker-compose.ymlに変更を加えた時に実施することをメモ的にまとめる

# やること

- 下記コマンドを実行してイメージの再取得と再ビルドを行いながらコンテナを起動する。

    ```terminal
    $ docker-compose up -d --build
    ```
Nodeのメンテナンスとkubectl drain コマンドについて

## Maintenance

クラスターの一部のノードで、ソフトウェアのアップグレードや、セキュリティパッチを適用させたい場合など、メンテナンスでノードを停止させたい場面が出てくる。

そこで、Node内のPodを、一時的に別のNodeに退避させたり、スケジューラの対象から外したりすることで、メンテナンスを行う。

## kubectl cordonとdrain

![スクリーンショット 2022-01-23 14.20.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/413ff071-715a-de17-209f-166ea35f78ff.png)

### kubectl drain

該当のNodeで、Podをスケジュールさせることはできない。
Podを他のNodeに移動させたあと、その間にNodeを再起動させたり、メンテナンスをする。
ただ、調べた感じ、使用シーンとしては、他のNodeに退避させて、その間にメンテナンスと言うよりは、Graceful Shutdownを実現するために使われているような印象を受けました。

![スクリーンショット 2022-01-23 14.25.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/28efefa0-b663-4e6e-8806-a58e5b1f7396.png)

```
参考
https://kubernetes.io/ja/docs/tasks/run-application/run-replicated-stateful-application/#%E3%83%8E%E3%83%BC%E3%83%89%E3%82%92drain%E3%81%99%E3%82%8B
https://kubernetes.io/ja/docs/concepts/scheduling-eviction/_print/#node%E3%81%AE%E9%9A%94%E9%9B%A2%E3%82%84%E5%88%B6%E9%99%90
```

### kubectl cordon

既存のノード上のPodは終了したり、移動しない。余分なポッドがノードに追加されるのを防ぐ。
ノードが cordon された後は、新しいポッドをそのノードにスケジュールすることはできない。
該当のNodeで、新しいPodはスケジュールされず、既存のPodは動き続ける。

![スクリーンショット 2022-01-23 14.54.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/19358175-7a84-47dc-a789-8865dd297d5c.png)


## kubectl drainの挙動

ノード上で実行している全てのPodを退避させる排出処理（drain）を行うには、kubectl drainを使う。

ノードが排出処理を開始すると、ノードをSchedulingDiasabledに変更してから、各Podに対してSIGTERMシグナルを送信し、Podを退避させる。

排出処理を開始すると、停止可能なPodは退避処理(Eviction)が行われる。

また、排出処理にはそれ以降のスケジューリング候補から除外する機能も含まれているため、前もってkubectl cordonで、指定したNodeにスケジュールさせないよう、実行する必要もない。

例えばこんな感じ。

まず、ポッドを確認。

```
root@controlplane:~# kubectl get pods -o wide
NAME   READY   STATUS    RESTARTS   AGE     IP  NODE     NOMINATED NODE   READINESS GATES
aws1   1/1     Running   0          3m24s   xx  node01   <none>           <none>
aws2   1/1     Running   0          3m24s   xx  node01   <none>           <none>
aws3   1/1     Running   0          3m24s   xx  node01   <none>           <none>
```

drain実行。

```
root@controlplane:~# kubectl drain node01 --ignore-daemonsets 
node/node01 cordoned
WARNING: ignoring DaemonSet-managed Pods: 
kube-system/kube-flannel-ds-hoge, kube-system/kube-proxy-fuga
evicting pod default/aws1
evicting pod default/aws2
evicting pod default/aws3
pod/aws1 evicted
pod/aws2 evicted
pod/aws3 evicted
node/node01 evicted
```

PodがEvictedされている。

## 参考

```
https://networkandcode.wordpress.com/2019/10/10/kubernetes-nodes-drain-or-cordon-nodes/
https://intl.cloud.tencent.com/document/product/457/30654
https://cloud.google.com/kubernetes-engine/docs/tutorials/migrating-node-pool
https://qiita.com/toshihirock/items/d22fee20b1a561b9efea
https://qiita.com/tkusumi/items/946b0f31931d21a78058
https://www.mtioutput.com/entry/2020/06/21/000000
https://www.udemy.com/course/certified-kubernetes-administrator-with-practice-tests/
```

参考にさせていただきました。ありがとうございます。
ruby on rails アセットパイプライン

## はじめに
ruby on rails チュートリアルを学習中
初学者

## アセットパイプラインとは
簡単に言えば複数のファイルを一つにまとめるための機能
scssを最終的に1つのcssにまとめる等
今では多くの言語でファイルをバンドルしているが、ruby on railsにアセットパイプラインが追加されたのをきっかけに
多くの言語やFWで取り入れられたらしい。

## Railsでのアセットパイプライン
**理解するべきこと3つ**

- アセットディレクトリ
- マニフェストファイル
- プリプロセッサエンジン

### アセットディレクトリ
アセット(画像やcss(scss))の置き場所
railsの場合`app/assets`に`stylesheetsやimagesディレクトリ`がある
`sample.svg`を保存する場合
`app/assets/images/sample.svg`となる
画像やcssの置き場所を固定することで、開発者間での違いをなくすことができ、開発効率や保守性を上げることができる

### マニフェストファイル
静的ファイル(アセット)をどのように1つのファイルにまとめるのかをRailsに指示する。
実際に1つのファイルにまとめる処理を行うのは`Sprockets`というgem

`app/stylesheets/application.css`はアプリケーション固有のCSS用マニフェストファイル

```css
/*
 * This is a manifest file that'll be compiled into application.css, which will
 * include all the files listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any
 * plugin's vendor/assets/stylesheets directory can be referenced here using a
 * relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at
 * the bottom of the compiled file so the styles you add here take precedence
 * over styles defined in any other CSS/SCSS files in this directory. Styles in
 * this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *
 *= require_tree .
 *= require_self
 */
```

### プリプロセッサエンジン
アセットに対してプリプロセッサエンジンを介して様々な処理を実行し、ブラウザに配信できるよう結合する
erbに対する処理
scssに対する処理など

## 3つまとめて

- アセットディレクトリ
- マニフェストファイル
- プリプロセッサエンジン

の3つが影響しあってアセットパイプラインは実現されている
基本的にはアセットディレクトリにアセットを追加すればrailsがよしなに処理をしてくれる
Lintエラー React Hook "useState" is called in function "" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use".の対処

Reactでコードを書いていたらタイトルのようなエラーが出て、対処に苦戦したのでメモ。

```
React Hook "useState" is called in function "signup" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use".
```

DeeLで翻訳をかけてみると下記のような結果が返ってきました。

```
React Hook "useState" は関数 "signup" の中で呼び出されていますが、これは React 関数コンポーネントでもなければ、React Hook のカスタム関数でもありません。Reactコンポーネント名は大文字で始める必要があります。React Hookの名前は、"use "という単語で始まる必要があります。
```

どうやらReactではコンポーネントの命名で大文字を使用しないといけないルールが存在するようです。

```react
export default function signup() {}
```

従来は上記のように記述していました。

下記のように修正した結果lintエラーが修正されました。

```react
export default function Signup() {}
```

コンポーネント名の最初の文字を大文字にすることでエラーを解決することができます
中学生のみなさんへ。「2022年共通テスト数学ⅡB問題2 [1]」３次関数のグラフの概形を選択する問題にチャレンジしてみて下さい 。

**解答を見る前に、
 まず問題をじっくり見てから、下の別解も見て下さい。**


#問題2[1]:

https://cdn.mainichi.jp/item/jp/etc/kyotsu-2022/pdf/MTBP.pdf#page=10

#解答＜毎日新聞#
https://mainichi.jp/exam/kyotsu-2022

解答＜youtube

https://youtu.be/f6fEOmY6NZA



#WolframAlpha で

一番下に答えがでていました。

https://ja.wolframalpha.com/input/?i=x**3-6x%2B16

(途中)

#Pycharmで:「一定の手順に従って数学的に処理する(問題作成方針 )」に準拠しているコード

(途中)

#Pycharmで:「一定の手順に従って数学的に処理する(問題作成方針 )」に違反しているコード



(途中)

# 別解1

ポイントは、グラフ0とグラフ1とグラフ2を重ねたグラフをイメージするだけです。

解説は読まなくてもーです。
6つのグラフの違いを見ると、上の3つのグラフをそれぞれ、y軸を対称に反転すると、下のグラフになります。
グラフの傾きは、式より、xの値がかなり?大きくなると、yの値も大きくなります。
グラフは、012に絞られます。グラフ345になりません。

3本の線を重ねた1つのグラフからなら、簡単です。
a正,a零,a負にあてはめるだけです。

3本を比較してみます。
範囲として、xの値が正の場合のみ考えます。y軸より右側だけみます。左側はみません。

a=0の線の場合が、まん中になります。
a<0の線の場合は、a=0の線よりabs(6ax) 上です。絶対値です。
a>0の線の場合は、a=0の線よりabs(6ax) 下です。右下がりの傾きが発生してから、右上がりです。

a=0の場合の線は、グラフ1
a<0の場合の線は、グラフ0



# 別解2

値を代入した方が、もっとはやい。

```
**は累乗です
a= 0,y=x**3    +16 : x=1の時、y=19
a=-1,y=x**3+6*x+16 : x=1の時、y=23
a= 1,y=x**3-6*x+16 : x=1の時、y=11
```

11と19と23を比較すると、
a=0の場合の線は、グラフ1
a<0の場合の線は、グラフ0

#続く

続きの問題は、みなさんもできるような気がしましたが、わかりませでした。

私は、みなさんの使っている何年生の教科書・参考書を勉強するといいかわかりませでした。勉強が必要ですね。教えて下さい。

differential calculus や 傾きについて、興味があれば、
**周りの高校3年生のやさしいおにいさん、おねえさんたちに聞いてください。**
数学ⅡBなので、高校生2年生のおにいさんおねえさんでした。

# 参考

予定のタイトル:(微分積分)「2021年共通テスト数学ⅡB問題2[1]」 をWolframAlpha とsympyでやってみたい


**数学共通テストの5対策**
**1:表現「実数」を疑う。**
**2:数字「13」を疑う。**
**3:式の順番①②を疑う。**
**4:(2)を別の問題とみない。**
**5:問題文の一字一句を大切にして下さい。**


https://qiita.com/mrrclb48z/items/7c16cb5141a495bc5307
EC-cube4 Controllerのカスタマイズで404エラーを解決（備忘録）

https://doc4.ec-cube.net/customize_controller

上記のサイトで記述通りに実装したが、404エラーが発生しました。

原因：キャッシュが残っていたこと

解決法：「/var/cache/prod」フォルダの中身を全て削除して、再度キャッシュを作成するようにする

上記の方法でサンプルページを表示することができました。

また、.env ファイルにて、APP_DEBUG=1とすることでキャッシュを残さない設定にできる
SQL

SELECT（データの検索）
INSERT（データの追加）
UPDATE（データの更新）
DELETE（データの削除）

【テーブル作成】
CREATE TABLE テーブル名(
　　　カラム名　データ型　制約,
　　　カラム名　データ型　制約,
　　　カラム名　データ型　制約,
　　　カラム名　データ型　制約,
)DEFAULT CHARSET=utf8mb4

【テーブル削除】
DROP TABLE テーブル名;

【行を削除】
DELETE FROM test_table WHERE id = 1;

【テーブルを表示】
SHOW TABLES;

【テーブルのカラム一覧表示】
SHOW COLUMNS FROM テーブル名;
Herokuコマンド

＜よく使うコマンド＞
・heroku open
・heroku config
・git remote set-url heroku https://git.heroku.com/アプリ名.git
　　//紐づけ変更
・git remote -v
・heroku logs
・heroku restart web.1
・heroku restart

（デプロイ手順）
・heroku login　　　//Herokuログイン

・heroku container:login　　　//Herokuコンテナログイン

・chmod +x docker/app/run-apache2.sh　　　//権限付与

・heroku create　　　//アプリ作成

・heroku container:push web　　　//コンテナプッシュ

・heroku container:release web　　　//コンテナリリース

（データベースと接続）
・heroku addons:create cleardb:ignite　　　//curiadbをインストール

・heroku config | grep CLEARDB_DATABASE_URL　　　//環境変数の取得、設定
　・heroku config:add DB_USERNAME=～
　・heroku config:add DB_PASSWORD=～
　・heroku config:add DB_HOST=～
　・heroku config:add DB_DATABASE=～

・heroku config　　　//環境変数設定の確認

・heroku container:push web　　　//プッシュ

・heroku container:release web　　　//リリース

・heroku open　　　//サイトオープン

・heroku pg:reset DATABASE　　　//データベース削除
Raspberry Pi Imager で WiFi の設定をする

Raspberry Pi の OS をインストールするのに [Raspberry Pi Imager](https://www.raspberrypi.com/software/) は便利ですが Ctrl + Shift + x を押すと Wifi の設定などができるようです。知らなかった。。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360970/2f52a3b2-9aa0-eba6-b327-4c494cc38bd6.png)

追記 (2022/2/4): v1.7.1 で　Raspberry Pi OS を選ぶと右下に歯車のアイコンが出るので Ctrl + Shift + X ではなくこのアイコンをクリックしても同様の設定が可能になったようです。

![screenshot2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360970/1c43ce0e-c568-4025-3be8-114bc9dc2942.png)

参照: [How To Configure WiFi on Raspberry Pi: Step By Step Tutorial](https://www.seeedstudio.com/blog/2021/01/25/three-methods-to-configure-raspberry-pi-wifi/)
身近な課題の自動化に挑戦 Power Automate DesktopでVPN接続の自動化に挑戦したが失敗した

テレワーク時に社内イントラに接続したい場合、VPNを利用しなければならない。
毎日手動接続も億劫なのでPower Automate Desktopで作業の自動化に挑戦してみてみました。
結果は失敗に終わりましたが、ツールで自動化可能な範囲が少し見えてきました。

#結果
**windowsセキュリティウインドウへのキーの送信が動作せず断念**

#使用したRPAツール
* Power Automate Desktop

https://powerautomate.microsoft.com/ja-jp/desktop/

#作成したフロー
![Flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491573/c7fff7fe-2a0d-7155-a086-ad7e53ceccf9.png)

#手順
##Cisco AnyConnect
![Cisco.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491573/5b496149-a7fc-acd1-d271-99f52f0af19a.png)

* Cisco AnyConnectを起動(以下AnyConeect)
* AnyConnectが起動するまで待機
* AnyConnectが起動したらフォーカスを合わせる
* AnyConnectのConeectボタンをクリック

##windowsセキュリティウインドウ①
![winsec1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491573/8cc7d3ea-ec6e-0d7a-75e5-d31ba46d6579.png)

* windowsセキュリティウインドウが起動するまで待機
* windowsセキュリティウインドウが起動したらフォーカスを合わせる
* windowsセキュリティウインドウの許可ボタンをクリック

##windowsセキュリティウインドウ②
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491573/4af658ff-2357-b67c-b27b-8ac8e9c95fbe.png)

* windowsセキュリティウインドウが起動したらフォーカスを合わせる
* windowsセキュリティウインドウでCtrl + Alt + Delを押す
**※ここが起動しない**

**うまく動かなかったアクション**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491573/f598a593-8fa1-648c-3fcd-1ac520c395bf.png)

###対応案 レコーダー機能を利用して作業を記録する
**記録された**
windowsセキュリティウインドウにフォーカスを合わせる(或いはUI要素を取得する)
**記録されなかった**
windowsセキュリティウインドウでCtrl + Alt + Delを押す
**結論**
windowsセキュリティウインドウに対してのキー送信はレコーダー機能で記録されない。

#まとめ
windowsセキュリティの画面に対しキー送信がうまくできず、自動化は失敗。
Power Automate Desktopで操作できない部分がwindowsの操作にはありそうだと考えてます。
今後はwindows側の設定へのアプローチも検討し、成功した際は記事を追加更新。
Gitコマンド

1,git init　　//ローカルリポジトリを作成

2,git add .　　//ステージに追加

3,git commit -m　　//ステージからローカルリポジトリへコミット

4,git remote app origin https://github.com/～
　　　　　　　//リモートリポジトリ新規追加

5,git push リモート名　ブランチ名
　git push origin master　
　 git push -u origin master

【コード一覧】
git init（初期化）

git clone アドレス     //リモリポからコピー

git add ファイル名     //変更選択

git commit -m  "メッセージ"      //コミット

git remote add Rリポ名 URL      //Rリポ登録

git push Rリポ名 master      //プッシュ

git pull Rリポ名 master      //プル

【確認】
git status　　//変更ファイル確認
git diff　　//ワークツリーとステージ間の変更確認
git log　　　//コミット記録確認
git log –oneline  　//一行で表示する
git log -p index.html　　　//ファイルの変更差分を表示
git log -n 5 　 //表示コミット数を制限
git log -p 　　　 //変更内容全確認
git rm ファイル　　//ファイルの完全削除
git rm -r ディレクトリ　　//ディレクトリ完全削除
git rm –cached ファイル名　　//ローカルリポジトリ内のみ削除

【移動】
git mv 旧ファイル名 新ファイル名
Shield Platform Encryption の設定と管理 トレイルヘッド


[Shield Platform Encryption の設定と管理](https://trailhead.salesforce.com/ja/content/learn/modules/spe_admins/spe_admins_set_up)


The Account Phone field isn't encrypted. Make sure you have records populated with data in this field.
何か入力しないといけないの？

よく分からんけど、ブラウザを更新してもチェックがつかない、
何度か更新したら機能した。

# i cant find my encryption policy even after creating a new trial

+ [i cant find my encryption policy even after creating a new trial](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000J7NKz)

:::note
Please check this article.

https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007ZAZH7SAP
:::

**You can't encrypt "Contact.FirstName", because it's used to filter records. To encrypt this field, in the flow "New Contact" stop filtering by "Contact.FirstName" in the "Find a Match" Get Records element.**
rustの連想配列の値部分にベクタを入れる方法

###概要
https://atcoder.jp/contests/abc235/tasks/abc235_c
を解く際に連想配列の値部分にベクタを入れたいがちょっと考えてあんまり思いつかなかったので
メモ

###連想配列とは
この辺参照
https://qiita.com/garkimasera/items/a6df4d1cd99bc5010a5e
今回の場合はhashmapもしくはbtreemap　のどちらかでよさそうです
違いはキーは大小の比較ができるもの、つまりOrdを実装している型である必要があります。ということだが
なんかよくわからん。ハッシュテーブル：メモリ大、早い　B木：メモリ小、遅い
くらいの気持ちでいればよいか。計算量がO(1)、O(logn)らしくどっちでも行けそうなので
B木でとりあえず実装してみる
###本題
というわけでbtreemapを使う。ハッシュテーブルでも行けそう。
やり方としてはキーをstring、値をベクタの型として BTreeMapを用意して
entryでキーを指定してinsertでベクタを呼び出す。値を追加したければpushしていけばよい


```rust
#![allow(unused)]
fn main() {
use std::collections::BTreeMap;

let mut map: BTreeMap<&str, Vec<usize>> = BTreeMap::new();
map.entry("1").or_insert(vec![0,1]);
map.entry("2").or_insert(vec![0,1]);
map.entry("3").or_insert(vec![0,1]);
println!("{:?}",map.entry("1").or_insert(vec![]));
///[0, 1]
map.entry("1").or_insert(vec![0,2]).push(4);
println!("{:?}",map.entry("1").or_insert(vec![]));
///[0, 1, 4]
println!("{:?}",map)
///{"1": [0, 1, 4], "2": [0, 1], "3": [0, 1]}

}
```

なかなか難しい。
LPIC向け基礎知識その１

##1.はじめに
この記事はLPICの試験範囲の中からグループ分けをした同じ分野の単語をまとめることで、自分の頭の中でごちゃ混ぜになっている知識を整理しつつ、しっかりと定着させていくことを目的としています。今回は基本的なディレクトリについてまとめます。
##2.ディレクトリ一覧

```:一般ユーザのホームディレクトリ(書き込み頻度が多い)
/home
```

```:後から追加したパッケージを格納(容量が大きくなることがある)
/opt
```

```:起動時にはいらないプログラム等を格納(読み込み頻度が多い)
/usr
```

```:可変ファイル群(ログファイルやメール等)を格納(書き込み頻度が多い)
/var
```

```:起動に必要なファイル(Linuxカーネル等)を格納
/boot
```

```:一時ファイルを格納
/temp
```

```:一般ユーザー用のコマンドを格納
/bin
```

```:デバイスファイルを格納
/dev
```

```:システム設定ファイルを格納
/etc
```

```:共有ライブラリを格納
/lib
```

```:管理者用のコマンドを格納
/sbin
```


##3.まとめ
もちろんディレクトリはここに記載しているもの以外にもたくさんありますが、LPIC対策として挙げられるのはこのあたりかと思いますのでディレクトリの紹介は以上とさせていただきます。「LPIC向け基礎知識」シリーズは基本的に今回のような書き方になる予定です。それでは次回もよろしくお願いします。
react-helmetを設定したらWarning: Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code.と怒られた

タイトルのまんま。

```SEO.tsx
// 普通に使ってたら怒られる
<Helmet>
 タイトルとか色んなメタタグとか 
</Helmet>
```

```
Warning: Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code.
```

このようにバグの可能性があると怒られてしまいます。
しばらくNextやGatsbyといったフレームワークを使っていてSEO周りであまり悩まなかったのでここら辺の情報はアップデートされていませんでした。

とりあえず解決策としてreact-helmet-asyncが見つかりました。（なぜか日本語情報はあまりない）

## react-helmet-async で解消
<a href="https://www.npmjs.com/package/react-helmet-async">npm - react-helmet-asynのページ</a>

----
DeepL翻訳

<quote>本パッケージは、React Helmetのフォークです。<Helmet> の使用法は同義ですが、サーバーとクライアントがリクエストごとに状態をカプセル化するために <HelmetProvider> を必要とするようになりました。

react-helmetはreact-side-effectに依存しており、これはスレッドセーフでありません。サーバーで非同期なことをする場合は、リクエストごとにデータをカプセル化するHelmetが必要で、このパッケージはまさにそれを実現します。</quote>

---
依存ライブラリのreact-side-effectに問題ありということですね。

## 導入

```公式.tsx
const app = (
  <HelmetProvider>
    <App>
      <Helmet>
        <title>Hello World</title>
        <link rel="canonical" href="https://www.tacobell.com/" />
      </Helmet>
      <h1>Hello World</h1>
    </App>
  </HelmetProvider>
);
```
公式だと二つのコンポーネントを挟むように書かれています。

HelmetProviderコンポーネント は Helmet を使用している全ての Route をラッピングしてあげるように設置。
Helmetコンポーネント は通常と同じようにしよう。

自分の場合は、rootとなるコンポーネント(index.tsx)へ HelmetProviderコンポーネント を設置して、SEO.tsxファイルの中へ Helmetコンポーネント を react-helmet と同様に設置しました。

## 無事にエラー解消
ヤッッッッッッタゼッッッッッッッッッ!!!!ｺﾞﾊﾝ ｵｲｼｲ ﾓｸﾞﾓｸﾞ
ソースのフルパスからファイル名を静的に取得

C++のプロジェクトで、ロガー等にソースファイル名を渡したい場合、定義済みマクロの`__FILE__`を渡すことが多いかと思います。

しかし`__FILE__`の実装は環境依存であり、私がネットで調べた限りでは殆どの環境でフルパス名でした。当方の環境MSVC(_MSC_VER==1930)のC++20もまた然りでした。

このフルパス名からファイル名だけを抜き出すマクロの作り方をネットで調べると、概ね下記のような実装が紹介されています。

```cpp
#define THIS_FILENAME (strrchr(__FILE__, '\\') ? strrchr( __FILE__, '\\' ) + 1 : __FILE__)
```

この方法でも問題なくファイル名の取得は出来るのですが、strrchr関数はコンパイル時評価が保証されていないため、実行の都度strrchrと条件分岐の判断が行われる可能性があります。
そこでフルパスからファイル名をコンパイル時に取得する方法を考えたので、拙劣ですが備忘録として記載します。以下はC++20のconsteval関数を使っております。

```cpp
// ソースファイルのフルパスの文字列リテラルからファイル名だけ抽出
consteval std::string_view ExtractSourceFileNameFromFullpath( const char* fpath )
{
	const std::string_view fname = fpath;
	const auto pos_delim = fname.find_last_of( '\\' );

//	const auto pos_fname = pos_delim != std::string::npos ? pos_delim - 1 : 0;
	const auto pos_fname = pos_delim != std::string::npos ? pos_delim + 1 : 0;
//  バグ修正2022/01/28
//  誤：pos_delim - 1
//  正：pos_delim + 1

	const auto	fn = std::string_view( 
		fname.data()   + pos_fname,
		fname.length() - pos_fname );
	return fn;
}
#define THIS_FILENAME ExtractSourceFileNameFromFullpath( __FILE__ ).data()
```

上記の関数は、引数fpath(ファイルのフルパス名)を受け取り、ファイル名の部分だけを参照するstring_viewを返します。その関数をマクロ`THIS_FILENAME`で置換します。
当初はconstexpr関数にしたのですが、当方の環境では静的評価しない場合があり、その条件が不明だったため、constevalにしたという経緯があります。条件さえ分かればconstexpr関数で問題ないかと思います。

更新履歴
2022/01/28 関数ExtractSourceFileNameFromFullpathのファイル名の先頭位置の計算が間違っておりました。これを修正しソース中にコメントを記述しました。大変失礼いたしました。
初めてTypeScriptでChrome拡張機能を作ったよ (Wordleネタバレ拡張機能)

なんとなくChrome拡張機能を作ってみたいな〜と思っていたので作ってみました。
意外と簡単で、1時間くらいで作れました。

## 作ったもの

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">wordleにアクセスしたら強制的にネタバレしてくるchrome拡張機能作った <a href="https://t.co/N1QEcINKMj">pic.twitter.com/N1QEcINKMj</a></p>&mdash; yoshii🐍 (@ganja_tuber) <a href="https://twitter.com/ganja_tuber/status/1485069400239915008?ref_src=twsrc%5Etfw">January 23, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

最近流行りの[Wordle](https://www.powerlanguage.co.uk/wordle/)で、答えを強制的に教えてくるおせっかいな拡張機能です。

## コード

以下に公開してます。

https://github.com/yoshiishunichi/wordle-extension

cloneして、`yarn install`してください。

## 環境

macです

## ディレクトリ構成

```
.
├── package.json
├── public
│   ├── image
│   │   └── icon.png
│   └── manifest.json
├── src
│   └── content.ts
├── tsconfig.json
├── webpack.config.js
└── yarn.lock
```

実行ファイルは、`src/content.ts`です。それ以外はテンプレをちょこちょこ変えただけです。

## 仕組み

どうやって答えを手に入れているかというと、
簡単な話で、[Wordle](https://www.nytimes.com/games/wordle/index.html)にアクセスするとLocalStorageに解答が保存されるのでそれを参照してるだけです。

solutionっていうプロパティです。
![スクリーンショット 2022-02-21 11.45.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2088889/13a3c753-be1f-ed05-7843-ff25c91f34aa.png)


実行ファイル`src/content.ts`はこんな感じ

```src/content.ts
const gameState = localStorage.getItem("nyt-wordle-state");
if (gameState) {
  const gameStateData = JSON.parse(gameState) as { solution: string };
  window.alert(`こたえ: ${gameStateData.solution.toUpperCase()}`);
}
```

localStorageから答えを取得して、大文字に変換したものをalertしてます。

## 使ってみる

まずは、ビルドします。

```
npx webpack
```
とすると、プロジェクト内に`dist`ディレクトリが生成されると思います。

あとは、このdistディレクトリをchromeで読み込んで、[Wordle](https://www.powerlanguage.co.uk/wordle/)にアクセスすれば、ネタバレしてくれます。

chromeで自作の拡張機能を読み込む方法は、以下が参考になると思います。

[うちでChrome拡張機能を作ろう](https://qiita.com/tetrapod117/items/648b05d250b436977f14)

## まとめ

初めてChrome拡張機能を作ってみました。
ちょっとしたものなら簡単に作れてお手軽だな〜と思いました。
気軽にコメントください〜

## 追記 (2022/2/21)

Wordleがニューヨークタイムズの傘下になって、urlとかlocalStorageのキーが変わったので、それに対応しました。