OmniAICreator/Qiita-1.07M huggingface dataset:
ABC 96C - Grid Repainting 2 を解いた

https://atcoder.jp/contests/abc096/tasks/abc096_c

![abc96_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/c00bc41d-7eb5-e628-4f67-58093cefd529.png)
![abc96_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/0ee7bfc0-4fb0-8919-4969-bb9b6e9a74d4.png)
![abc96_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/6d6486fd-b06d-c5fb-17b9-0b46def61b31.png)
![abc96_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/685c9d98-e62d-099e-c8cf-422f883d447e.png)

何回上書き(0回でも可)って書いてあるけど。
結局、"#" を発見した時に上下左右のうち、何れかに "#" があれば OK じゃね？っと考えた。
あとは for 文で全探索。

例えば1行目とか、普通に上下左右って探索しても error になるし、
どうしよっかなーって思ったけど以下の記述に落ち着いた。

```GridRepainting2.py
H,W = map(int,input().split())
S = [list(input()) for _ in range(H)]

#print(S)

for h in range(H):#O(50)
    for w in range(W):#O(50)
        lis = []

        if S[h][w] == "#":                      # もし"#" を発見したら。。
            if h-1 >= 0: lis.append(S[h-1][w])  #   1.上
            if h+1 <= H-1:lis.append(S[h+1][w]) #   2.下
            if w-1 >= 0: lis.append(S[h][w-1])  #   3.左
            if w+1 <= W-1:lis.append(S[h][w+1]) #   4.右　を lis に append

            # list の in 演算子は O(N)だけど、上下左右でも O(4)
            if "#" in lis:                      #  lis の中に "#" があれば連続したセルがあることになる
                continue
            else:
                print("No")                     #  無かった瞬間に No で break
                exit()
print("Yes")


##total 計算量は最低でも O(1000) 程度。全探索しても余裕。

```
通勤時間をpythonによるスクレイピングで取得

最近は大学の研究のためのコーディングばかりだったので、これが久々の投稿になります。

# コード
早速コードを紹介。

```get_arrivalTime.py
'''
Yahoo乗換から到着時間をスクレイピングで抽出する。
引数として以下を与える。
	1. 出発地点 ... 駅名、バス停名、住所など
	2. 到着地点 ... 駅名、バス停名、住所など
	3. 出発時刻 ... datetime型で指定
返り値
	到着時刻 ... datetime型
'''

import urllib.request
from bs4 import BeautifulSoup
import urllib.parse # URLエンコード、デコード
import datetime

def get_arrivalTime(departure_point="大阪",arival_point="東京",departure_time=datetime.datetime.today()):


	dp_en = urllib.parse.quote(departure_point) # encode
	ap_en = urllib.parse.quote(arival_point) # encode

	dt_url = "&y={0}&m={1}&d={2}&hh={3}&m1={4}&m2={5}".format(
		"{0:04d}".format(departure_time.year),
		"{0:02d}".format(departure_time.month),
		"{0:02d}".format(departure_time.day),
		"{0:02d}".format(departure_time.hour),
		"{0:02d}".format(departure_time.minute)[0],
		"{0:02d}".format(departure_time.minute)[1])
	url0 = 'https://transit.yahoo.co.jp/search/result?from='
	url1 = '&flatlon=&to='
	url2 = '&viacode=&viacode=&viacode='
	url3 = '&shin=&ex=&hb=&al=&lb=&sr=&type=1&ws=3&s=&ei=&fl=1&tl=3&expkind=1&ticket=ic&mtf=1&userpass=0&detour_id=&fromgid=&togid=&kw='

	url = url0 + dp_en + url1 + ap_en + url2 + dt_url + url3

	req = urllib.request.urlopen(url)
	html = req.read().decode('utf-8')
	soup = BeautifulSoup(html, 'html.parser')
	time = soup.select("li.time") # 到着時間の記載部分を抽出
	# print(time) # 詳細情報が欲しければこれを出力

	arrive = time[2].select_one('span.mark').text.strip() # <span class="mark">で囲まれたテキストを抽出	

	arrival_time = datetime.datetime(
		departure_time.year,
		departure_time.month,
		departure_time.day,
		int(arrive[0:2]),
		int(arrive[3:5]))

	return arrival_time

if __name__ == '__main__':
	now = datetime.datetime(2021, 10, 1, 10, 5)
	at = get_arrivalTime(
		"大阪府大阪市中央区大阪城１−１", #大阪城
		"京都府京都市上京区京都御苑３",	#京都御所
		now)

	print("到着時刻 ",at)
	print("所要時間 ",at - now)

```

結果は次の通りになるはず。

```結果
到着時刻  2021-10-01 11:49:00
所要時間  1:44:00
```

いい感じ。

住所入れても、駅を入れても、ちゃんと働くので非常に便利です。

#コードの説明
あえて説明が必要なのは、

```python
	dt_url = "&y={0}&m={1}&d={2}&hh={3}&m1={4}&m2={5}".format(
		"{0:04d}".format(departure_time.year),
		"{0:02d}".format(departure_time.month),
		"{0:02d}".format(departure_time.day),
		"{0:02d}".format(departure_time.hour),
		"{0:02d}".format(departure_time.minute)[0],
		"{0:02d}".format(departure_time.minute)[1])
```

ぐらいかなと思います。

"{0:02d}"は、時間に関するリクエストパラメータを与える際に
、桁数をそろえる必要があったため、このような記述にしています。
[SAP][ABAP] ジョブの多重実行を防ぐ標準プログラム RSBTONEJOB2を使ってみた

こんにちは。

今回は、SAPプログラムをジョブ実行した場合の、多重実行処理を防ぐ標準プログラムについての情報です。参考にさせていただきましたのはこちらの記事です。
[HOW TO PREVENT JOBS FROM RUNNING MULTIPLE TIMES IN PARALLEL](https://blogs.sap.com/2015/07/13/how-to-prevent-jobs-from-running-multiple-times-in-parallel/)

一例としてですが、周期ジョブ（サイクリックジョブ）の多重実行防止をアドオン不要で実装でき、設計やテスト工数を大きく削減できます。要件定義者や設計者の方には有用な知識になるものと思います。

## 内容

- 設定方法

- 試してみた

- まとめ

## 設定方法

RSBTONEJOB2を実行すると以下のような選択画面が表示されます。
各項目には以下を設定します。

・JOBNAME：**このプログラムをジョブ実行する際のジョブID**
・REPORT：多重実行したくない実行ログラムID
・VARIANT:上記REPORTのプログラムで使用するバリアントID

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326392/fbfeabb6-f3fd-49e7-49d5-34433cc6fedc.png)

このプログラムの簡単な処理フローを以下に記述してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326392/2acc3b49-1c30-d90a-be50-29b12d6d9426.png)

このプログラムは、自身のジョブを重複チェック対象として、今実行されているのが自分自身のみだと判定した場合にREPORTで指定したプログラムを実行する（俗にいう、「キックする」）仕様となっています。自分と同じジョブIDが自分以外にも動いている時は何もせず処理を終了することで、多重実行処理を防ぐ仕様となっています。逆に言うと、REPORT:BBBBBを直接実行するジョブが存在する場合は多重実行を防ぐことはできません。


## 試してみた

RSBTONEJOB2のバリアント設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326392/22356e7b-f3a0-3127-949e-6daf012f874e.png)

**RSBTONEJOB2のジョブ設定（トランザクション：SM36）**
※ジョブ名は、RSBTONEJOB2のJOBNAMEと同じ（自分自身）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326392/dc9f5e4d-9941-0e80-2f26-81c6c45297ba.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326392/0bea8858-3fb0-bf87-e905-4236cf8d8648.png)

ジョブステップはRSBTONEJOB2が１つのみ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326392/9f627d1f-4480-29cb-5ce0-11043db7a675.png)

**ジョブを実行の実行結果確認（トランザクション：SM37）**
最初の1つのみが実行され、あとの2つはすぐ終了している。多重実行が行われていないことが確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326392/724f86c8-7894-52df-c0cd-c554998bbe48.png)

多重実行と判定されすぐに終了したジョブのジョブログを確認。実行中の1つと自分自身で実行中ジョブが2とカウントされている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326392/b5bacf79-67cf-5891-8068-c6643e8182a9.png)

## まとめ

・RSBTONEJOB2を使用することで、アドオン不要で指定プログラムの多重実行を防ぐことができる

今回は以上となります。ありがとうございました。
【最初に読む】Typescriptってなぁに？？？


TypeScriptとは何でしょうか？
簡単に説明します。

2017年にはGoogleの標準開発言語となりました。
今注目されている将来性のある言語なので、知って損のない情報です。

#対象者
・JavaScriptを知っている方
・TypeScriptと聞いて初めて調べる方
・プログラミング基礎知識のある方

#TypeScriptとは（すごく簡単に）
初めてTypeScriptという言葉を聞く方は複雑に考えても難しいので、とりあえず　
・**TypeScriptはJavaScript**　
と考えましょう。（正確には異なるものです。）

#TypeScriptとは（もう少し詳しく）
正確にはTypeScript＝JavaScriptではありません。
・**JavaScriptの上位互換**。
・TypeScriptは**JavaScriptを拡張して作られたプログラミング言語**。
・TypeScriptを**コンパイルするとJavaScriptのコード**になる。

#重要な特徴（上位互換といわれる所以）
・JavaScriptでは動的型付けだが、TypeScriptでは**静的型付け**（**データ型が明確に宣言できる**）。
・JavaScriptではできない**クラスの作成**ができる。

#なぜTypeScriptをつかうの？
・**エラーを防止できる**
（変数の型をコード内で宣言するため、型が異なる時はコンパイル時にエラーとなる）
・**動作が早い**
（実行時に型を決める動的型付けよりコード内で型を決められる静的型付けのほうが早い）
・**コードが短くなる**
（クラスが使えるため、JSより簡略に書ける）

#TypeScriptの将来性
上記の理由から、TypeScriptは大規模開発での開発効率があがる言語です。
Googleが内の標準開発言語としてC/C++, Java, JavaScript, Python, Goに並んでTypeScriptを設定したことで注目され、今後習得して損のない言語です。
USDMに対するひと工夫

# はじめに
清水吉男さんの書籍・講演で、USDMを知り、開発で取り入れています。
私のプロジェクトでは、USDMにひと工夫を入れ、効果があるなぁと感じたので、そのひと工夫をまとめておきます。


# USDMとは

* 清水吉男，「派生開発の混乱を救う「XDDP」（eXtreme Derivative Development Process）」 
http://www.juse-sqip.jp/vol10/qualityone_01.html

* 清水吉男，「要求仕様記述手法「USDM」ってどんなの？ ～明日から使えるUSDMのエッセンス～」 
https://swquality.jp/temp/nagasakiqdg15_usdm.pdf

# 私達のプロジェクトの問題・課題
## 問題
**要求に対して、仕様が過不足ないか確認しにくい。**

## 課題
**「要求に対して、仕様が過不足ないか」を確認しやすくするために、USDMにひと工夫する。**

# 先行研究：D-Case

* 小林展英，「D-Case入門」，Embedded Technology WEST 2015，2015  
https://www.ipa.go.jp/files/000046847.pdf

* 小林展英，「D-Caseを用いたレビューを見える化する方法の導入事例」，12th WOCS2，2015  
https://www.ipa.go.jp/files/000043911.pdf

* 「D-Caseとは」
http://www.dcase.jp/p/jintro3.html

* D-Case部会，「はじめてのD-Case」，一般社団法人 ディペンダビリティ技術推進協会，2018
http://dimensions-japan.org/dcase/pdf/%E3%81%AF%E3%81%98%E3%82%81%E3%81%A6%E3%81%AED-Case.pdf

D-Caseのイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243842/1c735316-8ac0-fcef-27d4-e00be303971a.png)


# ひと工夫
D-Caseの考え方を応用し、USDMにひと工夫を加える。
「どうやって、その要求から、その仕様が特定したか」を示す、前提と説明をUSDMの要素に加える。
「前提」と「説明」をセットで、「分析結果」という。
要求から下位要求に分解するときにも、必要に応じて「分析結果」を示す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243842/c652d4ae-0f54-d659-f7fe-4f879b990ae8.png)

## ひと工夫したUSDMの形式
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243842/0345ff82-e104-312a-3575-9738417d57c9.png)

分析結果は、調査結果などが示された別ファイル・別シートへのリンクとすることが多い。

# 効果
「分析結果」欄を導入し、「分析結果」が見えるようになり、レビューで以下に気づけるようになった。

* 分析結果がそもそもない
* 分析結果に問題がある

レビューでの指摘をもとに、分析結果を見直すことで、仕様の漏れを検出することができた。

# 関連研究

* 永山辰巳，「IEC62853と派生開発」，2019  
https://www.juse.jp/sqip/symposium/archive/2019/day1/files/E1-3_happyou.pdf  
http://deos.or.jp/link/obj/pdf/SYMPOSIUM_20190611_D-ADD.pdf

# その他のUSDMに関する知見
## 教えていただいたこと
清水吉男さんと古畑慶次さんからお聞きしたこと。

* 関係者で同じ認識が持てれば、仕様の表現としては十分。関係者の持っている前提知識によって、最適な仕様書は変わる。
* 環境変化や制約も要求の１つとして捉える。
* 機能は、入力-変換-出力で表現できる。
* 要求は階層化する、仕様はグループ化する。
* 追加、変更、移植の３つで、プロセスは変えるべき/プロセスは変わる。

## 自分で感じたこと
* USDMは縦に視点を広げやすい。視点を横に広げるにはUSDM以外の手法も組み合わせたほうがいいかも。


# 関連記事
https://qiita.com/kazuo_reve/items/ea7a0720c58edf610034

https://qiita.com/kazuo_reve/items/58076494d0bb72c0a37a

https://qiita.com/KKKKKAAAAANNNNNMMMMMOOOOO/items/4c1761ee9ba5301d4be2
CodeLLDBでSTLの中身が表示されないときの対処法

## 状況

[CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)を用いてC++のデバッグを行う際に、下の画像のようにSTLの中身がうまく表示されない。
![スクリーンショット 2021-10-01 23.19.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635127/80744996-6f0b-7634-8c01-c0e727a9e52e.png)

### 環境

- macOS BigSur 11.6
- lldb 1205.0.27.3
- gcc (g++) 11.2.0
- VS Code

**tasks.json**

```json
{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Build C++17 for Debug",
      "type": "shell",
      "command": "g++",
      "args": [
        "-std=c++17",
        "-g",
        "${file}",
        "-o",
        "${fileDirname}/debug",
      ],
      "group": {
        "kind": "build",
        "isDefault": true
      }
    }
  ]
}
```

**launch.json**

```json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "lldb",
      "request": "launch",
      "name": "codeLLDB Debug",
      "program": "${fileDirname}/debug",
      "args": [],
      "cwd": "${workspaceFolder}",
      "externalConsole": true,
      "preLaunchTask": "Build C++17 for Debug",
    }
  ]
}
```

## 原因

**※正しい原因ではない可能性があります。**  

LLDBが対応しているデバッグファイルフォーマットがうまく生成されていない？
[LLDBの対応フォーマット](https://lldb.llvm.org/status/features.html)
[デバッグオプションごとの生成フォーマット](https://kazmax.zpp.jp/cmd/g/gcc.1.html#ah_13)

## 対処

コンパイラオプションに明示的にレベル3のdwarfフォーマットを指定する。

**変更後のtasks.json**

```json
{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Build C++17 for Debug",
      "type": "shell",
      "command": "g++",
      "args": [
        "-std=c++17",
        "-gdwarf-3",
        "${file}",
        "-o",
        "${fileDirname}/debug",
      ],
      "group": {
        "kind": "build",
        "isDefault": true
      }
    }
  ]
}
```

変更後、下記のようにSTLの中身が表示されるようになった。
![スクリーンショット 2021-10-01 23.19.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635127/80b566a0-60f8-517b-57e5-be8ff66d21d4.png)

## 参考

[Why lldb pretty printers doesn't work for GNU GCC compiled program on MacOS?](https://stackoverflow.com/questions/66225829/why-lldb-pretty-printers-doesnt-work-for-gnu-gcc-compiled-program-on-macos)
自分を奮い立たせたい時に読む

# とにかくアウトプットをし続ける
ということの大切さは、多くの人が認識していることではある。
自分も下記の記事を読んでその重要性を再認識した次第。

https://qiita.com/Cocot-RH/items/967ba54f2198789dbd13

第一線で活躍されている偉い方が言っていることなのだから、間違いないだろう。
そんな大切な行動習慣を三日坊主で終わらせないためには、どうすればいいのか。

答えは簡単だ。

とにかく、やればいいのだ。

まずは、やってみよう。
アリババクラウド SimpleApplicationServer で Jupyter Notebook を試す

# Ubuntuの更新

```bash
$ sudo apt update
$ sudo apt upgrade
```

もし下記のような更新が出たら、
そのままEnterキーを押してください。
![スクリーンショット 2021-10-01 21.34.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390200/fdf54c58-de5f-9d91-5df0-8d84901fc91f.png)

# Python環境インストール

```bash
$ sudo apt install python3-pip python3-dev
$ sudo -H pip3 install --upgrade pip
```

## バージョン確認
```bash
$ pip --version
```

## 仮想化環境インストール
```bash
$ sudo -H pip3 install virtualenv
```

## Jupyter Notebookインストール
```bash
$ mkdir jupyternotebook
$ cd jupyternotebook
$ virtualenv jupyternotebook
$ source jupyternotebook/bin/activate
$ pip install jupyter
```

# Jupyter Notebook設定
```bash
$ jupyter notebook --generate-config
$ jupyter-notebook password
$ cat /home/admin/.jupyter/jupyter_notebook_config.json
```

これで下記のようにハッシュ化されたパスワード(*****部分)をコピーします。

```json
{
  "NotebookApp": {
    "password": "*****"
  }
}
```

## configファイルを修正
```bash
$ vim /home/admin/.jupyter/jupyter_notebook_config.py
 
shift + g + ↓ で最終行に移動、下記を追加する：
c.IPKernelApp.pylab = 'inline'
c.NotebookApp.ip = '0.0.0.0'
c.NotebookApp.open_browser = False
c.NotebookApp.port = 9999
c.NotebookApp.password = '*****部分'
```

## ネットワーク規則追加
![スクリーンショット 2021-10-01 23.25.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390200/dac5db46-8506-9577-1c5e-6a8e9b38264a.png)

# 使ってみる！
```bash
$ jupyter notebook
```

ブラウザからアクセス
{Public IP}:9999
Ubuntuでfish shell導入したらanacondaが使えなくなった問題の備忘録

# はじめに
最近Ubuntu 20.04のPCにfish shellを導入したのですが、anacondaのcondaコマンドを認識しなくなってしまったのでその対処の備忘録になります。

# 環境
* Ubuntu 20.04 LTS
* conda 4.10.1
* fish 3.1.0

# 参考にしたサイト
毎度先人の方々にはお世話になっております。
ありがとうございます m(_ _)m

[Mention how to enable Anaconda in fish shell #1](https://github.com/gtrichards/PHYS_T480_F18/issues/1)
[fish shell で pyenv anaconda環境の初期設定(mac)](https://qiita.com/snara/items/632d42aa8e98c4658aeb)
[fish shell で conda の仮想環境を有効化するための設定](https://org-technology.com/posts/fish-conda.html)

# 問題①condaコマンドを認識しない
fish導入後、`conda`コマンドが認識されなくなってしまうようです。
こちらはデフォルトではfishのPATHにanacondaが入っていないことが原因とのことです。
以下コマンドをfishにて入力することでanacondaをfishのPATHに追加することができ、`conda`コマンドを認識するようになります。

```bash
set -U fish_user_paths "$HOME/anaconda3/bin" $fish_user_paths
```

# 問題②conda activateできない
問題①を解決すれば全部解決すると思いきや何故か`conda activate`が使えない…
以下を~/.config/fish/config.fishの末尾に追加すれば解決できます。

```bash
source (conda info --root)/etc/fish/conf.d/conda.fish
```
初学時に疑問だった事（複数のUITableViewがある時）

#今回の内容

* ひとつのViewにtableViewが2つ以上ある時にどうやって、それぞれ処理を正しく出来るのか？

#いきなり、結論から

* 他にも方法はあると思いますが、私は`switch`と`tag`を利用してそれぞれのtableViewに処理をする様にしています。

#コードと簡単解説

* tableViewを２つ用意して、それぞれに`tag`を設定します。

```Swift:例
import UIKit

class ViewController: UIViewController {
    
           ~~~~~~~~~~省略~~~~~~~~~~
    let tableView = UITableView()
    let tableViewTwo = UITableView()

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self
        tableView.tag = 1
        view.addSubview(tableView)

        tableViewTwo.delegate = self
        tableViewTwo.dataSource = self
        tableViewTwo.tag = 2
        view.addSubview(tableViewTwo)
    }
}
```

* 今回は`UITableViewDataSource`のメソッドを例に説明します。

* `case 1:`で`tableView`のセルの個数を設定

* `case 2:`で`tableViewTwo`のセルの個数を設定

```Swift:例
extension ViewController:UITableViewDataSource{

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        var returnInt = Int()
        
        switch tableView.tag{
        
        case 1: returnInt = 101
            
        case 2: returnInt = 51
            
        default: returnInt = 0
        }
        
        return returnInt
    }
}
```
# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
【Jest】非同期処理のテストを書こう~Promiseとasync/await~

# 非同期処理のテストを書こう
Jestを使った非同期処理のテストのテストをまとめたいと思います。
プロジェクトでは、Promiseとasync/awaitを使った非同期処理を書くことが多いのでこの２点のテストコードをまとました。

## Promiseのテストの書き方
* [公式ドキュメント](https://jestjs.io/ja/docs/asynchronous#promises)
* ```.resolves関数```を利用することでPromiseが処理され、``` Promise.resolve```が実行された値を評価することができます。
* ```return```を省略した場合、テストはfetchDataがresolveされpromiseが返ってくる前に実行されます

```javascript:assertion.test.js
const fetchData = () => Promise.resolve("hoge");

test("resolves to hoge", () => {
  return expect(fetchData()).resolves.toBe("hoge");
});
```

## async/awaitのテストの書き方
* [公式ドキュメント](https://jestjs.io/ja/docs/asynchronous#asyncawait)
* 非同期テストを書くには、テストに渡す関数の前にasync キーワードを記述するだけです


```javascript:assertion.test.js
const fetchData = () => Promise.resolve("hoge");

test("resolves to hoge with async/await", async () => {
  await expect(fetchData()).resolves.toBe("hoge");
});

```

## rejectsの書き方
* [公式ドキュメント](https://jestjs.io/ja/docs/asynchronous#resolves--rejects)
* promiseがrejectされることを期待するケースでは```.rejects```を使用を使用します


```javascript:assertion.test.js

const fetchData = (category = "hoge") =>
  category === "hoge"
    ? Promise.resolve("hoge")
    : Promise.reject(new Error("not exist"));

test("rejects with foo", () => {
  return expect(fetchData("foo")).rejects.toThrow("not exist");
});
```

## おわりに
jestを使えば、非同期処理のテストも簡単に書けますね！
GitLab CI/CDでNuxtのbuildをしたら17分もかかり、なんとかしたい

Gitlab CI/CDでNuxt Buildする場合ってこんなかかるもんなんでしょうか？

`npm install`は5分ほどで完了いるのに対して、`nuxt-ts build`が約17分かかってしまいます。

|   |  MacBook Pro (13-inch, M1, 2020)  |  Docker(node:14.18.0-alpine3.14)  |  GitLab CI/CD（Shared runner)  |
| ---- | ---- | ---- | ---- |
| build時間 |  Version: webpack 4.43.0 Time: 25613ms  |  Version: webpack 4.46.0 Time: 20465ms  |  Version: webpack 4.43.0　Time: 1056879ms  |

Specific runnerを使えばbuild速度は改善できると思いますが、できればSharedで行いたく。
改善できたら追記します。

## 参考

- https://qiita.com/baby-degu/items/195b498f2e19f620cc30
- https://gitlab.com/gitlab-org/gitlab-runner/-/issues/5028#note_605178838
AWS Lambda関数内でaws-cliを呼び出せる様にしたい

## 目的
aws-cliで行っていた処理を、Lambda関数で実行できるようにして、最終的にslackなどをトリガーにして、簡単に実行できる様にしたい。その前準備として、lambda関数でaws-cliを使えるように、lambdaレイヤーを使用して、lambda関数にaws-cliを追加するレイヤーを準備する。

## 結果
GithubのREADME.mdに従ってコマンドを実行するだけで、作成＆デプロイがされます。
(git cloneしてデプロイするだけ)

https://github.com/mocaberos/aws-cli-lambda-layer

## 仕組み
aws-cliはpythonスクリプトで実装されているため、pythonモジュールとしてインストールしたあと、該当するファイルをコピーする、実行環境が変わるため、awsスクリプトの先頭のシバンを`#!/var/lang/bin/python`に書き換えて、あとはzipに固めてデプロイするだけで、lambda関数から使えるようになります。
この処理をスクリプトとして纏めると、下記になります。

```shell
#!/usr/bin/env bash

set -eu;

cd `dirname ${0}`;
rm -rf ./tmp;
mkdir ./tmp;
python3 -m venv ./tmp;
./tmp/bin/pip install awscli;
rm -rf ./lambda-layer;
mkdir lambda-layer;
cp ./tmp/bin/aws ./lambda-layer;
cp -r ./tmp/lib/python3.*/site-packages/* ./lambda-layer;
rm -rf ./tmp;
cat ./lambda-layer/aws |(rm ./lambda-layer/aws; sed '1s/.*/\#\!\/var\/lang\/bin\/python/' > ./lambda-layer/aws)
```

デプロイのawsコマンドは`/opt/aws`に配置されており、Python3のランタイムを持つLambda関数に、該当するレイヤーを付けた後、下記のようにpythonからシェルコマンドとして使用できます。

```python
import subprocess
subprocess.call('/opt/aws --version', shell=True)
```
githubの個人アクセストークンを使用する

※ｎ番煎じですみませんが、自分用メモ

2021/8/13より、Githubへ認証が必要なgit操作をする場合は、
Passwordによる認証からアクセストークンを使用した認証に変わった。

> [Token authentication requirements for Git operations](https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/)

個人アクセストークンの使い方は、基本的には以下の公式サイトを参照するだけでよい。

> [個人アクセストークンを使用する](https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token#creating-a-token)

コマンドラインからアクセストークンを使う場合は、記載通り以下の通りにすればよい。

>コマンドラインでトークンを使用する
トークンを入手したなら、HTTPS経由でGitの操作をする際にパスワードの代わりにそのトークンを入力できます。
>
>たとえば、コマンドラインでは以下のように入力できます。
>
>$ git clone https://github.com/username/repo.git
>Username: your_username
>Password: your_token
Java基本的なまとめ

#クラス
クラスを組み合わせて一つのプログラムを作るイメージ。
クラスが集合体になってJavaの土台となっていくイメージ

![10285001417.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1572216/d299cde8-3c2e-a472-77cf-ac9e7fbfa142.jpeg)

__クラスを定義する__

```java:Greeting.java
class Greeting{
  public static void main(String args[]){

  }
}
```

①class Greetingと定義する。クラスを定義する際、最初にclassと記述しなければならない。

②classの次は、どんな名前のクラスを決定する。クラスの名前のことを「クラス名」という。

__※ファイル名とクラス名は同じにする必要がある。__
__※クラス名の最初は大文字にするのが鉄則。__

③クラス名の後は波括弧を記述する。波括弧で囲まれた部分をブロックと呼ぶ。
波括弧の中に、プログラムにどんなことをさせるのか処理を記述する。

#メソッド

```java:Greeting.java
class Greeting{
  public static void main(String args[]){

  }
}
```

①メソッドの書き方はpublicと
②static,main,丸括弧
③String arg　角括弧

#挨拶を処理させるプログラム
```java:Greeting.java
public class Greeting {
    public static void main(String[] args){
        System.out.println("Good morning");

        System.out.println("Good afternoon");

        System.out.println("Good evening");
    }
}
```

ファイルを実行して、文字を表示してみます。
ターミナルからコンパイルを実行！

コンパイル方法はJavacと書いて、Javaのファイル名を書く。
すると、Greeting.classというファイルが生成される。
次にJava,後ろにファイル名を記載しEnter。

```java:実行結果
Good morning
Good afternoon
Good evening
```

>コンパイルとは、Javaのプログラムをパソコンが読み取れる機械語に変換すること。
Google Colaboratoryでデバッグを行う方法

デバッグを行いたい場所に以下のコードを入力します。

```python
from IPython.core.debugger import Pdb; Pdb().set_trace()
```

このコードを読み込まれた時点で、Python 標準のデバッグツールである pdb が起動します。

pdbの基本的なコマンドは以下のとおりです。

- h [command]：ヘルプを出す
- p [expression]：式を評価して出力する
- n：次の行へ
- c：次のブレークポイントへ
- q：その場で終了する

他にもいろんなコマンドがあるので[pdbコマンド一覧](https://appletree.or.kr/quick_reference_cards/Python/Python%20Debugger%20Cheatsheet.pdf)を見てみるといいかもです。

[w：スタックトレースを含んだ現在位置を示す] コマンドなんかはどのような手順で関数が呼び出されたのかを把握できたりするので便利です。


# 具体例

例えば、以下の例を見てみましょう。

```python
def harmonic(n):
  acc = 0
  for i in range(n):
    from IPython.core.debugger import Pdb; Pdb().set_trace()
    acc += 1.0 / i
  return acc
print(harmonic(10))
```

```python
> <ipython-input-8-8f37e64adc73>(5)harmonic()
      3   for i in range(n):
      4     from IPython.core.debugger import Pdb; Pdb().set_trace()
----> 5     acc += 1.0 / i
      6   return acc
      7 print(harmonic(10))

ipdb> p acc
0
ipdb> p i
0
ipdb> c
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-8-8f37e64adc73> in <module>()
      5     acc += 1.0 / i
      6   return acc
----> 7 print(harmonic(10))

<ipython-input-8-8f37e64adc73> in harmonic(n)
      3   for i in range(n):
      4     from IPython.core.debugger import Pdb; Pdb().set_trace()
----> 5     acc += 1.0 / i
      6   return acc
      7 print(harmonic(10))

ZeroDivisionError: float division by zero
```


# 参考文献
[Google Colaboratoryでのデバッグのやり方](https://ja.stackoverflow.com/questions/62955/google-colaboratory%E3%81%A7%E3%81%AE%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E3%81%AE%E3%82%84%E3%82%8A%E6%96%B9)
Windowsの環境でもLinuxのフォレンジックツールを使いたい！


この環境は題名の通り、Windowsの環境でもLinuxのフォレンジックツールを使う為の環境を構築します。

今回WSL2を使うことで、WindowsでもLinux環境が使え、かつSIFTとRemnuxをインストールすることで、Linuxのフォレンジックツールを使うことができる一石二鳥な環境です。

そんな環境構築メモになります。

# 目次
 - [1. インストール環境](#インストール環境)
 - [2. WSL2のセットアップ](#wsl2のセットアップ)
   - [1. Linux 用 Windows サブシステムの有効化](#1-linux-用-windows-サブシステムの有効化)
   - [2. 仮想マシン プラットフォームの有効化](#2-仮想マシン-プラットフォームの有効化)
   - [3. Linux カーネル更新プログラム パッケージのダウンロードとインストール](#3-linux-カーネル更新プログラム-パッケージのダウンロードとインストール)
 - [3. Ubuntu 20.04 LTSのインストール](#ubuntu-2004-ltsのインストール)
 - [4. SIFTのインストール](#siftのインストール)
    - [1. Shellを起動し、root（sudo su）に昇格する](#1-shellを起動しrootsudo-suに昇格する)
    - [2. SIFT CLIのダウンロード](#2-sift-cliのダウンロード)
    - [3. 権限の変更](#3-権限の変更)
    - [4. インストール](#4-インストール)
 - [5. REMnuxのインストール](#remnuxのインストール)
    - [1. ダウンロード](#1-ダウンロード)
    - [2. 諸々実行](#2-諸々実行)
    - [3. インストール](#3-インストール)
 - [6. その他ツールのインストール](#その他ツールのインストール)
 - [7. 参考URL](#参考url)

## 1. インストール環境

インストール環境は下記の通り

```
エディション    Windows 11 Home
バージョン      21H2
OS ビルド       22000.194
```

## 2. WSL2のセットアップ

### 1. Linux 用 Windows サブシステムの有効化
```
Powershell/管理者として実行

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
```

### 2. 仮想マシン プラットフォームの有効化
```
Powershell/管理者として実行

dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
```
### 3. Linux カーネル更新プログラム パッケージのダウンロードとインストール


[wsl_update_x64.msi](https://docs.microsoft.com/ja-jp/windows/wsl/wsl2-kernel)をダウンロードし、ダウンロードした「wsl_update_x64.msi」を実行

## 3. Ubuntu 20.04 LTSのインストール
Microsoft StoreからUbuntu 20.04 LTSを入手する

## 4. SIFTのインストール

### 1. Shellを起動し、root（sudo su）に昇格する

### 2. SIFT CLIのダウンロード

```
curl -Lo /usr/local/bin/sift https://github.com/sans-dfir/sift-cli/releases/download/v1.11.0/sift-cli-linux
```

### 3. 権限の変更

```
chmod +x /usr/local/bin/sift
```

### 4. インストール

```
sift install --mode=server
```

## 5. REMnuxのインストール
### 1. ダウンロード
```
wget https://REMnux.org/remnux-cli
```

### 2. 諸々実行

```
mv remnux-cli remnux

chmod +x remnux

mv remnux /usr/local/bin
```

### 3. インストール

```
remnux install --mode=addon
```


## 6. その他ツールのインストール
- [autopsy](https://www.autopsy.com/)
- [kape](https://www.kroll.com/en/insights/publications/cyber/kroll-artifact-parser-extractor-kape)
- [RegRipper](https://github.com/keydet89/RegRipper3.0)
- [nirsoft](https://www.nirsoft.net/)
- [Eric Zimmerman Tools](https://ericzimmerman.github.io/#!index.md)
- [Docker](https://www.docker.com/products/docker-desktop)

## 7. 参考URL
- https://docs.remnux.org/install-distro/install-from-scratch
- https://github.com/teamdfir/sift-cli#installation
DataFrameの行を重複なしで組合せる

データセット、例えば3つの特性からなる5回分の試験データがあったとして、5回分の試験データを重複なしで組み合わせて平均をとるなりの処理をしたいときの方法をメモします。

まず、サンプルデータを作ります。乱数で5行3列を作成しています。random.seedを設定することで、毎回同じ乱数になります。

```python
import numpy as np
import pandas as pd

np.random.seed(seed=1)
df = pd.DataFrame(np.random.rand(5, 3),
                  columns=['sy', 'su', 'elong'],
                  index=['a', 'b', 'c', 'd', 'e'])
```

dfの中身はつぎのようになります。

```
         sy        su        el
a  0.131750  0.469233  0.032909
b  0.433968  0.014887  0.557556
c  0.611954  0.148562  0.172844
d  0.166242  0.230893  0.703038
e  0.965665  0.492269  0.537133
```

a〜eの5行を重複なしで組み合わせる、すなわち、5つの中から2つ取り出す場合、5つの中から3つ取り出す場合、5つの中から4つ取り出す場合、5つの中から5つ取り出す場合のすべてに対して何らかの計算をしたい場合には、itertoolsのcombinationsを使うと上手く行きました。

```python
import itertools

n = len(df)
combinations = []
for i in range(2, n+1):
    combinations += list(itertools.combinations(df.T, i))
````

これで、combinationsはデータフレームの列のidの組合せのタプルになります。df.Tとして転地しておくことで、もとの行、すなわち試験データセットの組合せとなります。combinationsの中身はつぎのようになります。

```
[('a', 'b'), ('a', 'c'), ('a', 'd'), ('a', 'e'), ('b', 'c'), ('b', 'd'), ('b', 'e'), ('c', 'd'), ('c', 'e'), ('d', 'e'), ('a', 'b', 'c'), ('a', 'b', 'd'), ('a', 'b', 'e'), ('a', 'c', 'd'), ('a', 'c', 'e'), ('a', 'd', 'e'), ('b', 'c', 'd'), ('b', 'c', 'e'), ('b', 'd', 'e'), ('c', 'd', 'e'), ('a', 'b', 'c', 'd'), ('a', 'b', 'c', 'e'), ('a', 'b', 'd', 'e'), ('a', 'c', 'd', 'e'), ('b', 'c', 'd', 'e'), ('a', 'b', 'c', 'd', 'e')]
```

dataframeから特定の要素を抽出するには、df.loc[]で配列を渡してやればいいです。combinationsはタプルなので、まず配列に変換して、df.locに渡してやります。例えば1番最初の組合せを取り出すには、以下のようになります。

```python
x = list(combinations[0])
df2 = df.loc[x]
```

df2の中身は出力はつぎのようになります。

```
         sy        su        el
a  0.131750  0.469233  0.032909
b  0.433968  0.014887  0.557556
```

あとは、それぞれの組み合わせで取り出したDataFrameに対して、お好みの処理を行います。
AtCoderログ：0130 - ABC 114 B

# 問題

https://atcoder.jp/contests/abc114/tasks/abc114_b

## 収録されている問題セット
- [AtCoder Problems Boot camp for beginners Easy 100](https://kenkoooo.com/atcoder/#/training/Boot%20camp%20for%20Beginners/1) [#029]

# 回答
## 回答1 (AC)
文字列 $S$ を3文字ずつ読み込んで整数に変換し、753 との差が最も小さいものを調べれば良いでしょう。コードは以下のようになりました。

```C++:abc114b-1.cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
  string s;
  cin >> s;

  int dmin = INT_MAX;
  for ( int i=0; i<(int)s.size()-2; i++ ) {
    string a = s.substr(i,3);
    dmin = min( dmin, abs(753-stoi(a)) );
  }
  
  cout << dmin << endl;
}

```

# 調べたこと
## [AtCoder の解説](https://atcoder.jp/contests/abc114/tasks/abc114_b/editorial) → [ユーザ解説](https://blog.hamayanhamayan.com/entry/2020/03/08/100424)
回答1と同じ方針でした。「文字を数字に変換する場合はc-'0'とすればいい」そうです。

## [AtCoder の解説](https://atcoder.jp/contests/abc114/tasks/abc114_b/editorial) → [ユーザ解説]((https://atcoder.jp/contests/abc114/tasks/abc114_b/editorial) → [ユーザ解説](https://blog.hamayanhamayan.com/entry/2020/03/08/100424)
)
回答1と同じ方針でした。やはり「文字を数字に変換する場合はc-'0'とすればいい」とのこと。

# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0129 - ABC 220 C](https://qiita.com/RoadLynton/items/69b399998a26d6ca107e)
【Unity】Androidトラブルシューティング

# 正しいパスを設定してもファイル保存時にExceptionが発生する。
<B>API29以上の場合、</B>セキュリティ違反でエラーが発生していることがあるので、manifestfileの"application" タグに <B>android:requestLegacyExternalStorage="true"</B>を追加する。

# ビルド時に"CommandInvokationFailure: Unable to retrieve /proc/meminfo from device. Please make sure the Android SDK is installed and is properly configured in the Editor. See the Console for more details."が表示される。

Build Settingsの実行デバイスとしてビルド対象の端末が見つからない場合に発生する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/0512f2d6-89e5-162e-565b-669b64898826.png)
Android端末の再起動か、開発者モードのOFF→ONすると検出できるようになる。
MIUI12.5のRedmiNote9sにGame TurboでEnhanced Audioを表示させる　（動くとは言っていない）

#はじめに
Xiaomi製スマホのMIUI12.1以降のGameTurboには「WiFiの最適化」、「最適化されたタッチコントロール」の他に「強化されたオーディオ」の項目があるはずなのですが、RedmiNote9sにはMIUI12.5になってもありませんでした。
これの何が問題かと言うと、デレステ（アイドルマスターシンデレラガールズスターライトステージ）やプロセカ（プロジェクトセカイ）と言った音ゲー（音楽・リズムゲーム）をプレイする際に、タップした時に効果音が鳴るのですが、鳴った際にデレステではノーツが一瞬カクっと遅れます。
特に高難易度をやろうとすると音が狂うので大問題です。
Mi11Liteなどは問題なくEnhanced Audioが表示されているそうですが、私のスマホには無かったため表示させる方法を模索しました。
あとついでにゲームターボのボイスチェンジャーも有効化します。
キチンと検証してないので完全無責任です。
#必要なもの
MIUI12.1以上のスマホ（12.0.4などではダメ）
Rooted環境（推奨）
Magisk（推奨）
ADB環境（rootが無ければ）（出来るか不明）
#やり方
rooted環境ならば、MagiskHide Props Configなどを使いpropに"ro.vendor.audio.game.effect=true"の項目を追加することで「強化されたオーディオ」の項目が出てきます（要再起動？）
MagiskHide Props Configの使い方は書かないので検索なりなんなりして下さい。
しかし、[とある中国人のMiPad5では][link-1]これだけでは表示されるだけで効果が無かったそうなので"ro.vendor.audio.game.mode=false"を追加したそうです。
ちなみに私のRedmiNote9sでは両方追加しても効果を感じられませんでした。
[link-1]:https://www.bilibili.com/read/cv12999751
非Rood環境でpropを編集する場合は、adb shellのsetpropで設定出来るかもしれません。（未確認）

ボイスチェンジャーを有効にするには、propに"ro.vendor.audio.voice.change.support=true"を追加してください。
私はこれでRedmiNote9sでもボイスチェンジャーが使えました。

…とわざわざPropを書き換える方法を書きましたが、普通にMagiskモジュールも[あり][link-2][ます][link-3]
[link-2]:https://wwr.lanzoui.com/ivUbGtivj2j
[link-3]:https://androidfilehost.com/?fid=17248734326145680618

ちなみに、GameTurboはMiSecurityの一部なのでAPKMirrorなどから最新版を入れれば「Gameturbo4.0」など新しい機能が追加されます（UIが英語や中国語のみになります。）が、最新のを入れてもVendor.Propに上記の記載が無ければ多分出てきません。

#おわりに
わざわざBLUまでしてやろうとするならMIUIに拘らずAOSPベースのカスタムROMにすれば全て解決します。
MIUIのカメラ機能が欲しいならANXCameraやこれを内蔵したArrowOSなどの選択肢があります。
他にもMIUI12.6ベースのカスタムROMを使う方法もいいかもしれません。（curtunaだけじゃなくmiatoll向けのも探してみよう）

##参考記事
[【全网首发】修复小米平板 5 Project Sekai 及其他 CRIWARE 游戏卡顿问题【root】][link-1]


[Game Turbo 3.0 Voice Changer in any MIUI Xiaomi phone][link-4]
[link-4]:https://androinterest.com/2020/12/10/game-turbo-voice-changer-miui-xiaomi-phone/
STM32CubeIDE マルチタスク 小物

# Special thanks to

https://qiita.com/imagou/items/8af2ad999b2a80009c6f

# 確認環境

STM32CubeIDE 1.7.0
NUCLEO-F303K8

# やりたかったこと

各タスクで時間を知りたい。

# 解決方法

`osKernelSysTick()` を取得する。

# サンプル

冒頭のURLの手順で，タスクを2個追加。

```c:
/* USER CODE BEGIN Header_StartDefaultTask */
/**
 * @brief  Function implementing the defaultTask thread.
 * @param  argument: Not used
 * @retval None
 */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN 5 */
	/* Infinite loop */
	for (;;) {
		printf("%d:Task 1--\r\n",(int)osKernelSysTick());
		osDelay(1000);
	}
  /* USER CODE END 5 */
}

/* USER CODE BEGIN Header_StartTask02 */
/**
 * @brief Function implementing the myTask02 thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_StartTask02 */
void StartTask02(void const * argument)
{
  /* USER CODE BEGIN StartTask02 */
	/* Infinite loop */
	for (;;) {
		printf("%d:Task -2- o\r\n",(int)osKernelSysTick());
		// printf("%d:Task -2- x\r\n",(int)xTaskGetTickCount());
		osDelay(2000);
	}
  /* USER CODE END StartTask02 */
}

/* USER CODE BEGIN Header_StartTask03 */
/**
* @brief Function implementing the myTask03 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask03 */
void StartTask03(void const * argument)
{
  /* USER CODE BEGIN StartTask03 */
  /* Infinite loop */
  for(;;)
  {
		printf("%d:Task --3\r\n",(int)osKernelSysTick());
		HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
		osDelay(800);
  }
  /* USER CODE END StartTask03 */
}
```

実行結果

```
2401:Task --3
3000:Task 1--
3201:Task --3
4000:Task 1--
4001:Task --3
4003:Task -2-
4801:Task --3
5000:Task 1--
5601:Task --3
6000:Task 1--
6003:Task -2-
6401:Task --3
7000:Task 1--
7201:Task --3
8000:Task 1--
8001:Task --3
8003:Task -2-
8801:Task --3
9000:Task 1--
9601:Task --3
10000:Task 1--
10003:Task -2-
10401:Task --3
11000:Task 1--
11201:Task --3
```

## 追記

最初は `StartDefaultTask()` がうまく動かなくて悩みました。
コメント欄でもある通り，UART送信を使った `printf` が重複してフリーズしていたのが原因のようでした。
動作確認では，UART送信にDMAを使って，前回の送信終了を確認してから `printf` するようにしました。

See also:
https://qiita.com/numeru55/items/fd61922eeec6be62a22a

# 補足

## xTaskGetTickCountじゃないの？

cmsis_os.c 参照 私にもよくわかりません...

```c
#if (defined (osFeature_SysTick)  &&  (osFeature_SysTick != 0))     // System Timer available
/**
* @brief  Get the value of the Kernel SysTick timer
* @param  None
* @retval None
* @note   MUST REMAIN UNCHANGED: \b osKernelSysTick shall be consistent in every CMSIS-RTOS.
*/
uint32_t osKernelSysTick(void)
{
  if (inHandlerMode()) {
    return xTaskGetTickCountFromISR();
  }
  else {
    return xTaskGetTickCount();
  }
}
#endif    // System Timer available
```
プログラミング学習　Day2

#前回の復習
- pythonはAIや機械学習が得意
- pythonの現在のバージョンは3.台（2021年現在）

#goole colaboratory
- グーグルが無料で提供
- 速い実行などが必要なときは有料バージョンも
- 一定期間操作しないとプログラムが消えてしまう
- １つのプログラムに１つのノートブック
- ブラウザで動いてるわけではなくクラウド上のサーバで計算されている
- 333.3333333333*3が1,000になるときもならないときもある（999.9999999になる)
- 32bitOSなら1つの数値を保存するのに32bitしか使用できないので無限小数は無限には表記できない
- しっかりと数値を計算するのは結構難しい（言語による）
- 課題は答え合わせはせずに自分で検索して答えにたどり着く、それがプログラミングの勉強の仕方

#pythonでの型
- str　文字列
- int　整数
- float  浮動小数点数
- bool　ブール　TrueかFalseか
- Nonetype　型なし　None

#定数と変数
- 値がかわらないもの。１とか２とか。
- 値を代入することができて上書きできる文字で表すことのできる値
エラトステネスの篩

#ソースコード

```javascript
function primesvalue(n){
    // サイズnのブーリアン値trueを持つリストを作成
    let cache = [];
    for(let i = 0; i < n; i++) {
        cache.push(true);
    }

    // ステップを√n回繰り返します。
    for (let currentPrime = 2; currentPrime < Math.ceil(Math.sqrt(n)); currentPrime++){
        if (!cache[currentPrime]) continue;
        let i = 2;
        let ip = i * currentPrime;
        while (ip < n){
            cache[ip] = false;
            // i*pをアップデートします。
            i += 1;
            ip = i * currentPrime;
        }
    }

    // 素数
    let numbers = [];
    for (let i = 2; i < cache.length; i++){
        if (cache[i]){
            numbers.push(i);
        }
    }

    return numbers;
}

```
未経験からエンジニアになった自分のロードマップ

本日第一志望の企業から内定を頂きました。
未経験からエンジニアになるためのロードマップを覚えている範囲で書きます。

#2019年
9月 始まりはネットで次どこの職種行こうかななんて探していたらIT企業を見つけここにしようと思ったのがきっかけです。

#2020年
2月 UZUZさんにて転職サポートを受け、Javaの学習を始める

4月 UZUZさんにて転職活動開始

8月 7社応募したうち面接に進んだのは2社、内定0と苦戦した

10月　マコなり社長の動画を見てテックキャンプに入って力つけてエンジニアになる決意を固めた

#2021年
1月 雑食サロンに入会してポートフォリオの作成を開始

4月 テックキャンプを卒業し、転職活動を開始

5月　　どこも内定が取れず、中途半端だ、学習期間が長すぎると批評を受ける

6月 SES企業から1社内定

7月 SES企業から1社内定

8月 SES企業から2社内定

10月　受託開発企業から1社内定

他にもマイナビ、type,doda,green,メイテックネクストを使いました。

#最後に
長い期間にわたる初めての転職が終わりました。これからエンジニアとしてスタートを切るので今まで以上に努力を積み重ねていこうと思います。
[Rails] migrationファイルが無く、RDBMSに変更が残ってしまった時の解消方法

ブランチを移ってmigrationしたが、それを戻さずに違うブランチに移ってしまい、ファイルが行方不明になってしまった下記のような場合の解決法。

```
$ rake db:migrate:status
...
   up     20210709062913  ********** NO FILE **********
```

「rails migration no file」と検索するとマイグレーション管理のtableに変更を入れるだけ記事がいくつかヒットするが、本質的解決ではない。マイグレーションの冪等性を保つためにRDBMSに残っている変更も同時に消すことが望ましい。

https://qiita.com/sakatan_1/items/9bf321f81d3b84042694
https://note.com/yofupro/n/nd2ed39123066

## 解決策
前提：gitで管理されているリポジトリであること

### 手順
1. gitのコミットに残っていないか検索する
1. 検索結果からcherry-pickなり、コピペなりで、同名のmigrationファイルを復元する
1. `rake db:migrate:down VERSION=xxxx` を実行する
1. 2.で作成したmigrationファイルを削除する

### 1. gitのコミットに残っていないか検索する

```
$ git log --all --full-history db/migrate/20210709062913*
```

参考

https://intellipaat.com/community/9088/git-how-to-find-a-deleted-file-in-the-project-commit-history

あとはよしなに。


## 他の解決策
`rails migration no file` で検索するとstack overflowがヒットした。
[What is the best way to resolve Rails orphaned migrations? - Stack Overflow](https://stackoverflow.com/questions/16041790/what-is-the-best-way-to-resolve-rails-orphaned-migrations)
【WordPress】自作ショートコードの定義

依頼に応じてショートコードを作成することがあるのですが、
なにぶんよく書き方を忘れるので、ひな形を備忘録として残します。

#シンプルなショートコードの定義
決められた文字列を返すだけのどシンプルなショートコード

```functions.php
function hoge_func() {
    return "Hello World";
}
add_shortcode('hoge', 'hoge_func');
```
```WordPress.設定
[hoge]
```

#引数を渡して実行するショートコード
###１つの引数を渡す場合

```functions.php
function hoge_func($atts) {
    extract(shortcode_atts(array(
        'num' => 0,
    ), $atts));
 
    return $num * 2;
}
add_shortcode('hoge', 'hoge_func');
```
「'num' => 0」で変数「num」に初期値「0」を代入する。
※引数が渡されなかった場合、「0」が設定される。

```WordPress.設定
[hoge num=1]
```

###２つ以上の引数を渡す場合

```functions.php
function hoge_func($atts) {
    extract(shortcode_atts(array(
        'num1' => 0,
        'num2' => 0,
        'num3' => 0,
    ), $atts));
 
    return $num1 + $num2 + $num3;
}
add_shortcode('hoge', 'hoge_func');
```
※初期値の設定を追加するだけ

```WordPress.設定
[hoge num1=1 num2=2 num3=3]
```
複数の引数を渡す際は、半角スペースを挟んで記述する。

#囲み型のショートコード
文字列を囲った形で使用したい際に使う。

```functions.php
function hoge_func($atts, $content = null) {
    return '<h1>' . $content . '</h1>';
}
add_shortcode('hoge', 'hoge_func');
```

```WordPress.設定
[hoge]Hello World[/hoge]
```
囲まれた文字列が「$content」に入る。
※文字列だけでなくGutenbergのブロック要素を囲っても動作可能。

#囲み型で引数を渡す場合

```functions.php
function hoge_func($atts, $content = null) {
    extract( shortcode_atts( array(
        'class' => 'default',
    ), $atts ) );

    return '<h1 class="' . $class . '">' . $content . '</h1>';
}
add_shortcode('hoge', 'hoge_func');
```
引数に関する書き方は自己完結型のものと同じ。

```WordPress.設定
[hoge class="class-name"]Hello World[/hoge]
```

#テンプレート（PHPファイル内）からショートコードを呼び出す場合
```template.php
<?php echo do_shortcode('[hoge]'); ?>
```
ショートコードは基本的に投稿や固定ページで記述するものだが、
テンプレート等のPHPファイルから実行も可能。
Javaに慣れている人向けのPython基本文法のメモ

Javaに慣れた人（自分）からすると、一見、見慣れなかったり奇妙だと思える記法があるためメモ

# python 基本文法

# import

module をインポートします

```
import <module> as <alias>
```

module 内のmethodやvariableをimportします

```
import <module> from <method> [as <alias>]
import <module> from <var> [as <alias>]
```

import の指定にドット区切りのものを指定するケースは、パッケージ内パッケージとからしい。（追記予定）

https://qiita.com/hiroyuki_mrp/items/4b7102709e6582b9dd15


## 関数引数

スプレッド演算子のような使い方で関数の引数に値を渡すことができる。

tuple / arrayを展開して引数に与える

```python
arr = (1,2,3)
print(*arr)
arr = [1,2,3]
print(*arr)
```

## 比較演算子

pythonの論理演算子は連結して記載すると評価結果の論理積が式の値として扱われます。
そのため、よくあるプログラミング言語で使用できない以下のような数学の記法

```python
if 1 < a < 5:
```

は

```python
if 1 < a and a < 5:
```

として解釈されます。

```python
a is b is c is None
```

は

```python
a is b and b is c and c is None
```

として解釈されます。

## 文字列のパーセント演算子

```python
print("aaa%d" % 123)
print("aaa%d%d" % (123,456))
```

のような表現があり、c言語のprintfのようにフォーマットされているのかと思いきや、
フォーマット処理自体が文字列の演算子として定義されている。

https://docs.python.org/ja/3/library/operator.html#in-place-operators

この % 演算子の実態は、数値の剰余演算子 % の実体と同じ名称の関数 mod(s, obj) で定義されている・・・

## 浮動小数点数の精度

```
ほとんどすべてのプラットフォームでは Python の浮動小数点を IEEE-754 における "倍精度(double precision)" に対応付けます。
...
J/2**N の形式にしようと努力します。J はちょうど 53 ビットの精度の整数です
```

https://docs.python.org/ja/3/tutorial/floatingpoint.html


## 整数の精度

```
Python3のintはPython2のlongに相当し、最大値の上限はなく、メモリの許す限り大きな値を扱うことが可能。
...
なお、NumPyではint32（32ビット整数型）やint64（64ビット整数型）のようにビット数が固定のデータ型が用いられる。
```

https://note.nkmk.me/python-int-max-value/


## 配列のスライス

`a:b` は範囲として `b` を含まないことに注意。

```
arr = [10,11,12,13]

print(arr[1:3])
# [11, 12]

print(arr[1:])
# [11, 12, 13]

print(arr[:3])
# [10, 11, 12]

print(arr[::2])
# [10, 12]
```
deviseのメールアドレスのバリデーションを変更する

## はじめに
開発ですぐに忘れそうなことを、簡単に再度調べられるようにするための備忘録です。

## やりたいこと
ログイン認証関連のgem、[devise](https://github.com/heartcombo/devise)の
メールアドレスのバリデーションを強化したい。

## 背景
deviseには、メールアドレスとパスワードのバリデーションが簡単に設定できる「validatable」モジュールが実装されているが、メールアドレスのバリデーションがゆるい。

例）
- exam$$ple@gmail.com のような記号が含まれていても通ってしまう
- example@aaaaa のような不正なドメインでも通ってしまう

しかし、パスワードの確認やメールアドレスの一意性は、便利なので、そのままにしたかった。

[参考](https://github.com/heartcombo/devise/blob/master/lib/devise/models/validatable.rb)


## 試した方法

modelに、メールアドレスのフォーマットを指定した。

```ruby:model/user.rb

VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, format: { with: VALID_EMAIL_REGEX }
```

しかし、この方法では、エラーメッセージが重複して表示されてしまう。

## 結論
どうやらdeviseの設定ファイルconfig/initializers/devise.rbで、
メールアドレスのバリデーションだけを指定できたみたい。

```ruby:config/initializers/devise.rb

  # Email regex used to validate email formats. It simply asserts that
  # one (and only one) @ exists in the given string. This is mainly
  # to give user feedback and not to assert the e-mail validity.
  config.email_regexp = /\A[^@\s]+@[^@\s]+\z/

```

これを、指定したい正規表現で書き換えれば、完了。

```ruby:config/initializers/devise.rb

  config.email_regexp = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

```
LINEbotに画像を送信すると、その画像をS3に保存

# 前提
・Lineデベロッパーアカウント開設済み
・LinebotのwebhookにApiGatewayのpostエンドポイント設定済み
・LambdaとApiGatewayの紐づけ
・その他LINE発行のトークンを環境変数に設定やS3へのアクセス権限付与などLambda周り
詳しくは下記記事が参考になります。
https://qiita.com/w2or3w/items/1b80bfbae59fe19e2015

# コード
Lambdaに下記コード記述・デプロイ
<font color="Red">あなたのバケット名はS3のバケット名に変えてください</font>

```lambda_function.py
import os
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.models import (
    MessageEvent, TextSendMessage,
    ImageMessage
)
import boto3
import tempfile
LINE_CHANNEL_ACCESS_TOKEN   = os.environ['LINE_CHANNEL_ACCESS_TOKEN']
LINE_CHANNEL_SECRET         = os.environ['LINE_CHANNEL_SECRET']
LINE_BOT_API = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
LINE_HANDLER = WebhookHandler(LINE_CHANNEL_SECRET)

def lambda_handler(event, context):
    logger.info(event)
    signature = event["headers"]["x-line-signature"]
    body = event["body"]
    
    # 画像を受け取った時に呼ばれるイベント
    @LINE_HANDLER.add(MessageEvent, message=ImageMessage)
    def on_image(line_event):
        logger.info('image event')
        image = LINE_BOT_API.get_message_content(line_event.message.id)
        with tempfile.TemporaryFile() as tmp:
            for chunk in image.iter_content():
                tmp.write(chunk)
            tmp.seek(0)
            s3 = boto3.resource('s3')
            bucket = s3.Bucket('あなたのバケット名')
            try:
                bucket.put_object(
                    Body=tmp,
                    Key=f'{line_event.message.id}.png'
                )
                LINE_BOT_API.reply_message(
                    line_event.reply_token,
                    TextSendMessage(text='アップロードに成功しました')
                )
            except Exception as e:
                logger.error(e)
                LINE_BOT_API.reply_message(
                    line_event.reply_token,
                    TextSendMessage(text='アップロードに失敗しました')
                )
            
    LINE_HANDLER.handle(body, signature)
    return 0
```
分からなかった言葉

#学んだ言葉まとめ
随時更新していきます

##リファクタリング
- ソフトウェアの外部的振る舞いを保ちつつ、理解や修正が簡単になるように、内部構造を改善すること。
- ソフトウェア設計の向上、劣化の防止、理解しやすくするために行う。

##NoSQL(Not only SQL)
- 非リレーショナルなデータベースを表す言葉でデータを表形式で管理する
- RDBではないもの
- 高速な処理を行える
- システムの拡張・分散性が高い

##ORM(Object relational mapping)
- データベースからデータを取得する、取得したデータをオブジェクト化する、データの更新・変更などをデータベースに格納するという機能のまとまりのこと

##RESTAPI（RESTful API）
- そもそもAPI（Application Programming Interface）とはあるソフトウェアの機能や管理するデータなどを外部の
- 他のプログラムから呼び出して利用するための手順やデータ形式などを定めた規約のこと。
- RESTAPIはAPIの１つでRESTと呼ばれる設計原則に従って策定されたもの。
- RESTとは「セッションなどの状態管理を行わず、やり取りされる情報はそれ自体で完結して解釈することができる」「情報を操作する命令の体系が予め定義・共有されている」「すべての情報は汎用的な構文で一意に識別される」「情報の一部として、別の状態や別の情報への参照を含めることができる」の4つの項目からなる原則。

##テック（技術）スタック
- 一つのアプリケーションを構築および実行するのに使用される一連のテクノロジーサービスのこと
- たとえば、ソーシャルサイトのFacebookは、JavaScript、HTML、CSS、PHP、ReactJSなどのコーディングフレームワークと言語の組み合わせで構成されています。それがFacebookの「技術スタック」

##CWE(Common Weakness Enumeration)
- 脆弱性の種類を識別するための共通の脆弱性タイプの一覧

http://cwe.mitre.org/data/definitions/1337.html

https://www.ipa.go.jp/security/vuln/CWE.html

##リセットCSS
- リセットCSSとは、Google ChromeやSafari、Microsoft Edgeなど異なるブラウザを使っても同じようにWebサイトが表示されるためのCSSファイルのことを指します。

##キャメルケース
単語の区切りを大文字にする表記方法
ex) TestUser, UserItem

##スネークケース
単語の区切りをアンダースコア（_）にする表記方法
ex)test_user, user_item

##セマンティクス
言語によって異なるが基本的にはコードの断片という意味。syntaxに対応する言葉
HTMLでは h1というセマンティック要素は「ページの最上位の見出し」という役割を与える。

https://developer.mozilla.org/ja/docs/Glossary/Semantics

##グルー言語
グルー（接着剤）という名の通りソフトウェアコンポーネント同士を結びつけることを主眼としたプログラミング言語の総称。
Perl, Python, Ruby, Lua, C++などが該当する。
例えばPythonは他言語で実装されたnumpyやPandasなどを利用できる。

##パース
一定の規則で記述されたテキストを解析し、プログラムで扱いやすいようなデータに変換する処理のこと。

##LL
Lightweight Languageの略で短い記述で処理を実現でき、手軽に取り扱う事ができるプログラミング言語。PythonやRubyなど

##ガベージコレクション
プログラムが確保したメモリ領域のうち不要になった箇所だけを開放してくれる機能

##WSGI(Web Server Gateway Interface)
WebサーバソフトウェアとPythonで記述されたWeアプリケーションとの標準インターフェース
docker コマンド関連

#Dockerコマンド

##Docker compose
```
コンテナの作成
docker-compose build

コンテナの起動(-dをつけることでバックグラウンドで実行可能)
docker-compose up
docker-compose start

コンテナに入る
docker exec -it コンテナ名 bash(など)

コンテナ名の確認
docker ps

コンテナの停止
docker-compose down
docker-compose stop
```

###起動時の違い
https://qiita.com/tegnike/items/bcdcee0320e11a928d46

###停止時の違い
https://www.ikkitang1211.site/entry/2021/03/09/084833

##Database(MySQL)の操作
```
MySQLに接続
コンテナに入り
mysql -u ユーザ名 -p
パスワードを入力

データベースを表示
SHOW DATABASES;

データベースに接続
USE データベース名;

テーブルを表示
SHOW TABLES;

テーブルの作成
CREATE TABLE users(id int, name varchar(10));

データの挿入
INSERT INTO users VALUES (1, 'test');

データの確認
SELECT * FROM users;

```
terraform error code: 400の対処法

##背景
terraformを使って、構築しようとしたらエラーが発生した。。。
やりたいこととしては、ローカル環境(mac)からAWSにterraformで環境構築したいよねーっていう図式。
対処法を備忘録として記す。

##発生したエラー
まずは発生したエラーについて。
発生したのは以下エラーで、エラーで言われてるsubnet.tf内の問題はなさそう見えたので、原因を突き止めるべくログを出力することに。

```
Error: error creating subnet: InvalidSubnet.Range: The CIDR 'XX.XX.XX.X/24' is invalid.
	status code: 400, request id: XXXXXXXXXXXXXXXXXXXXXXXXXXXX

  on ../subnet.tf line 2, in resource "subnet" "XXX":
   2: resource "subnet" "XXX" {
```

##対処法
###①ググる
ググったら[デバック方法](https://zenn.dev/wim/articles/terraform_ga_katteni_kowareta)が出てきた
これを参考にする

###②ローカルで以下コマンドにより環境変数をセット

```
# export TF_LOG=TRACE 
# export TF_LOG_PATH=hoge.txt ##terraformのログを出力するファイル名とか適当につけた
```

###③tfstateファイルにログが残っていないか確かめる
localで実行している場合、tfstateファイルが以前のdeploy時の情報を持ってしまっている場合がある。
ので、一度削除してもう一度デプロイすると上手くいったりする。

##感想
今回は②を実行することで解決しました
macからsetコマンドだと環境変数設定出来ないことが判明。。
exportコマンドで設定すると良い（戒め）
※後日、③で引っ掛かっていました。反省。

##参考資料
[なにもしてないのに壊れた？Terraformのデバッグ方法](https://zenn.dev/wim/articles/terraform_ga_katteni_kowareta)
[Debugging Terraform](https://www.terraform.io/docs/internals/debugging.html)
[PATHを通すために環境変数の設定を理解する (Mac OS X)](https://qiita.com/soarflat/items/d5015bec37f8a8254380)
[シェル変数や環境変数を削除するコマンド](https://qiita.com/ttokutake/items/c9b466312da8239d11b4)
【Python × SQLite3 × DB Browser for SQLite】 PythonでDBを作成して、中身を確認する

#目的
タイトルの通り。
Pythonにて標準ライブラリsqlite3を使用してデータベースを作成、
DB Browser for SQLiteを使用して中身を確認。



# Pythonにて標準ライブラリsqlite3を使用してデータベースを作成
```make_db.py
# データベースに文章を保存

# ライブラリをインポート
import sqlite3

db_name = "ManyTexts.db"
# データベースを作成
connect = sqlite3.connect(db_name)
cur = connect.cursor()


cur.execute('CREATE TABLE users(id INTEGER, name STRING , birthday STRING)')

# データの挿入
cur.execute("INSERT INTO users VALUES (1, '煌木 太郎', '2001-01-01')")
cur.execute("INSERT INTO users VALUES (2, '学習 次郎', '2006-05-05')")
cur.execute("INSERT INTO users VALUES (3, '牌存 花子', '2017-09-10')")

connect.commit()
connect.close()

```



# 「DB Browser for SQLite」 を使用して中身を確認

1. 「DB Browser for SQLite」 をネットからインストール。バージョンは 3.12.2 (2021/10/1時点最新)
https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.12.2

2. 「DB Browser for SQLite」 をPCのアプリケーションへ移動させる

3. 作成したデータベース(ManyTexts.db)上で右クリック,「DB Browser for SQLite」 を使い開く
![スクリーンショット 2021-10-01 19.21.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/764557/a73beace-ddfb-a49b-b9ee-5731e827d9d6.png)

4. データベースのテーブル名(user)を指定する
![スクリーンショット 2021-10-01 19.23.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/764557/73bc8fd5-ae01-4f81-42a9-f556182ac4be.png)