OmniAICreator/Qiita-1.07M huggingface dataset:
GoogleSpreadSheetをPythonで操作する





JASONキーのファイルを開いてClient_emailの値を取得

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346533/a2e3ca5e-3dbb-2461-41d2-3e4667c0649f.png)



該当のスプレットシートを開いて共有ボタンを押す
先ほどのClient_emailを貼り付ける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346533/76bc832e-a8e0-27db-07b2-103b00a8ebf5.png)

リンクをコピーしておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346533/af1192f9-e9e6-7d78-7cde-92616a70a883.png)


###Pythonの環境にインストール

```hoge.php
pip install gspread
pip install oauth2client
```

###jsonfile名とスプレットシートのkey





JSONファイルは実行ファイルと同じ場所に配置する

```hoge.py

import gspread
import json
from oauth2client.service_account import ServiceAccountCredentials

# (1) Google Spread Sheetsにアクセス
def connect_gspread(jsonf,key):
    scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive']
    credentials = ServiceAccountCredentials.from_json_keyfile_name(jsonf, scope)
    gc = gspread.authorize(credentials)
    SPREADSHEET_KEY = key
    worksheet = gc.open_by_key(SPREADSHEET_KEY).sheet1
    return worksheet

# ここでjsonfile名と2-2で用意したkeyを入力
jsonf = "~~~~~~~.json"
spread_sheet_key = "aaaaaaaaaaaaaa"
ws = connect_gspread(jsonf,spread_sheet_key)

#(2) Google Spread Sheets上の値を更新
#(２−１)あるセルの値を更新（行と列を指定）
ws.update_cell(1,1,"test1")
ws.update_cell(2,1,1)
ws.update_cell(3,1,2)

#(２−２)あるセルの値を更新（ラベルを指定）
ws.update_acell('C1','test2')
ws.update_acell('C2',1)
ws.update_acell('C3',2)

#(2-3)ある範囲のセルの値を更新
ds= ws.range('E1:G3')
ds[0].value = 1
ds[1].value = 2
ds[2].value = 3
ds[3].value = 4
ds[4].value = 5
ds[5].value = 6
ds[6].value = 7
ds[7].value = 8
ds[8].value = 9
ws.update_cells(ds)

```

```hoge.py
#--- n列目をすべて取得して値を1つずつ出力 ---
col_list = ws.col_values(1)
for data in col_list:
    print(data)
```
##大量にデータを書き込む場合はupdate_cellsを利用する
データを大量に書き込む場合、途中で以下のようなAPIエラーが発生することがある。

```
raise APIError(response)
gspread.exceptions.APIError: {
  "error": {
    "code": 429,
```
その時はupdate_cellsを利用して書き込み回数を減らすようにしましょう。

```hoge.py
       cell_list = ws2.range('A'+str(i)+':P'+str(i))

        cell_list[0].value=homepage
        cell_list[1].value=title
        cell_list[2].value=price
        cell_list[3].value=surl
        cell_list[4].value=area
        cell_list[5].value=service
        cell_list[6].value=copy
        cell_list[7].value=comment
        cell_list[8].value=clock
        cell_list[9].value=tel
        cell_list[10].value=created_at
        cell_list[11].value=updata_at
        cell_list[12].value=sogo
        cell_list[13].value=point
        cell_list[14].value=premium
        cell_list[15].value=tipe
       
        ws2.update_cells(cell_list)

```
###ループを利用する場合

```hoge.py

cell_list = ws2.range('A'+str(i)+':P'+str(i))

for cell in cell_list:
    cell.value = 'fuga'
sheet.update_cells(cell_list)

```



参考：
https://qiita.com/164kondo/items/eec4d1d8fd7648217935

https://tanuhack.com/library-gspread/

https://www.fastclassinfo.com/entry/python_data_syukei#%E3%82%B9%E3%83%86%E3%83%83%E3%83%972%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%8B%E3%82%89%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E5%8F%96%E5%BE%97
ArchLinuxでのR環境構築（備忘録）

## インストール(Intel MKLを使わない場合)
- r: R本体
    - `sudo pacman -S r`
- gcc-fortran: CRANパッケージをコンパイルする際に必要になることがある 
    - `sudo pacman -S gcc-fortran`

## インストール(Intel MKLを使う場合)
行列演算等を頻繁に行う場合は、MKLを使用することで高速に計算できる

- intel-mkl: Intel math Kernel Library
    - `yay -S intel-mkl`
- r-mkl: MKL対応(マルチスレッド対応&Intelプロセッサ向けに最適化)したR
    - `yay -S r-mkl`
    - 備考: 既に`r`がインストールされている場合、`r`は削除する
        - `:: r-mkl と r が衝突しています。r を削除しますか？ [y/N] ` -> y


### 確認

```
$ R

R version 4.0.5 (2021-03-31) -- "Shake and Throw"
Copyright (C) 2021 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

R は、自由なソフトウェアであり、「完全に無保証」です。 
一定の条件に従えば、自由にこれを再配布することができます。 
配布条件の詳細に関しては、'license()' あるいは 'licence()' と入力してください。 

R は多くの貢献者による共同プロジェクトです。 
詳しくは 'contributors()' と入力してください。 
また、R や R のパッケージを出版物で引用する際の形式については 
'citation()' と入力してください。 

'demo()' と入力すればデモをみることができます。 
'help()' とすればオンラインヘルプが出ます。 
'help.start()' で HTML ブラウザによるヘルプがみられます。 
'q()' と入力すれば R を終了します。 

> 
```

ok.

### パッケージの更新
- Rセッション内で更新: `update.packages(checkBuilt=TRUE)`
    - 以下のエラーが出たら、`sudo chmod -R 777 /usr/lib/R/library` で権限を変更し、再実行（私用PCのみ推奨）
        - `'lib = "/usr/lib/R/library"' は書き込み可能ではありません` 


## VSCodeでの設定
- VSCode拡張機能の導入
    - R
    - R LSP Client
- R Language Serverのインストール
    - Rセッションでインストール: `install.packages("languageserver")`
- radianのインストール
    - radian: リッチなシンタックスハイライトを備えたコンソール。ipythonやjuliaに似ているそう。
    - pipでインストール: `pip install -U radian`
    - [option] エイリアスを設定: `alias r="radian"`

### Settingsへ反映
- `R › Rpath: <OS>` に "通常" のRのパスを記述
    - 例: `/usr/lib/R/bin/R`
- `R › Rterm: <OS>` には "radianを含む" Rのパスを記述
    - 例: `/home/<username>/.local/bin/radian`
- グラフをVSCode内(同一ウィンドウ)に描画するため、`r.sessionWatcher` は `true` にしておく

### テスト
- VSCodeで簡単なコードを書いてみる
    - `Ctrl + Enter`: 現在の行を実行
    - `Ctrl + Shift + Enter`: ソースコード全体を実行

``` r
r$> # 一様分布から
r$> runif(5, min = -1, max = 1)
[1]  0.1438143  0.5091703  0.8834975 -0.4026284  0.8865723

r$> # 正規分布から
r$> rnorm(5, mean = 3, sd = 2)
[1] 3.31243677 3.23406731 0.06873435 2.11458855 4.96647989

r$> # 可視化
r$> plot(sin, -3 * pi, 3 * pi)
```
![plot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300536/40ab7ccc-6779-99b0-fa2b-7319f347ae4b.png)

---


簡単なコーディングの際はbashから`r`(radian)を用い、ガッツリ書くときはVSCodeで開発するようにする。

## 参考
- [ArchWiki - R](https://wiki.archlinux.jp/index.php/R)
- [Qiita: Visual Studio Codeを使ったR言語開発環境の利用ガイド (応用編)](https://qiita.com/Ikuyadeu/items/ac8f0852a953829151dd)
- [A fresh start for R in VSCode](https://medium.com/analytics-vidhya/a-fresh-start-for-r-in-vscode-ec61ed108cf6)
『変動係数』を20億1番目ぐらいに発明してしまった。ダメ。。。

# 概要
先日、複数の項目のデータの分析をしていて、標準偏差とかでは目的に合致せず、試行錯誤し、<font color="orange">**変動係数**</font>を発明した。
**このとき発明したので、名前は後から知りました。**
20億2回目の発明を阻止するために、記事にします。

# 変動係数とは
wikipediaによると、

<font color="orange">**変動係数**</font>

以下、wikipedia引用

（引用元：https://ja.wikipedia.org/wiki/%E5%A4%89%E5%8B%95%E4%BF%82%E6%95%B0）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/7c517c72-04fb-449c-add9-48a5d0f02274.png)


とのこと。

# Scipyでは一発

リンゴ（1個）とバナナ（1房）の重さの変動係数を比較しました。
リンゴのほうが、ばらつきが小さかったです。架空の問題です。

**numpyとscipyの両方で計算しました。ともに、<font color="blue">1行</font>で計算できます。scipyは、関数1個。**


```python
import numpy as np
from scipy.stats import variation

ringo=[251,230,300,280,290,261,273,253,243]#1ko(gram)
banana=[820,1050,631,950,945,809,810,923,830]#1fusa-4hon(gram)

cv_ringo_np = np.std(ringo)/np.mean(ringo)
cv_banana_np = np.std(banana)/np.mean(banana)

cv_ring_sci = variation(ringo)
cv_banana_sci = variation(banana)

print(cv_ringo_np, cv_ring_sci, cv_banana_np, cv_banana_sci)
```

```
0.08167729886624266 0.08167729886624266 0.13116523617182338 0.13116523617182338
```

#まとめ
特にありません。
知らないことが多くてしんどいっちゃ、しんどいですね。。。。:candy:
仮想環境Linux上の共有フォルダへのアクセス

sambaを使ってホストOSから仮想OS上の共有フォルダにアクセスするまでのメモ。
あとはgitを使うなり、svnを使うなりで好みの環境を構築。

仮想環境の設定はよく忘れるので。
既存の記事もあるけど、古くなって構成が結構異なることなることがあるので。

※身内用。
※最短手順を目指して。
※間違えていたらごめん。

#対象環境
* ホストOS
    * Windows10 pro
* 仮想OS
    * Ubuntu18.04（Ubuntu16.04でも確認済み）
* 仮想化ソフトウエア
    * Oracle VirtualBox

#前提
* VirtualBoxインストール済
* 仮想OSセットアップ済

#Virtual Box設定
###ネットワークアダプタ追加
デフォルトだとアダプタ1のみ有効なので、アダプタ2を追加する。
![スクリーンショット 2021-04-24 193543.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1384790/f5a80aae-21b1-9478-aebf-0ea1f92eed0f.png)



#仮想OS編（Ubuntu18.04）

##sambaのセットアップ
インストールから起動まで

###1. インストール
```terminal:nautilus
~$ sudo apt install samba
```

###2. インストール確認
バージョンを表示できるかで確認

```terminal:nautilus
~$ smbd --version
```

###3. コンフィグファイルを更新
共有フォルダ設定

```terminal:nautilus
~$ vi /etc/samba/smb.conf
```
以下の記述を追加（ユーザ制限はかけない）

```conf:smb.conf
[share_dev]
    path = /home/share
    writable = yes
    guest = yes
    guest only = yes
    create mode = 0777
    directory mode = 0777
    share modes = yes
```
* __[share_dev]__はホストから見た時の共有フォルダ名
* __path = /home/share__はUbuntu上の共有フォルダにしたいディレクトリパス

変更はお好みでどうぞ。

###4. コンフィグファイルの正当性チェック
```terminal:nautilus
~$ testparm /etc/samba/smb.conf
```
WARNINGは出ても動く。
ERRORが出なければOK。

###5. 仮想OS再起動
サービスの起動/再起動はめんどうなので。
OS起動時サービス有効化設定もデフォルト有効みたい。

###追記
今はこうみたい。

```terminal:nautilus
~$ sudo service smbd restart
```

###補足
ホストOSから接続する先のIPをメモしておく。

```terminal:nautilus
~$ ip addr
```
loopback含めて3つ表示されるはず。
その内、loopback以外のどっちか。
※デフォルトは"192.168.56.101"が割り当てられるみたい。

#ホストOS編（Windows10）
エクスプローラーからメモしたURLにアクセスするだけ。

![スクリーンショット 2021-04-24 201216.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1384790/95d05947-2583-bc71-5727-9fd04940d9fe.png)

以上。終わり。
【初学者目線】Dockerの環境構築の際に意味分からんかった用語たち

# この記事なに？
WindowsでDockerの環境構築をイチからしようとした際に分からなかった用語を初学者の目線で解説する

* ターミナル (Windows Terminal)
* シェル (Widows PowerShell)
* テキストエディタ (VSCode)
* バージョン管理ツール(Git)
* WSL2

# ターミナル (Windows Terminal)
windows向けのターミナルだ

####は？ターミナルってなんやねん
コマンドでPCの操作とか設定ができるソフトウェアだよ。

普段はデスクトップにあるアイコンをクリックしてブラウザとかを起動してるけど、こういうことを文字入力でできるぞ。

趣味とかの範囲でパソコンを使う人には不要だけど、高度な設定をするときとかプログラミングをする人には必須だぞ。

ちなみにWindowsには、**コンソール(conhost.exe)**というターミナルが標準装備されてるけど、それよりスゲーのがWindows Terminalだ

ちなみに検索していくと**ターミナル**やら**コンソール**やら出てくるが、
**ターミナル＝コンソール**だ

ただし、ターミナルがPCの操作とかをしているわけではなく、あくまでガワだけ。
次項で説明するシェルなどを操作するためのGUIだ！

#シェル(Widows PowerShell)
PCに命令を送ってるのは、実はターミナルではなくこの**シェル**だ！
人間が直接PCに命令するのがムズいからコイツが仲介役になってくれてるというイメージだ！

元から入っている**コマンドプロンプト(cmd.exe)**よりスゲーのがコイツ


# テキストエディタ (VSCode)
Visual Stadio Code
超便利なテキストエディタだ
Windowsに元から入っている**メモ帳**をより便利にしたソフトウェアだぞ

#Git
ソースコードを差分(バージョン)管理するツール
これを使えば、間違ったときに前のバージョンに戻せるし、変更したときには変更内容が分かるぞ

みんな大好き**GitHub**はこのツールをオンライン上で使えるようにするためのサービスだ！

#WSL 2
Windows Subsystem for Linux 2
その名のとおり、Windows上でLinuxを動かすためのツールだ！

#####そもそもなんでLinuxを動かしたいん？Windowsだけじゃダメなん？
できなくはないけどめっちゃやりにくい（コマンドが長かったりとか）
まあそもそもDockerはLinux上でしか起動しないよ
MicronautのSession Cookieの設定方法

# やりたいこと

MicronautでSessionベースの認証の仕方については、[Micronaut SecurityのSession項目](https://micronaut-projects.github.io/micronaut-security/2.1.0/guide/index.html#session)に記載されている.

しかし、発行されるCookieの設定(name, path, expire, samesiteなど)について設定したいのに、設定方法が記載されていない.
JWTについては、記載されているのに記載されていないので、どうやれば設定できるかを調べたので説明します。


# 設定方法

調査すると、HttpSessionに関しては、HttpSessionConfigurationというのがあり、これは、CookieConfigurationインタフェースを実装しているので、これの設定方法が分かればいいことがわかります。

HttpSessionConfigurationは、`@ConfigurationProperties(value="http")`となっているので、httpのキー配下にCookieConfigurationの項目を設定すればいいことがわかります。

また、HttpSessionConfigurationは、SessionConfigurationを継承しており、SessionConfigurationは`@ConfigurationProperties(value="micronaut.session")`となっているので、micronaut.session.httpに設定すればいいことがわかりました。
実際に試してみます。

### 未設定の場合(デフォルト)

```bash
$ curl -X POST -i \
> -H "Content-Type: application/json" \
> -d '{"username": "test", "password": "test"}' \
> http://localhost:8080/login

HTTP/1.1 303 See Other
Location: /login-success
Authorization-Info: 44e65657-e86b-4215-9f83-4edd4ae22ea0
set-cookie: SESSION=NDRlNjU2NTctZTg2Yi00MjE1LTlmODMtNGVkZDRhZTIyZWEw; Path=/; HTTPOnly
Date: Sat, 24 Apr 2021 11:12:18 GMT
connection: keep-alive
transfer-encoding: chunked
```

キー名は、SESSIONでPathは/で、HTTPOnlyが設定された状態です。


### 設定した場合

```yaml:application.yml
micronaut:
  session:
    http:
      cookie-name: MYSESSION
      cookie-path: /api/
      cookie-secure: true
      cookie-same-site: Strict

```

```bash
$ curl -X POST -i \
> -H "Content-Type: application/json" \
> -d '{"username": "test", "password": "test"}' \
> http://localhost:8080/login

HTTP/1.1 303 See Other
Location: /login-success
Authorization-Info: b628cd4c-3e77-4daa-9860-8ed686fe40dd
set-cookie: MYSESSION=YjYyOGNkNGMtM2U3Ny00ZGFhLTk4NjAtOGVkNjg2ZmU0MGRk; Path=/api/; Secure; HTTPOnly; SameSite=Strict
Date: Sat, 24 Apr 2021 11:09:50 GMT
connection: keep-alive
transfer-encoding: chunked
```

無事にキー名がMYSESSIONとなり、Path, Secure, SameSiteの設定を付加することができた。
Autodesk Inventor API Hacking (C#9.0)

# 0. はじめに
[Freeradical](https://www.freeradical.jp)の中の人、[yamarah](https://qiita.com/yamarah)です。
[Autodesk Inventor API Hacking (C#8.0、そして.NET Core3.0)](https://qiita.com/yamarah/items/06bb1a67c88ad85277e2)の続きで、C#9.0は使えるのか、検証します。

# 1. C# 9.0
## 1.1 C#8.0 → C#9.0に切り替える
結論を言うと、C#9.0に出来ました。変更は簡単で、Projectの`<LangVersion>`を書き換えるだけです。

```xml
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Library</OutputType>
    <TargetFramework>net472</TargetFramework>
    <RootNamespace>InvAddIn</RootNamespace>
    <LangVersion>8.0</LangVersion>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  (以下、続く)
```
これを、

```xml
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Library</OutputType>
    <TargetFramework>net472</TargetFramework>
    <RootNamespace>InvAddIn</RootNamespace>
    <LangVersion>9.0</LangVersion>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  (以下、続く)
```
とするだけです。

## 1.2 何が変わるの?
大きくは変わりません。と言うのも、InventorのAddInを書く限りは.NET Frameworkを使い続ける必要があり、.NET Coreで有効になる多くの新機能が使えないのです。
**25.01.04追記**
Inventor2025からNET8に移行しました。
[Autodesk Inventor API Hacking (Inventor2025からの注意)](https://qiita.com/yamarah/items/00ddee874dbcf5241c43)も参照してください。
**25.01.04追記終わり**
数少ない.NET Frameworkでも使える新機能で有用なのは、オブジェクト初期化の簡略化です。以下のように書けるようになりました。

```c#
Dictionary<int, string> Table = new();  // 右辺を省略できる
// 今までは、こう書いていた。
//Dictionary<int, string> Table = new Dictionary<int, string>();
// もしくは、varが使える場面では、
//var Table = new Dictionary<int, string>();
```
また、些細ですが型によるswitchが出来るようになりました。

``` c#
switch (sketchEntity)
{
// C#8.0では'種類のパターン'が使えないので、次のように書く必要があった。
//  case SketchLine _:
    case SketchLine:
        message = "Line";
        break;
//  case SketchArc _:
    case SketchArc:
        message = "Arc";
        break;
    default:
        break;
}
```
# 99. 親の記事に戻る
[Autodesk Inventor API Hacking (概略)](https://qiita.com/yamarah/items/cee08eb8f2b7aecbda83)
CodiMDで書く設計書が便利、でも残念なことも

# 最近CodiMD というOSSを知った。
仕事でソフトウエアの設計書や、簡単な取り扱い説明を作ることが多いが
下記のような情報をもつ資料を作ろうとすると、WordやExcelを使うことになり、
結構ストレスを感じる。

1. 説明文
2. 画像( 画面ダンプ )
3. UML図( シーケンス図やクラス図 )

この Qiita のエディタのような感覚で使える資料作成エディタがあればいいのだが。
ただ、Qiitaでもまだちょっと問題がある。

1. 説明文 --> Markdownで快適
1. 画像   --> 画面ダンプをとって、エディタにCtrl-Vで貼り付けられる
1. UML図  --> これは無理なのかな。Qiitaに慣れていないので何とも。
1. (**追加課題**) --> ネットワーク越しのせいか、気持ちエディタの反応が鈍い時がある
1. (**追加課題**) --> 仕事の設計資料を全世界に公開するリスクがある( Trelloの件もあるし人為ミスも怖い)

# CodiMDが便利そうだ
リンク : [CodiMD](https://github.com/hackmdio/codimd)
もともとは有償サービスの[HachMD](https://hackmd.io/)を模したOSSらしい。
ライセンスは AGPL なのでそのまま社内で使う分には問題なさそう。

## Markdownベース

1. 説明文 --> Markdownで快適
1. 画像   --> 画面ダンプをとって、エディタにCtrl-Vで貼り付けられる
1. UML図  --> 下でシーケンス図を紹介するがテキストベースでUML図を記述できる。
1. ネットワーク --> 社内イントラ内なら遅くないだろう。自分用メモならローカルPCでも可。
1. オンプレ構築だから社外流失事故も安心。

### シーケンス図を描いてみた。
JavaScriptライブラリの種類があって、何通りかかけるようようだが、快適そう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1384978/b1c7ad8f-a005-02cf-aae9-16e19134a994.png)

### ほかにもすごいことが
PDFを出力できる。もう、WordやExcelをPDFにして客先提出とかいらなんじゃないか...

#### ちょっと残念なこと
PDF出力はベータ機能なのかいくつか問題がありました。

1. Markdownの表に罫線がでない
1. シーケンス図が 図のほうではなく、テキストを出力してしまう。

また、記事の検索については

1. 自分が作った記事か、ほかの人が公開した記事のURLを直接みないと後で検索できない
1. 検索は記事のタイトルだけ

あと、画像以外の添付ファイル( PDF とか Excelとか )をuploadできない。

このあたりが改善されると非常にいいツールになると思う。

## とりあえず CodiMDを使ってみよう
Dockerを使うとあっという間に自分のPCにインストールできます。
[ 準備 ]
  Windows10 にDocker for Windows]をインストールしておいてください。
  最近は Windows10Proでなく Windows10Home でも Docker for Windows をインストールできるようになりました。
　[インストールの参考サイト](https://docs.docker.jp/docker-for-windows/install.html)
  ほかにも様々な情報がネット上を検索すれば見つかるでしょう。

[ CodiMDのインストール方法 ]
  [CodiMDのサイトのインストール手順](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-docker-deployment)にある 下記の26行を docker-compose.ymlというファイルに保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1384978/be0970ae-bc77-b4a3-6be5-e30eef88fd7a.png)
・(注1) 7行目と15行目は postgresqlのパスワードで適当に変えておいたほうが良いでしょう
・(注2) PDF出力で日本語を出したいときは 13行目を 2.2.0-cjk にしましょう。CodiMDのサイトのインストール手順にも記述があります。
・(注3) Linux上のdockerで動かす場合は、インストール手順のパーミッション設定をしないと画像をuploadできないのでご注意ください。


  あとは Windowsのコマンドプロンプトで上記の docker-compose.yml のあるディレクトで下記を実行するだけ。

```shell:docker-compose起動
docker-compose up -d
```
初回起動だけ Dockerイメージのダウンロードで時間がかかりますが、下記のようにコンテナが2つ起動したら完了。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1384978/a521aaed-a0ef-3650-16ab-90270051af35.png)

停止するときは stop です。
```shell:docker-compose停止
docker-compose stop
```

これだけです。では http://localhost:3000/ にアクセスして CodiMDを堪能下さい。
最初は「サインイン」からユーザー登録して、改めて「サインイン」してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1384978/52ac6682-0da1-fe6d-e943-c17f577eab1f.png)

以上。
ディレクトリ階層内に存在する重複ファイルを検索（シェルスクリプト）

こんにちは。
ディレクトリ階層内の重複ファイルを検索しました（シェルスクリプト）。ファイル名ではなく md5 値が等しい重複ファイルを探します[^1]。```uniq -f1 -D``` を使っていますが、その際にファイル名が blank space を含む場合へ対処しています（```uniq_duplicate_f```）[^2]。

出力は、[fdupes](https://github.com/adrianlopezroche/fdupes), [jdupes](https://github.com/jbruchon/jdupes) コマンドに似せて、重複グループ間を空行で区切っています。GNU find, GNU uniq を用いています。

ただし実用性(?)よりも、「シェルスクリプト＋パイプライン」で実現させる試みの意図が少々強いので悪しからず。

[^1]: 参考：「[指定ディレクトリ階層内に存在する重複ファイルを検索（ファイル名およびサイズが等しい条件）](https://qiita.com/kkdd/items/b4855631421e239a2a83)」
[^2]: ```guniq -f1 -D``` を使っており、```-f1``` でスキップを使っています。ファイル名の blank space がその対象にならないように、直前に ```tr ' ' '\0'``` を行なって回避しています。

```console
$ ./fdupes.sh
./memo.txt
./memo/memo.txt
```

```fdupes.sh
#!/bin/sh

dir="."
size="0c"
TAB=$(printf '\t')

# functions
size_csum_f() {
  file="$1"
  siz=$(wc -c "$file" | awk '{print $1}')
  csum=$(md5sum "$file" | awk '{print $1}')
  printf "%s\t%s\t%s\n" "$file" "$siz" "$csum"
}

uniq_duplicate_f() {
  tr ' ' '\0' |
  sort -t"$TAB" -k2nr |
  guniq -f1 -D |
  tr '\0' ' '
}

# main
gfind $dir -size +"$size" -type f -printf "%p\t%s\n" |
  uniq_duplicate_f | cut -f1 |
  while read -r file; do size_csum_f "$file"; done |
  uniq_duplicate_f | 
  while read -r line;
    do
      size_csum=$(echo "$line" | cut -f 2-3);
      [ "$size_csum" != "$prev" ] && echo;
      prev="$size_csum";
      echo "$line" | cut -f1;
    done 
```
PHPの基本操作⑤ 「クッキーとセッションの保存と取得」

##参考書籍
よくわかるPHPの教科書 PHP7対応版

##他記事リンク
- [PHPの基本操作①<br>「簡単な出力と構文、配列、連想配列、少数、フォーマット」](https://qiita.com/kunrenyouAcount/items/7a3bb6e5769ba94a7dc5)

- [PHPの基本操作②<br>「ファイルの読み込み、ファイルの書き込み、XMLの読み込み、JSONの読み込み」](https://qiita.com/kunrenyouAcount/items/bec393cae5901e32ec70)

- [PHPの基本操作③<br>「入力欄、ラジオボタン、チェックボックス」](https://qiita.com/kunrenyouAcount/items/1c66ccee97c33f320fb2)

- [PHPの基本操作④<br>「数字かどうかの判定、正規表現、別ページにジャンプ」](https://qiita.com/kunrenyouAcount/items/5b292d8481a76386fd1e)

- [PHPの基本操作⑤<br>「クッキーとセッションの保存と取得」](https://qiita.com/kunrenyouAcount/items/7324fad1d3d1845de075)

- [PHPの基本操作⑥<br>「電子メールの送信」](https://qiita.com/kunrenyouAcount/items/2172f03af0d8d8a32cc6)

- [PHPの基本操作⑦<br>「ファイルアップロードの受信をする」](https://qiita.com/kunrenyouAcount/items/dece31f962472fb23610)


##クッキー(Cookie)

ログイン画面などで次回アクセス時に自動的に入力された状態にするなどのデータベースには保存しないけれど中長期的に保存しておきたいデータなどに使用する機能です。ブラウザを起動しているときだけ保存したいデータにはセッションを使います。

###データを保存する

クッキーにデータを保存するにはsetcookie関数を使います。

```:データをクッキーに保存する
setcookie(クッキー名, 値, 保存秒数, フォルダ, ドメイン, セキュア接続のみ, HTTPのみの接続);
```

3番目の引数まで指定すれば、関数は使用することができます。
４番目以降の引数は、セキュリティに関する設定です。

- フォルダ：　ここで設定したフォルダ配下でのみ有効になります
- ドメイン：　 ここで設定したドメイン配下でのみ有効になります
- セキュア接続のみ：　SSL接続でのみ有効になります
- HTTPのみの接続：　JavaScriptなどからはアクセスできなくなります

```php:before.php
<?php
  $value = '変数に保存した値です';
  setcookie('save_message', 'Cookieに保存した値です', time() + 60 * 60 * 24 * 14);
?>

<p>Cookieに値を保存しました。次のページに移動してみましょう。
<a href="/sample24/after.php">page02へ</a>
```

###データを取得する

保存した値を取得するには$_COOKIE関数を使います。

```:クッキーに保存されているデータを取得する
$_COOKIE[クッキー名];
```

```php:after.php
変数の値: <?php print($value); ?>
Cookieの値: <?php print($_COOKIE['save_message']); ?>
```

##セッション(Session)
ログイン後にログイン中であることを保存するなどのブラウザを開いている間だけデータを保存しておくための機能です。ブラウザを閉じても利用する場合には、クッキーを使います。

###データを保存する
セッションは保存する場合も取得する場合も、session_start関数を先に使います。
セッションを保存する場合には、$_SESSION関数を使います。

```php:データをセッションに保存する
session_start()
$_SESSION[セッション名] = 値
```

```php:before.php
<?php
  session_start();
  $_SESSION['session_message'] = '値をセッションに保存しました';
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>セッション</title>
</head>
<body>
  <pre>
  セッションに値を保存しました。次のページに移動してみましょう。&raquo; <a href="after.php">afterページへ</a>
  </pre>
</body>
</html>
```

###データを取得する

セッションに保存してある値を取得する場合も保存する場合と同様に使います。

```php:セッションに保存されているデータを取得する
session_start();
$_SESSION[セッション名]
```

```php:after.php
<?php session_start(); ?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>セッション</title>
</head>
<body>
  <pre>
  セッションの値： <?php print($_SESSION['session_message']); ?>
  <?php session_unset(); ?>
  </pre>
</body>
</html>
```

###データを削除する

今回は使用していませんが、明示的にセッションに保存されているデータを削除する場合にはunset関数を使用します。

```:セッションに保存されているデータを削除する
unset($_SESSION[セッション名]);
```
FileMakerのボタン、アイコンとテキストのズレはフォントで解消

初めまして！
私は田舎の小さなデイサービスで事務員をやっています。

FileMakerを専門の仕事にしているわけではなく、間違った点があるかもしれませんが、その際は問題点を教えてくださるととても嬉しいです。



#ボタン設定でアイコンとテキストがズレる
FileMakerで最もイケてないところ、それがこのズレるボタン。
ボタンをレイアウト上に配置するとき、最もイライラする問題ですよね。
マージンを調整するもアイコンも一緒にマージンされて効果がなく、いっそのことアイコンとテキストを別々にレイアウトに配置する方も。

実はこの問題、フォントを変えるだけで解決します。
![IMG_2320.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568792/223e7ecf-cc10-c17a-7ab3-98cf2f33b2ff.jpeg)
美しぃぃぃぃいいいいいい
ど真ん中！！！
(この画面はFileMakerGo、iPadでスクショ撮った画像です)

#源ノ角ゴシック
使用しているフォントが "源ノ角ゴシック" と言われるフォントです。
AdobeとGoogleの共同制作したフォントで、無料で提供されており、尚且つオープンソースです。
そのため、後述しますが、有志の方がカスタマイズしたフォントを公開して下さってます。(源柔ゴシック等)

ヒラギノ角ゴと比べ、源ノ角ゴはやや字体が太く、若干クラッシックな書体ですが、これもまた信頼感があって良いのではないでしょうか。

#PCに入れる
そのままフォントをDLしてインストールするだけです。
インストール後はFileMakerの再起動をお忘れなく！

https://forest.watch.impress.co.jp/library/software/source_hansan/

が、

注意点が一つ。
これは "海外が" 作ったフォントです。
邦題が "源ノ角ゴシック" なのであって、
オリジナルのタイトルは、"Source Han Sans" です。
なので、FileMaker内でフォントを選ぶ際、"G" ではなく "S" の範囲に存在しています。
(ただ "S" の範囲にはありますが、フォント名は "源ノ角ゴシック" または "源ノ角ゴシック JP" で存在しています)



#iPadに入れる
AnyFontというアプリを使ってフォントの設定をします。

https://apps.apple.com/jp/app/anyfont/id821560738

1. App StoreにてAnyFontをDL
2. macOSならAirDropで、窓ならメール等でフォントをiPadに送る。
3. iPadでフォントを開こうとすると "どれで開きますか？" 系のダイアログが出てくるので、AnyFontを指定。
4. 指定後、AnyFont内へフォントがコピーされる。
5. コピーされたフォント名をタップすると、設定Appにフォントのプロファイルが保存される。
6. あとは、設定Appを起動して、プロファイルをインストール。

という流れです。

フォント設定自体は至極簡単ですが、ウェイト分(Regular、Bold等)同じ作業をしないといけないのがちと面倒でもあります。
(初投稿で画像が一枚しか投稿できないことが悔やまれる…)



#源ノ角ゴは何故ズレないのか？
おそらくですが、海外が作った日本語フォント、というところが味噌なんだと思います。
折角なので、ここに至った経緯とともに推測してみます！

アイコンとテキストがズレる問題、
この問題にずーっと頭を悩ませていたのですが、

https://fm-aid.com/bbs2/viewtopic.php?id=9221

をみて、どうやら欧文フォントでは起きない現象ということを知りました。
そうなんです。欧文フォントではみられない現象なのです。
ということは、もしかすると、海外で作成された日本語のフォントであれば、欧文フォントと同じ働きをするのではないか！？と風呂場でひらめき、そこで、イラレでよく使用していた源ノ角フォントを設定してみると、うまく行った。という経緯です。

また、Appleが出している、SanFranciscoフォントも同じ働きをします。
これもApple(海外)が出している、日本語込みのフォントですから、ズレは生じません。
ですが、たまにiPadでは反映されないことがあり、お勧めしません。
(個体差があるのかもしれませんが)


<details><summary>**カスタマイズフォント**</summary>
源柔ゴシック
角丸、やや角丸を御所望の方は是非是非！
個人的には源柔ゴシックLがお淑やかで好きです。
http://jikasei.me/font/genjyuu/

<details><summary>**バリアフルフォント**</summary>
因みにですが、つい最近源ノ角ゴシックがバリアブルフォントになりました。
https://github.com/adobe-fonts/source-han-sans/tree/release/Variable
一つのフォントファイルだけでウェイトが自由に指定でき、容量も軽く大変便利です。
ただし注意点があります。
iPadでバリアブルフォントを対応していない(?)ようですので、プロファイルのインストールができません。
FileMakerGo愛用者の方々はご注意ください。
PCでは使用できます(バリアブルではないですが)
【Linuxコマンド】コマンド操作の履歴を確認できる「historyコマンド」

##  historyコマンド
historyコマンド使っていますか？

```
$ history
  444  git branh
  445  git branch
  446  git co master
  447  git co develop
  448  git co master
  449  git pull origin master
  450  git co develop
  451  git branch
  452  git co develop
  453  git branch
  454  git branch
  455  git co develop
  456  git branch
  457  git branch

```
historyコマンドというものをご存知でしょうか？
このコマンドを入力すると、番号が付与された状態でこれまでのコマンド操作の履歴を確認することができます。

このコマンドは、自分がどんな手順でコマンド操作を行なったのかを振り返ることができるので、自分で業務外に勉強をしたときや先輩エンジニアにレクチャーを受けた時に振り返りができるので大変便利なコマンドです。

このhistoryコマンドにもたくさんのオプションが存在するみたいなので興味がある方はググってみてください。

## 参考記事
[【 history 】コマンド――コマンド入力の履歴を表示、再利用する](https://www.atmarkit.co.jp/ait/articles/1710/20/news015.html)
Mecanim をなるべく使わない Animator メモ

# 方法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307985/61f74a48-63f2-e3f0-92fb-8ea91298101d.png)
Mecanim に State を並べて配置し、スクリプトから State名 を指定してアニメーションさせる。

# 再生・停止
``` C#
//再生
animator.Play("Run");
//一時停止
animator.speed = 0f;
//続きから再生
animator.speed = 1f;
//はじめから再生
animator.Play("Jump", レイヤー番号, 0 (開始地点) );
```

# 遷移
``` C#
animator.CrossFade("Run", 遷移時間, レイヤー番号, 遷移先の開始時間 );
```

# ブレンド
レイヤーで疑似的にブレンドできるが管理が大変になるため、BlendTree を推奨する。

``` C#
//BlendTree を使う際のスクリプト
animator.Play("Run");
animator.SetFloat("Speed", 割合 );

//レイヤーを使う際のスクリプト
animator.Play("Walk");
animator.Play("Run", レイヤー番号 );
animator.SetLayerWeight( レイヤー番号, 割合 );
```

# レイヤーについて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307985/1a3e29eb-dbfb-69df-1c29-54212f287b78.png)

|項目名|説明|
|-|-|
|Weight|合成の割合|
|Mask|部位ごとにアニメーションを上書き・加算|
|Blending|合成方法|
|Sync|指定したレイヤーと State 群を同期し、アニメーションのみ変更する。状態異常で全体のアニメーションを変更したい時などに有用。|
|Timing|アニメーションの長さを調整可能にする|
|IK Pass|コールバック関数「OnAnimatorIK(int layerIndex)」が呼ばれるようになる。animator.SetIK○○ 関数を使って動的にアニメーションを変更できる。 |

レイヤー番号は上から昇順で指定する。Base Layer は 0、UpperBody は 1。
Raspberry Pi OSをx86_64 上のdockerで動かしたい

# これはなに？
いつもの如くの何番煎じシリーズです。

ちょっとラズパイを使って色々やってみたいことが増えてきたので、ハードをあまり持っていない自分として簡単に試せる環境を作りたいと思って調べたことの備忘録です。

以下の記事のほぼ丸パクリレベルになります。
https://qiita.com/autch/items/c8c9cdc7b8e5821e81a4
http://blog.guiraudet.com/raspberrypi/2016/03/03/raspbian-image-for-docker.html

変えたのは rasbianじゃないのをraspiosに変えたのと、qemu-arm-static を現時点で最新(v5.2.0-2)を入れたくらいです。

スクリプトは以下にあります。
https://github.com/shun/build-raspios-docker-image

docker imageは以下で取得できます。
タグ長げぇ。。。

```bash
$ docker pull kudoshunsuke/raspios-lite-for-x86_64:2021-03-04-raspios-buster-armhf-lite
```

コンテナ起動する前におまじないを実施する必要があるようです。
これをやらないと次のようなエラーが出力されます。[本家](https://github.com/multiarch/qemu-user-static) に書いてあります。
どうも、docker が multi-architecture 機能がサポートが有効化されていないと出力されるようです。

```
standard_init_linux.go:211: exec user process caused "exec format error"
```

ですので、multi-architecture 機能を有効化するため、おまじないを実行します。

```bash
$ docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
```

# 実行するスクリプト

以下は実際のスクリプトですが参考までに載せておきます。まぁ、パクリですけど。。。

```bash
#!/bin/bash

# target sources
SRC=https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-03-25/2021-03-04-raspios-buster-armhf-lite.zip
QEMUARM=https://github.com/multiarch/qemu-user-static/releases/download/v5.2.0-2/qemu-arm-static

set -e
mkdir -p raspios-tmp
cd raspios-tmp

filename=`basename $SRC`
if [ ! -e $filename ]; then
    echo "Download image..."
    wget --trust-server-names $SRC
fi

DISK_IMG=$(ls *.zip | sed 's/.zip$//')
if [ ! -e $DISK_IMG.img ]; then
    unzip *.zip
fi

OFFSET=$(fdisk -lu $DISK_IMG.img | sed -n "s/\(^[^ ]*img2\)\s*\([0-9]*\)\s*\([0-9]*\)\s*\([0-9]*\).*/\2/p")

mkdir rootfs
sudo  mount -o loop,offset=$(($OFFSET*512)) $DISK_IMG.img rootfs
# Disable preloaded shared library to get everything including networking to work on x86
sudo mv rootfs/etc/ld.so.preload rootfs/etc/ld.so.preload.bak

filename=`basename $QEMUARM`
if [ ! -e $filename ]; then
    echo "Download image..."
    wget $QEMUARM
fi
chmod 755 ./qemu-arm-static
sudo cp ./qemu-arm-static rootfs/usr/bin

# Create docker images
cd rootfs
sudo tar -c . | sudo docker import - kudoshunsuke/raspios-lite-for-x86_64:$DISK_IMG
cd ..

# Clean-up
sudo umount rootfs
rmdir rootfs
rm $DISK_IMG.img
sudo docker images | grep raspios

echo "Test the image with:"
echo "docker run -ti --rm kudoshunsuke/raspios-lite-for-x86_64:$DISK_IMG /bin/bash -c \'uname -a\'"
if docker run -ti --rm kudoshunsuke/raspios-lite-for-x86_64:$DISK_IMG /bin/bash -c 'uname -a' | grep armv7l; then echo OK; else echo FAIL; fi
```

これで、ラズパイ用のビルドとか残念な気持ちにならずにやれるのは 最＆高 ！
C#の列挙型(Enum)にOrderをつける

今回並び替えてみるEnumです。

```C#
public enum OrderTestEnum
{
    One,
    Two,
    Three
}
```

まず属性を用意

```C#
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class OrderAttribute : Attribute
{
    public int Value { get; set; }
}
```

Enumの拡張メソッドを用意

```C#
public static class EnumExtension
{
    public static T GetAttrubute<T>(this Enum e) where T : Attribute
    {
       var field = e.GetType().GetField(e.ToString());
       if (field.GetCustomAttribute<T>() is T att)
           return att;

        return null;
    }

    public static int GetOrder(this Enum enumKey)
    {
        var attribute = enumKey.GetAttribute<OrderAttribute>();
        return attribute?.Value ?? 0;
    }
}
```

EnumにOrder属性をつける

```C#
public enum OrderTestEnum
{
    [Order(Value = 0)]
    One,
    [Order(Value = 2)]
    Two,
    [Order(Value = 1)]
    Three
}
```

使い方

```C#
List<OrderTestEnum> enums = Enum.GetValues(typeof(OrderTestEnum))
.Cast<OrderTestEnum>()
.OrderBy(x => x.GetOrder())
.ToList();
```

以上でソートされると思います
【Windows10】ノートPCの電源が切れて付かなくなった場合

ノートパソコン復活して喜んでる状態からどうもカラボンです。

今回はノートパソコンの電源が付かない場合の対処法を1つ教えて行きたいと思います。

<h4>ノートパソコンのRAMを外してまた付ける</h4>

これは効果的でした。


〜方法〜

<h3>この方法は電源が完全に切れている前提で説明します。</h3>

1.ノートパソコンの裏側のネジを外して開ける
物によっては違います。

2.メモリを付け替える
付け替えるのに割と力がいるので注意

3.付け替えたら蓋を閉めてネジも締める

4.電源プラグを差し、電源ボタンを押す

5.ブルースクリーンなどが出ずにちゃんと起動できればOK!
並列分散処理基盤の概要まとめ[hadoop][spark][kafka]


https://www.youtube.com/watch?v=oaRRtnkyXKI&t=1s
ここで見たものを纏めてみた。

並列分散処理とは
- データを複数台のサーバに分散・蓄積および並列処理するための手法
- 大量のデータを現実的な時間で処理する


並列分散処理基盤を用いないで単体のサーバでデータを処理しようとすると？

- データを抱えきれない
- データを現実的な時間で処理できない


オープンソースの世界では、大規模分散処理フレームワークのhadoopが誕生
gfs mapreduceを基にしたオープンソースによる実装


## [hadoopとは？]

- 並列処理分散基盤フレームワーク
- 複数のサーバを使い、全体で大きな課題を解決させる。

 [hadoopの役割]

- 大規模データの保存と処理を行う
- 並列分散処理フレームワーク

 [実現できること]
現実的なコストで大規模分散処理ができる

※hadoopは繰り返しの多い処理と、複雑な処理が苦手。
それを解消するためにapache sparkが生まれる


## [sparkとは？]

- 並列処理分散基盤フレームワーク
- 複数のサーバを使い、全体で大きな課題を解決させる。

 [sparkの役割]

- メモリCPUディスクなどのリソースを効率的に利用
- SQLによる技術、機械学習、ストリーム処理などの分散処理で活躍

 [実現できること]
- 複雑な処理も高速で処理できる
- 豊富なライブラリやAPIが付属し、複雑処理も容易に実装できる

※しかしsparkとfluentdなどで、ストリーム処理するには、流れるデータを受け取れない場合消えてしまうためそれを
解消するために、kafkaが生まれた。


## [kafkaとは？]

- スケーラブルで高速な分散メッセージングシステム
（awsではaws kinesis）

 [kafkaの役割]

- サーバ複数台で並列に処理
- ディスクへの記録などデータを失いにくい仕組みを備える

 [kafkaで実現できること]
- 逐一送られるデータを高速に受け取ることが出来る
主従関係とマイグレーション順番を合わせないといけない

以下のdownのファイルをマイグレートしてテーブルを作ろうと思います。


 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20210409081355  Devise create users
   up     20210414110750  Create items
   up     20210415131442  Create active storage tablesactive storage
  down    20210424083734  Create addresses
  down    20210424083812  Create purchases

何度やってもうまくいきません。

```rb:terminal
Caused by:
Mysql2::Error: Table 'furima_32844_development.purchases' doesn't exist
```

細かいことなんですが、
①MigrationID20210424083734のファイルが配送先住所ファイルで、
②MigrationID20210424083812が購入情報なので

①が子②が親でマイグレーションの順番を変えないとMigrationできないようです。

解決策1
-

###最初についている長い名前のMigrationID番号を入れ替えるで解決します。

解決策2
-

##% rails db:migrate:up VERSION=20210424083734
コマンドでMigrationするファイルを指定する
AWS DocumentDB で $lookup pipeline が使えない話


AWS DocumentDB では、\$lookup 内で pipeline 使えないんですね。

> $lookup
> Amazon DocumentDB は、等価マッチを実行する機能 (左外部結合など) をサポートしていますが、相関のないサブクエリはサポートしていません。

MongoDB 3.6, 4.0 と互換性とか書いてあったので使えると思ってた。。。

本当は、以下のようなことがしたかった。


```python
[{"$lookup": {
        "from": "orders",
        "let": {
            "book_id": "$author.book_id",
            "author_id": "$author.author_id"
        },
        "pipeline": [
            {"$unwind": "$books"},
            {"$match": {"$expr": {"$and": 
                           [{"$eq": ["$$book_id", "$books.book_id"]}, {"$eq": ["$$author_id", "$books.author_id"]}] }}}
        ],
        "as": "book"
    }}
}]
```

とはいえ、何かしら代替の方法があるのではないのではないかと探してみる。

#### 暫定的な解決策： 事前に等価マッチできる形に、collectionを変形させておく

もう事前に $unwing しておけばよいのでは？という発想から


```python
[
{"$unwing": "$books"}
{"$out": "books"}
]
```

~~だけどこれもだめ、というのもユニークなIDがなくなるかららしい。~~
~~ユニーク or 連番を自動生成する方法も探したがないらしい。~~

```python
[
{"$unwing": "$books"}
{"$project": {"_id": 0, "books": 1}}
{"$out": "books"}
]
```

ユニークなidがないことじゃなくて、idがユニークじゃないことが問題だったのね。
消せばいいだけでした。

ちなみに、リファレンスとか読む感じ以下の書き方でも大丈夫な感じだったが、カラムがなくなるからダメ！ってエラーが出る。
これもDocumentDBの仕様なのかな。

```python
[
{"$unwing": "$books"}
{"$project": {"_id": 0}}
{"$out": "books"}
]
```

ただ、別のコレクションを作って解決するのは、
「すべての処理はDB内で完結させろ」と洗脳を受けた私的にはあまり気持ちのいいものじゃない。
他の方法があったりすんのかなぁ

#### 追記

これ使えばなんとかなりそう
（参考：https://cloud6.net/so/mongodb/239569）

```python
db.collection1.aggregate([
    { "$lookup": { 
        "from": "collection2", 
        "localField": "user1", 
        "foreignField": "user1", 
        "as": "collection2_doc"
    }}, 
    { "$unwind": "$collection2_doc" },
    { "$redact": { 
        "$cond": [
            { "$eq": [ "$user2", "$collection2_doc.user2" ] }, 
            "$$KEEP", 
            "$$PRUNE"
        ]
    }}, 
    { "$project": { 
        "user1": 1, 
        "user2": 1, 
        "percent1": "$percent", 
        "percent2": "$collection2_doc.percent"
    }}
])
```
【超入門】初心者のためのGitとGitHubの使い方（第一回）

初心者にはなかなか使い慣れないGitを超基本的なレベルから自分の理解を深めるためにアウトプットとして何回かにまとめて説明していきたいと思います。

第一回の目次は以下の通りです。

- はじめに
- そもそもGitとは何なのか？
- ファイルのバージョンを管理するとは？
- まとめ

#はじめに

最近何かとよく耳にするようになった「Git」。
エンジニアには必須知識になってきていますが、いまいちピンとこない方も多いかと思います。

今回は「Gitとは何なのか？」を専門用語を使わずに簡単に説明していきます。

#そもそもGitとは何なのか？

まずGitは何なのかというと、 ずばり...

『ファイルのバージョンを管理するツールです！』

もう一度言います。

『ファイルのバージョンを管理するツールです！』

ちょっと何言ってるかわからない状態になっていないでしょうか？
まずはなんとなくでも大丈夫です。次に行きましょう。

#ファイルのバージョンを管理するとは？

例えば発表資料のファイルを編集しているとき何回も編集していると、
以下のようにどれが最新のファイルかわからなくなるときがあります。

例）
発表資料ファイル_20210420.pptx
発表資料ファイル_20210420のコピー.pptx
発表資料ファイル_20210421.pptx
発表資料ファイル_20210424.pptx
発表資料ファイル_20210424_最新.pptx

自分一人でファイルを編集しているときならファイルを開いて確認すればわかるかもしれません。

ですが、複数人でファイルを編集しているときのことを想像してみてください。

誰がどのファイルを編集したのかわからなくなったり、誰かが編集したファイルを他の人が上書きしてしまったり・・・様々なトラブルが起こる可能性があります。

これを解決するには、誰がいつ何を編集したのかがわかれば、つまり...

『ファイルのバージョンを管理すれば...！』

最新のファイルや編集内容がわかるようになります。

Gitがファイルのバージョンを管理してくれることにより、誰が・いつ・何を編集したのかわかるようにしてくれます。

#まとめ

まずはGitとは何なのかを理解してもらえたかと思います。

複数人でファイルを編集するような作業ではGitを使用することでがとても重要になってきます。特にシステムなどを開発する場合は必須項目に挙げられます。

Gitの使用方法を習得して今後に活かしていきましょう。

次回はもう少しGitの詳細についてお話していきます。
CSSだけで画像をフェードインさせる方法

# 概要
### トップページの画像をフェードインさせる。フェードインしてくると見栄えが全然違ってきます。　　
### 「アニメーションだからJavaScriptかな・・・」と思いましたが調べてみるとCSSだけで可能でしたのでここに記述します。
###※Railsのヘルパーメソッドで作成しました

# 手順
### 1.HTMLで画像があるクラスを定義する
### 2.親クラスにposition: relative;、子クラスに position: absolute;を記述。
### 3.CSSで「opacity: 0;」「transition:all 1s（任意の時間） ease-in-out;」を記述。

# 1.HTMLで画像があるクラスを定義する
```html.
<div class="first-view">
    <%= image_tag("img1.jpg", class: :top_image) %>
</div>
```
### 画像の入っているクラスを作ります。

# 2.CSSで「opacity: 0;」「transition:all 1s（任意の時間） ease-in-out;」を記述。
```css.
.first-view{
  position: relative;
}

.top_image{
  position: absolute;
  opacity: 0;
  transition:all 1s ease-in-out;
}
```

###以上で画像をフェードインすることができる
Flutter Doc JPのBottomNavigationBarで軽く詰まったので

備忘録
Flutter初心者
Flutter Doc JPのBottomNavigationBarで軽く詰まったので

https://flutter.ctrnost.com/basic/navigation/bottomnavigationbar/

ここが抜けてたら、初心者はわからへん
MainPageがウィジェットじゃないからって怒られる。
　　　　　　　　↓
MainPageのStatefullWidget作る
             ↓
class MyAppのhome にMainPage(),追加
 

```main.dart
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

  class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MainPage(),
     );
    }
  }

  class MainPage extends StatefulWidget{
    @override
    _MainPageState createState () => _MainPageState();
  }
```





以下全文



```main.dart
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

  class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MainPage(),
     );
    }
  }

  class MainPage extends StatefulWidget{
    @override
    _MainPageState createState () => _MainPageState();
  }

  class _MainPageState extends State<MainPage> {

    int _currentIndex = 0;
    final _pageWidgets = [
      PageWidget(color:Colors.white, title:'Home'),
      PageWidget(color:Colors.blue, title:'Album'),
      PageWidget(color:Colors.orange, title:'Chat'),
    ];

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('BottomNavigationBar'),
        ),
        body: _pageWidgets.elementAt(_currentIndex),
        bottomNavigationBar: BottomNavigationBar(
          items: <BottomNavigationBarItem>[
            BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('Home')),
            BottomNavigationBarItem(icon: Icon(Icons.photo_album), title: Text('Album')),
            BottomNavigationBarItem(icon: Icon(Icons.chat), title: Text('Chat')),
          ],
          currentIndex: _currentIndex,
          fixedColor: Colors.blueAccent,
          onTap: _onItemTapped,
          type: BottomNavigationBarType.fixed,
        ),
      );
    }

    void _onItemTapped(int index) => setState(() => _currentIndex = index );
  }

  class PageWidget extends StatelessWidget {
    final Color color;
    final String title;

    PageWidget({Key key, this.color, this.title}) : super(key: key);

    @override
    Widget build(BuildContext context) {
      return Container(
        color: color,
        child: Center(
          child: Text(
            title,
            style: TextStyle(
              fontSize: 25,
            ),
          ),
        ),
      );
    }
  }

```
CSSで画像にぼかし（ブラー）をかける方法

##CSSで画像にブラーをかける方法

クラス付与でぼかしを入れる方法は、

```ruby:HTML.css
.blur{
  -ms-filter: blur(6px);
      filter: blur(6px);
}
```
と定義すればOK。

背景だけにブラーをかけたい場合は、beforeを用いて、

```ruby:HTML.css
.blur{
  background: url(imageURL) no-repeat center;
  background-size: cover;
  position: relative;
  overflow: hidden;
}
.blur:before{
  content: '';
  z-index: -1;
  -webkit-filter: blur(5px);
  -moz-filter: blur(5px);
  -o-filter: blur(５px);
  -ms-filter: blur(5px);
  filter: blur(5px);
  position: absolute;
  top: -5px;
  left: -5px;
  right: -5px;
  bottom: -5px;
  z-index: -1;
}
```
C++の共変、反変、不変

C++のVarianceの話、といっても`std::variant`のことではない。

# 共変リターンタイプ

```cpp
struct Animal {
};

struct Cat : public Animal {
};
```

このようなクラスがあったときに

```cpp
std::function<Animal* ()> func1 = []() { return new Cat;};
```

このコードは問題なくコンパイルが通る。`func1()`は`Cat*`しか返さないが`Animal*`を返すという宣言に嘘はない。

このようにサブタイプ(C++でいうところの子クラス)を返す関数を許容する特徴を「共変リターンタイプ(covariant return types)」と呼ぶ。


# 反変パラメタタイプ

先程の「共変リターンタイプ」は返り値についてであった。では引数についてはどうだろうか。

```cpp
std::function<void (Animal*)> func2 = [](Cat*) {}; // ERROR
```

返り値の場合と同様に引数にサブタイプを指定しているが、**このコードはコンパイルが通らない**。
`std::function<void (Animal*)>`は`Animal`のサブタイプ(`Dog`とかいるかも)をすべて受け入れる必要があるが、`[](Cat*){}`は`Cat`としか受け入れることができないのでコンパイルが通ってしまっては不都合が生じることになる。

だが次のコードはコンパイルが通る

```cpp
std::function<void (Cat*)> func3 = [](Animal*) {};
```

コンパイルが通らなかった例と比べると引数の型が逆になっている。
一見奇妙な感じを受けるが、`Cat*`しか引数に取らない関数として`Animal*`を引数に取る関数を渡したとして、その後`func3()`には`Cat*`しか渡されないだろうが、`Cat*`も`Animal*`なのだから特に問題はないはずだ。

このようにリターンタイプのときとはちょうど許容する型が逆転しているように見えるこれを「反変パラメタタイプ(contravariant parameter types)」という。

以上のようにコンパイラは型の位置（引数、返り値）によって許容するかどうかの判定をおこなっている。

# メソッドのVariance

いままでは`std::function`について見てきたがメソッドについてはどうだろうか。

```cpp
struct Breeder {
    virtual Animal* product()=0;
};

struct CatBreeder : public Breeder {
    Cat* product() override {
        return new Cat;
    }
};
```

これはコンパイルが通る。メソッドについても共変リターンタイプを持っていると言える。

しかし次はコンパイルは通らない

```cpp
struct AnimalDoctor {
    virtual void treat(Animal*) = 0;
};

struct CatDoctor : public AnimalDoctor {
    virtual void treat(Cat*) override {};
};
```

反変的なものを期待した次のコードもコンパイルは通らない。

```cpp
struct CatDoctor {
    virtual void treat(Cat*) {};
};

struct AnimalDoctor : public CatDoctor {
    void treat(Animal*) override {};
};
```

メソッドは引数について「不変(invariant)」である。

# STLコンテナについては「不変」

以下のコードはコンパイルは通らない。

```cpp
const std::vector<Animal*>* v = new std::vector<Cat*>{};
```

# クラス以外のVariance

C++のVarianceはクラスに限った話ではない。例えば`int*`は`const int*`のサブタイプとみなされ、今までの例と同様に以下のコードでコンパイルが通る。

```cpp
std::function<const int* ()> func4 = []() -> int* { return new int(1);};
std::function<void (int*)> func5 = [](const int*) {};
```

同様に次のコードはコンパイルが通らない。

```cpp        
std::function<int* ()> func6 = []() -> const int* { return new int(1);};
std::function<void (const int*)> func7 = [](int*) {};
```

# QA

## Q. Varianceの知識ってプログラミングで必要?

A. C++で自分が使うのはメソッドの共変リターンタイプくらい。ほとんど必要ない。

## Q. じゃあなぜこの記事を書いたのか？

A. 実はRustではVarianceの知識がそこそこ必要になるのでその入門としてC++ある程度知っている人向けに書いた。Varianceはクラスに限らないという話をしたが、Rustのライフタイムにもサブタイプの概念があり[^1]、記述位置によって共変、反変が存在し（C++とよく似ている）コンパイルが通らなくなりユーザーを悩ませるのだ。

[^1]: 例えばライフタイム`'a`がライフタム`'b`を包含するとき`'a`は`'b`のサブタイプとなる。

# 参考

* https://quuxplusone.github.io/blog/2019/01/20/covariance-and-contravariance/
* https://eli.thegreenplace.net/2018/covariance-and-contravariance-in-subtyping/
音声録音機能をつける 

音声録音機能のついたアプリケーションを作成したい


フレームワーク・・・Ruby on Rails
API・・・MediaStream Recording API


音声録音機能を実装するために調べて出てきた、MediaStream Recording APIについて書いていきます。

MediaStream Recording APIとは・・・オーディオとビデオをユーザーのデバイスから簡単に記録し、web上で使うことができる。生成されるファイル拡張子　Ogg Vorbis（オッグ ボルビス）。

Ogg Vorbis・・・ogg形式は、MP3形式のライセンス権に関する問題を避けるために開発された規格であるとされる。音質はMP3ファイルよりも優れ、規格はオープンソースでロイヤルティフリー。再生するためには、対応のプレーヤーが必要となる。


<a href="https://gyazo.com/226075dcbebfc1955daa8651de21a5bd"><img src="https://i.gyazo.com/226075dcbebfc1955daa8651de21a5bd.png" alt="Image from Gyazo" width="198"/></a>

MediaStream Recording APIのサンプルアプリがあったので、それを参考に導入。
app.jsにjavascriptで書かれた機能の内容が書かれてある。
マイクの取得して、音声のファイルを作成します的なこと...　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　
packsの直下にapp.jpを置くことでうまく連動しました。







参考サイト

<a>https://github.com/mdn/web-dictaphone</a>

https://developer.mozilla.org/en-US/docs/Web/API/MediaStream_Recording_API/Using_the_MediaStream_Recording_API
AWS　アカウント作成とIAM作成

# AWSのS3を利用して画像の管理をする為の設定方法です。

自分の備忘録として残させていただきますので、個別で設定方法は異なる場合がございますのでご注意ください。。。
前半はAWSアカウント作成とIAMの作成までの確認です。

S3とはAWS(Amazon Web Servies)のサービスに含まれる機能のひとつで、「Amazon Simple Storage Service」の略称です。

### 簡単に説明しますと、オンライン上の倉庫の中に大量のデータを安全かつ長期的に保存ができるものです。
ちなみに、データ容量やファイル数に上限がなく使用ができ、使った分だけ課金されるシステムとなっています。

# S３を利用するまでの手順

ざっくりと

- AWSのアカウント作成
- IAMの作成
- S3の保存先を作成

となっています。


# AWSのアカウント作成

AWSのトップページ(リンク下記参照)へいき、サインアップを行います。
（無料枠を超えると料金が発生するので注意）

- アカウントの作成
※半角英数字で入力

- 電話番号など必要な項目を入力
※注意点として「プロフェッショナル」「パーソナル」の選択があるので、法人利用なら前者、個人利用なら後者を選択する。

- クレジットカード情報を登録

- 本人確認
※検証コードはSMSにチェックしました。
※国(リージョンコード)は日本にしました。

- 登録後にSMSで認証コード(4桁の番号)が届きましたので打ち込む

- サポートプランの選択
※詳しくはわかりませんが、ベーシックプラン(無料)で開始

これでアカウント作成は完了です。

作成したアカウントでログインする場合あは「コンソールにサインイン」をクリックし、「ルートユーザー」を選択しメールアドレスを打ち込む。その後パズワードも入力してサインインが可能。

# IAMの作成

ルートユーザーアカウントは、AWS上のサービスや機能を自由に操作できるため、不正利用があると危険です。。

その為、権限に制限をかけた「IAMユーザー」を作成します。

- AWSトップページで「IAM」を検索しIAMのページから「ユーザー」へ遷移し、画面の左上のユーザー追加を押します。

- ユーザー名は自由に設定し、アクセス権限は「プログラムによるアクセス」を選択。

- その後、既存のポリシーを直接アタッチを選択
検索で「AmazonS3」を入力し「AmazonS3FullAccess」というものを選択し次のステップへ。

- タグの追加(オプション)では何もせず次へ。

- 次の確認画面で「ユーザーの作成」を押すとcsvのダウンロードができます。

※「Access key ID」「Secret access key」はソースコードのプログラム内でAWSにアクセスする際に使用するものです。ファイルを削除しないように注意しましょう。

- ユーザーページから作成したIAMに遷移し、「認証情報」で「サインイン認証情報」が表示されます。

- 表記のある「コンソールのパスワード」の「管理」にてコンソールへのアクセスを「有効化」し「自動生成パスワード」で適応し、csvファイルのダウンロードをします。

※ファイルには「ユーザー名」「パスワード」「ログインURL」が記載されています。AWSのサイト上でIAMユーザーとしてログインする際に必要となるため、ファイルを削除しないように注意しましょう。

- csvに記載のある「Console login link」のURLからログイン画面へアクセスし記載のある「アカウントID」「ユーザー名」「パスワード」を入力してサインインします。

(セキュリティで２段階認証が必要な場合は参考リンクのAWS アカウントを保護をご確認ください。)

ここまでで、IAMの作成までできました。この後いよいよS3の設定を行い適応させる段階へいきますが、今回はここまでとさせていただきます。

# 参考リンク

>AWSトップページ
https://aws.amazon.com/jp/

>IAMに関して
https://aws.amazon.com/jp/iam/

>AWS アカウントを保護
https://aws.amazon.com/jp/blogs/news/guidelines-for-protecting-your-aws-account-while-using-programmatic-access/
GitLabでclone出来なくて困ったのでメモ

GitLabで個人開発をしようとプロジェクトを作成したのですが、以下のエラーが出て`git clone`が出来ませんでした・・・
なんとか解決できましたのでメモ。

~~~:エラー
git@gitlab.com: Permission denied (publickey,keyboard-interactive).
~~~

# 環境
OS: macOS Big Sur バージョン11.1
ssh: OpenSSH_8.1p1, LibreSSL 2.7.3

# 試したこと
１、アカウントとプロジェクト作成後、ssh接続設定（参考：[GitLabにSSHで接続するまでの手順](https://qiita.com/kyamawaki/items/07fb3332cf3c2f47728a)）
→git cloneで冒頭のエラーが発生。

2、`~/.ssh/config`を見直すが特におかしな点は見つからず・・・

3、GitLabに登録したメールアドレスを指定して、秘密鍵＆公開鍵を作り直す。（参考：[メールアドレスを指定してSSHキーペアを作り直す](https://wing-degital.hatenablog.com/entry/2020/01/03/175752#GitLab%E3%81%AESSH-Keys%E3%82%92%E8%A6%8B%E7%9B%B4%E3%81%99)）
→解消されず。

4、参考：[ssh-agentに秘密鍵を登録する](https://wing-degital.hatenablog.com/entry/2020/01/03/175752#ssh-agent%E3%81%AB%E7%A7%98%E5%AF%86%E9%8D%B5%E3%82%92%E7%99%BB%E9%8C%B2%E3%81%99%E3%82%8B)
→解決
下記のように`ssh-add`で秘密鍵を登録したら解決できました！！

~~~bash:ssh-agentに秘密鍵を登録
$ ssh-add (秘密鍵のパス)
$ ssh -T git@gitlab
Welcome to GitLab
$ git clone git@gitlab.com:アカウント名/プロジェクト名
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
~~~

# 終わりに
今回から初めてGitLabを使っての開発です。
初っ端なからつまずきましたが、頑張っていきます！！

# 参考
https://wing-degital.hatenablog.com/entry/2020/01/03/175752
https://qiita.com/kyamawaki/items/07fb3332cf3c2f47728a
【Python】を使ってターミナル１で入力した情報をターミナル２で表示してみた【需要無し】

# 開発環境
> Python 3.9.2
Windows10 Home
Windows10標準コマンドプロンプト

# 開発経緯
なんとなく。
なんかできたら面白いから。

# 本編

システムとしては、
ターミナル１(以降 T1)で文字を入力→ファイルにその情報を保存→ターミナル２(以降 T2)でファイルの変更を認識→T2で出力
でやっていきます。

用意するファイルは
・input.py
・output.py
・file.txt
の三つ。
別に名前は何でもいいです。


## コーディング

### input

文字入力する方のファイルでは、
文字入力→ファイルに情報書き込み
をループさせていく感じでやっていきます。
簡単ですね。

```py:input.py
while True:
    s = input()
    with open('file.txt', 'w', encoding='utf-8') as file:
        file.write(s)
```

たった４行。とても簡素。
これでT1で実行するファイルは完成です。

### output

文字出力する方のファイルでは
ファイル内容を確認→前回の内容と比較→内容が違ったら内容を出力
をループします。
とても簡単。

```py:output.py
with open('file.txt', 'r', encoding='utf-8') as file:
    before = file.read()
import time    
while True:
    with open('file.txt', 'r', encoding='utf-8') as file:
        cnt = file.read()
    if not cnt == before:
        before = cnt
        print(cnt)
    time.sleep(0.00001)
```

inputよりは行数が多いけどそれでも少ないですね。
`time.sleep`を途中に挟んでいる理由として、「ファイルの開閉を高速で行いすぎるとファイル内容が無になることがある」からですね。
sleep挟んだら解決したのでそうなんだろうっていう仮説ですけどね。
もしくは、ファイルの内容がなければ何もしないという処理を挟むのもいいかもしれませんね。
T2で実行するファイルもこれで完成です。


`file.txt`の内容は何も書かなくて大丈夫です。


## 実行
もう完成です。あとは実行するだけですね。
実際に実行してみると、

![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701137/aecf8c12-cd05-7408-047a-defdc91bac78.gif)

はい、うまくいきましたね。
意外とファイルの読み書き速度が速かったです。
これの使い道を考えた人の勝ちっていうことにします。
コメント欄で遊んでください。

ﾉｼ
javascriptを使用して配列の中から最も近い値を取得する方法

qiita初投稿です。備忘録として投稿させていただきます。


```javascript:
const val = 8 //　対象値
const closest = [1, 10, 7, 2, 4].reduce((a, b) => {
    return Math.abs(b - val) < Math.abs(a - val) ? b : a;
});
console.log(closest); // Output: 7
```

こちらの記事を参考にしました。
https://www.gavsblog.com/blog/find-closest-number-in-array-javascript