OmniAICreator/Qiita-1.07M huggingface dataset:
[flutter doctor] cmdline-tools component is missing


flutter doctorでcmdline-toolsが無いと言われた。

```bash
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.5.3, on macOS 11.6 20G165 darwin-x64, locale ja-US)
[!] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more
      details.
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.1)
[✓] Android Studio (version 4.1)
[✓] VS Code (version 1.62.3)
[✓] Connected device (2 available)
```


# 対応
`cmdline-tools` をインストールする。

#### 1. AndroidStudioの検索ボタンを押し、`SDK Manager`を検索し、起動する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121224/f87e7150-b4cc-0c5e-cc5f-55a2ec3a1883.png)

#### 2. `SDK Tools` -> `Android SDK Command-line Tools`にチェックを入れ、applyを押すとダウンロードが始まる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121224/787f2253-6311-4346-7836-dd09668b8a6b.png)

#### 3. `flutter doctor`で`cmdline-tools`がインストールされたことを確認

```bash
flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.5.3, on macOS 11.6 20G165 darwin-x64, locale ja-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.1)
[✓] Android Studio (version 4.1)
[✓] VS Code (version 1.62.3)
[✓] Connected device (2 available)

• No issues found!
```
Python3: cos類似度を計算 (Mecab わかちがき)

次のページを参考にしました。
[［文章生成］MeCabをインストールして分かち書きを試してみよう](https://atmarkit.itmedia.co.jp/ait/articles/2102/05/news027.html)
[文書のコサイン類似度を求める](https://tex2e.github.io/blog/python/docs-similarity)

```py:mecab_wakati.py
#! /usr/bin/python
#
#	mecab_wakati.py
#
#						Nov/28/2021
#
# ------------------------------------------------------------------
import sys
import MeCab
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

# ------------------------------------------------------------------
def to_wakati_proc(sentence_list):
	tagger = MeCab.Tagger('-Owakati') 

	docs=[]
	for it in range(len(sentence_list)):
		result = tagger.parse(sentence_list[it])
#		print(it)
#		print(result)
		docs.append(result)
#
	return docs
# ------------------------------------------------------------------
def output_proc(sim):
	from_id = 0
#	 print('doc_id:', from_id)
	for to_id in range(1,len(docs)):
		print('sim[{0}][{1}] = {2:f}'.format(
			  from_id, to_id, sim[from_id][to_id]))

# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")

sentence_list = [
        '昔ある所に、王様がいました。',  # 文章A
        'ある所に、かわいい女の子がいました。',  # 文章B
        '一人の王様がいました。',  # 文章C
        '昔ある所に、貧しい女がいました。',  # 文章D
        '昔、王様がある所にいました。',  # 文章E
        ] 

docs = to_wakati_proc(sentence_list)

#
vectorizer = TfidfVectorizer(max_df=0.90) # tf-idfの計算
#                            文書全体の90%以上で出現する単語は無視する
X = vectorizer.fit_transform(docs)
# print('feature_names:', vectorizer.get_feature_names())
# print('X:')
# print(X.toarray())
sim = cosine_similarity(X) # 類似度行列の作成
#

output_proc(sim)

sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行結果

```text
$ ./mecab_wakati.py 
*** 開始 ***
sim[0][1] = 0.315979
sim[0][2] = 0.425818
sim[0][3] = 0.315979
sim[0][4] = 1.000000
*** 終了 ***
```
Haskellでポラード・ロー法を実装してみた

**ポラード・ロー法(Pollard's rho algorithm)**は非自明な約数を高速に発見するアルゴリズムです。
ただし、このアルゴリズムは必ず約数を発見できるわけではなく、失敗する可能性があります。

https://ja.wikipedia.org/wiki/%E3%83%9D%E3%83%A9%E3%83%BC%E3%83%89%E3%83%BB%E3%83%AD%E3%83%BC%E7%B4%A0%E5%9B%A0%E6%95%B0%E5%88%86%E8%A7%A3%E6%B3%95

今回は、このアルゴリズムをHaskellで実装して、その速度を計測してみました。
また、素朴な試し割り法による約数の探索についても速度を計測して、ポラード・ロー法の速さと比較してみようと思います。

# 実装
次のように実装しました。

```haskell
-- ポラード・ロー法
rho :: Integer -> Maybe Integer
rho n
  | n < 4 = Nothing
  | otherwise = loop 2 2 1 -- フロイドの循環検出法で循環が検出されるまで試し割りする
  where
    random = \x -> mod (x*x + 1) n --疑似乱数
    loop x0 y0 d
      | d == n = Nothing -- 非自明な約数がない、もしくは発見できなかった
      | d /= 1 = Just d -- d == gcd (x0-y0) n なので d は n の約数
      | otherwise = loop x1 y1 (gcd (x1-y1) n)
      where
        x1 = random x0
        y1 = random (random y0)
```

疑似乱数を用いて約数を探すのですが、約数を発見する前に疑似乱数が循環してしまう可能性があります。
そこで、ポラード・ロー法では**フロイドの循環検出法**を用いて疑似乱数の循環を検出した場合は探索を終了します。

https://ja.wikipedia.org/wiki/%E3%83%95%E3%83%AD%E3%82%A4%E3%83%89%E3%81%AE%E5%BE%AA%E7%92%B0%E6%A4%9C%E5%87%BA%E6%B3%95

なので、ポラード・ロー法では非自明な約数を発見する前に探索が打ち切られる可能性があります。

# 速度の比較

次にポラード・ロー法の速度を測ってみます。
まず、GCHiオプション```+s```で経過時間などを表示するよう設定します。

```
*Main> :set +s
```

ここでは$100000980001501(=10000019\times10000079)$の約数を探索することにします。

```
*Main> rho 100000980001501
Just 10000079
(0.02 secs, 10,298,096 bytes)
```

ちゃんと約数($10000079$)を探すことができました。
経過時間は$0.02$秒と表示されています。

次に、素朴な試し割り法での速度を計測してみます。
試し割りのプログラムは以下のように実装しました。

```haskell
-- trial division
trial_div :: Integer -> Maybe Integer
trial_div n = head' (filter ((0 ==) . mod n) (takeWhile (\d -> d*d <= n) (2:[3,5..])))
  where
    head' xs
      | xs == [] = Nothing
      | otherwise = Just (head xs)
```

$2$と奇数からなるリスト```2:[3,5..]```のうち$\sqrt n$以下のものについて、$n$を割り切るもののみをフィルタして、その結果の先頭を返します。
つまり、$n$を割り切る非自明な約数のうち、最小のものを求めています。
$\sqrt n$以下で存在しない場合、$n$を割り切る非自明な約数はないので```Nothing```を返します。

ポラード・ロー法のときと同様に時間を計測します。


```
*Main> trial_div 100000980001501
Just 10000019
(1.86 secs, 1,160,342,328 bytes)
```

約数($10000019$)を見つけることができましたが、$1.86$秒かかりました。
ポラード・ロー法の方が数十倍速い結果になりました。

# 非自明な約数を発見できない例

先程も述べたように、ポラード・ロー法では非自明な約数を発見できない場合があります。
どの程度発見できないのか、確認してみます。

以下は、今回の方法で非自明な約数を見つけることに失敗した合成数の例です。
$$4,8,16,21,22,25,32,44,62,64,88,95,\dots$$

このような合成数の数はどの程度あるのでしょうか？
$n$以下の合成数のうち、ポラード・ロー法で非自明な約数を発見できた数を計算してみます。

以下のように、合成数を数えるプログラムと、ポラード・ロー法の成功率を計算するプログラムを用意しました。

```haskell
count_composite :: Integer -> (Integer -> Maybe Integer) -> Int
count_composite n algorithm = length (filter ((Nothing /=) . algorithm) [0..n])

rate_success :: Integer -> Double
rate_success n = (f rho) / (f trial_div) where f = fromIntegral . (count_composite n)
```

結果は以下のとおりです。

```
*Main> rate_success 10
0.6
*Main> rate_success 100
0.8378378378378378
*Main> rate_success 1000
0.9626955475330926
*Main> rate_success 10000
0.9905359179019384
*Main> rate_success 100000
0.9973895826650592
```

$100000$以下の合成数の$99\%$以上について、非自明な約数を発見することができています。

# まとめ

* ポラード・ロー法は素朴な試し割り法より速い。
* ポラード・ロー法は失敗する可能性がある。
Spring Security とは

## 勉強前イメージ

ちらっと聞いただけだからイメージもつかないけど
セキュリティに関連するもの。。。

## 調査

### Spring Security とは

Spring Frameworkのアプリケーションに対してセキュリティ強化するためのフレームワークになります。
Spring Frameworkはオープンソースのjavaのフレームワークの一つで汎用性が高く豊富な機能があります。
↑のフレームワークに対するセキュリティ対策するフレームワークです。
セキュリティ強化とは、認証・認可、その他セキュリティ保護が目的です。

### Spring Security の機能

いくつか機能があるので、確認していきます。

- 認証機能

webアプリを使うユーザが正しいことを確認する機能で、
DB認証やBASIC認証、LDAP認証やOAuth2.0など複数認証方法があります。

- 認可機能

webアプリのユーザの権限や管理を行う機能です。
リクエストURLやメソッドで設定ファイルにアクセス認可情報を記載して管理を行います。

- セッション管理機能

webアプリとユーザの通信を管理を行う機能です。
Spring SecurityではセッションIDが発行され、サーバ側とユーザ側で持つことで整合性を担保します。

- CSRF対策機能

[CSRF(クロスサイトリクエストフォージェリ)](https://qiita.com/miyuki_samitani/items/73d1b1df3a4d901aeb56) の対策ですが、
サーバ側でページにトークンを埋め込んだりパスワードを再入力させたりすることで保護することができます。

- セキュリティヘッダ出力機能

Spring Securityではブラウザのセキュリティ機能を使うことでユーザを保護します。
セキュリティ関連のレスポンスヘッダを出力させることで、ブラウザのセキュリティと関連して脆弱性の仕組みを動作させます。

- パスワードの暗号化・ハッシュ化

パスワードを管理する際に[暗号化、またはハッシュ化](https://qiita.com/miyuki_samitani/items/e0c1c1271af874991a33) することで
盗み見られても実際のパスワードが分からないようにする方法で
認証機能と連動してこちらの機能を提供するクラスが用意されています。


## 勉強後イメージ

フレームワークのセキュリティ対策を行うためのフレームワークってことかな？
セキュリティに特化したもの。
それってフレームワークに入ってるわけじゃないのね。

## 参考

- [【5分でわかる】Spring Securityの概要や認証機能、仕組みなどわかりやすく解説](https://camp.trainocate.co.jp/magazine/spring-security/)
- [Spring Framework]https://e-words.jp/w/Spring_Framework.html)
Python_moduleをimportできるパスを確認、追加する


# moduleをimportできるパスを確認する


```py
import sys

print(sys.path)
```

> ['/opt/conda/lib/python37.zip', '/opt/conda/lib/python3.7', '/opt/conda/lib/python3.7/lib-dynload', '', '/opt/conda/lib/python3.7/site-packages', '/opt/conda/lib/python3.7/site-packages/IPython/extensions', '/home/jovyan/.ipython']

# moduleを使えるようにするために、パスを追加する

`sys.append('path')`で追加できる。
一階層上のディレクトリのpathの追加は以下のように書ける。
~/.bashrcにPYTHONPATHを追加する方法もあるが、それは恒久的に使いたい場合に用いる。

```py
import os
import sys

sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
```


## importしたmoduleがどこのパスにあるのか確認する
sys.pathで確認したパスのどこにnumpyが入っていたかわかる。

```py
import sys
import numpy as np

print(np.__file__)
```
> /opt/conda/lib/python3.7/site-packages/numpy/__init__.py
【javascript】Promise

# Promis
* 非同期処理をより簡単に、可読性が上がるように書けるようにしたもの。
* ES6から導入された。

## 構文
* thenなど連続して扱える。非同期チェーンがしやすい。
* resolve, rejectいずれかを呼ぶ

```js

new Promise(function(resolve, reject){
    //同期処理
    resolve('args') // thenの処理へ 
    reject() // catchの処理へ
    console.log('Promise')
}).then(function(args){ //非同期処理 //resolveから引数を受け取れる。
     console.log('then1' + args) // >>> then1 args
     return args //return 引数とすると次のthenに引数を渡すことができる。
    })
.then(function(args){
    console.log('then2 +' + args)
    console.log('then2')
    throw new Error(); //catchの処理へ移行できる。
})
.then(function(){
    console.log('then3')
})
.catch(function(){ //非同期処理
    console.log('catch')
})
.finally(function(args){ //非同期処理, resolve,reject共に終了処理される。 //引数は受け取れない
    console.log('finally' + args) // >>> finallyundefined
})
```

# Promiseチェーン

* 引数valを受け取り、Promiseのインスタンス化したsleep関数実行
    * Promiseを実行
        * rejectがない場合は省略可能。
        * 1秒後に引数valを受け取ったresolveを実行
        * 引数valをインクリメントしコンソールに出力
    * thenのreturnにさらにsleepを実行することで連続してsleep関数を実行することができる。


```js
function sleep(val) {
  return new Promise(function(resolve){
    setTimeout(function(){
      console.log(val++);
      resolve(val);
    }, 1000);
  });
}

sleep(0).then((val) =>{ return sleep(val)})
.then((val) =>{ return sleep(val)})
.then((val) =>{ return sleep(val)})
.then((val) =>{ return sleep(val)})
.then((val) =>{ return sleep(val)})

>>> 0
>>> 1
>>> 2
>>> 3
>>> 4

```

# Promise.all()
* Promise.all() メソッドは入力としてプロミスの集合の反復可能オブジェクトを取り、入力したプロミスの集合の結果の配列に解決される単一の Promise を返します。
* 引数は反復可能オブジェクト、例えばarrayなど。

```js
var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("foo");
  }, 100);
});

Promise.all([p1, p2, p3]).then(values => {
  console.log(values); // [3, 1337, "foo"]
});
```
Firestoreのトリガーで指定するコレクションのパスは、ランタイム環境変数では正しく指定できない

Firestoreには何か変更があったときにCloud Functionを発火する[トリガー](https://firebase.google.com/docs/functions/firestore-events?hl=ja)と呼ばれる機能がある。
たとえば、あるドキュメントが作成されたときトリガーを起こしたい時は、以下のような記述になる。

```js
const FIRESTORE_COLLECTION_PATH = process.env.FIRESTORE_COLLECTION_PATH

export const onCreateXXX = functions.firestore
  .document(`${FIRESTORE_COLLECTION_PATH}/{id}`)
  .onCreate(async (snapShot, context) => {
   ...
```

このコードの意図としては、Cloud Functionのコンソール上で設定したランタイム環境変数のコレクションパスにドキュメントが新規生成されたときに発火するというものだ。
しかし実際は、このパスにドキュメントが生成されてもこのCloud Functionが発火されることはない。

### 原因(推察)
おそらく、Firestoreのトリガーがランタイム環境変数が有効となる前に生成されるため、設定した変数値でトリガーできないというもの。

### 対応策
とはいうものの、コレクションパスをベタ書きするのもためらわれる。
そこで、[環境構成](https://firebase.google.com/docs/functions/config-env?hl=ja)を利用する。

#### 設定方法

```sh
firebase functions:config:set <key>=<value>
```

**key は、少なくとも一つの「.」で連結した形にする必要がある(2-part key)**

- ok: foo.bar=goodvalue
- ng: foo=badvalue

設定した構成は確認可能である。

```sh
firebase functions:config:get 
```

以下コマンドによりデプロイすることで、Cloud Functionにアップロードする。

```sh
Firebase deploy --only functions
```

また、中身は `.runtimeconfig.json` に認められている。

```json
{
  “foo”: {
    “bar”: “goodvalue”
  },
  // 以下はデフォルトで設定されている
  "firebase": {
    "projectId": ..,
    "storageBucket": …,
    "locationId": …
  }
}
```

ローカルでも環境構成を使用したい場合は、以下コマンドでファイルとして吐き出す。

```sh
firebase functions:config:get > .runtimeconfig.json
```
package-lock.jsonとyarn.lockとは!? 分かりやすくシンプルに解説!!

# はじめに
この記事を読む前にpackage.jsonファイルがどんな役割を持っているか、知っている事が前提知識として必要になります。
詳しくは解説してないので、詳しい記事を見たい方は別のを探してください。あくまで入門〜初級者向けの概要程度でシンプルに説明しています。


# 目次
<!-- タイトルとアンカー名を編集 -->
1. [package-lock.json, yarn.lockとは](#package-lock.jsonとは)
2. [package-lock.jsonファイルが有る場合](#package-lock.jsonファイルが有る場合)
3. [package-lock.jsonファイルが無い場合](#package-lock.jsonファイルが無い場合)
4. [yarn.lockとは](#yarn.lockとは)

<!-- 各チャプター -->
# package-lock.json, yarn.lockとは
ざっくり解説すると、チーム開発をする際にチームメンバーでライブラリ等の<font color="blue">__バージョンを統一する__</font>際に必要になるファイルです！！
下記でpackage-lock.jsonファイルが「有る場合」と「無い場合」で比較をしています。

# package-lock.jsonファイルが有る場合

①npm installを実行
②package-lock.jsonに記載されたバージョンでライブラリをインストールする。
③チーム開発の場合、<font color="blue">__開発メンバー全員が同じバージョンのライブラリ__</font>で開発ができる。
※Gitでpackage-lock.jsonファイルを共有している為、チームメンバー全員が同じpackage-lock.jsonファイルを元に同じバージョンでライブラリをインストールできます。

# package-lock.jsonファイルが無い場合
①npm installを実行
②package.jsonに記載されたバージョンの範囲内で最新バージョンのライブラリをインストール。
※pacage.jsonだけだと、pacage.jsonに記載されている最新版のバージョンでインストールしてしまう為、各々の開発メンバーがインストールしたタイミング次第では、チーム内でライブラリのバージョンに違いが出てしまう。
③チームメンバー同士でnpm installのタイミングが異なり、インストールした<font color="blue">__ライブラリのバージョンがチームメンバー内で異なる__</font>状況ができてしまう。


# yarn.lockとは
package-lock.jsonと同じ役割を持つファイル。
主な違いは、npm installではなく、<font color="blue">__yarn installを実行した場合__</font>に参照するファイルであるという点です。

・```npm install``` → package-lock.jsonファイル
・```yarn install``` → yarn.lockファイル
インチキをしてRailsでExcelを読み書きする

## Excel大好きな人達

多くの案件ではExcel好きなプロパーとかExcel好きなプロパーとかExcel好きなプロパーが跋扈しており、確固たる理由はないがなんとなく「Excelライクで」とか言われることが非常に多いと感じています。
Excelライクと言わないまでも、Excelをアップロードできたりダウンロードできたりと言った要件は、非常にカジュアルに生じています。

「DXの意味わかっているの？」と言いたくなるのですが、これが原状なのでしょうがありません。

## Railsライブラリの限界
ただ、Railsエンジニアなら一度は経験したことがあると思うのですが、RailsにはExcelをうまく扱えるライブラリがあまりありません。

|ライブラリ|機能|注記|
|-|-|-|
|Axlsx|新規作成から書き出しだけ|新規作成のみで、テンプレートファイルからの新規作成もできない。複雑なワークシートを作ろうと思うと、コードが恐ろしく読みにくくなる|
|Roo|読み込みだけ|読み込み専用|
|RubyXL|読み書き可能|数少ない読み書き可能なライブラリだが、`parse`が恐ろしく遅いのであまり使い物にならない|

## Pythonにはopenpyxlがある

一方、Pythonは世界中のデータサイエンティストが使っていることもあって、openpyxlという非常に使いやすいライブラリが存在して、ものすごく手軽に扱うことが可能になっています。
今回は、Rubyからopenpyxlを呼び出してみました。

## コンテナにpython及びライブラリを入れる

今回はDockerを使っている前提で、Rubyの動いているコンテナにpythonをインストールします。システム管理や`aws-cli`を動かすためにすでに入っているケースも多いと思います。

```Dockerfile:Dockerfile
FROM ruby:2.7.4-alpine

RUN mkdir /app
ENV APP_ROOT /app
WORKDIR $APP_ROOT
RUN apk add --update --no-cache \
    ...
    python3 python3-dev py3-pip && \
    pip install openpyxl
...
```

コンテナを使っていない場合はvenvを使ったほうがいいと思いますが、本稿では触れません。

## 簡単なPythonスクリプトを作成する

ここでは、標準入力から`{"A1": "Hello, World!"}`のようなJSONを受け取り、テンプレートのExcelファイルに書き込んだうえ、そのExcelファイルを標準出力に書き出すスクリプトを作成しました。
メインのロジックをあまりRailsの外におきたくなかったので、極力シンプルにしています。

```python:python/to_excel.py
import os
import sys
import json
import openpyxl
import tempfile

cell_values = json.loads(sys.stdin.read())

wb = openpyxl.load_workbook("spec/fixtures/template.xlsx")
ws = wb.worksheets[0]

for cell, value in cell_values.items():
    ws[cell] = value

tmp = tempfile.NamedTemporaryFile(delete=False)
wb.save(tmp.name)
tmp.close()

with open(tmp.name, 'rb') as f:
    sys.stdout.buffer.write(f.read())

os.unlink(tmp.name)
```

## Ruby(Rails)から`popen`でpythonを呼び出す

```ruby
excel = IO.popen('python3 python/to_excel.py', 'r+') do |io|
  io.puts cell_values.to_json
  io.close_write
  io.read
end
```

excelにはExcelファイルのバイナリが入ります。ActiveStorageに入れるなり、`send_data`するなりして料理しましょう。
Tableau 表計算を理解する　②RANK関数

## 前置き
　TableauのRANK関数、項目を順位別に並べたい時などに便利ですよね。簡易表計算から使用することがほとんどだと思いますが、自分で計算式で作ることも可能です。計算式で作ろうとすると、実はRANK関数は5種類あることがわかります。どう違うのか気になったので整理してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307669/467ad520-110d-99c5-2dde-6fa3077f1082.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307669/a94bcc76-805f-6c6d-1633-04bcaf73b21c.png)

## 5種類のRANK関数の違い
　サンプルスーパーストアでサブカテゴリごとの販売数量を、5種類のRANK関数で計算すると下図のようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307669/86c6e5d7-645e-3e58-2066-173ae8cb0dad.png)
　一番上の`RANK`が簡易表計算でも使われる、もっとも一般的なものです。結果を見ると、文房具と電話機が同率9位で、その次の家具は11位となって10位は存在しません。つまり、**RANKは同率を許し、同率の後ろの項目の順位は1位から数えた〇個目になる（同率があると順位が飛ぶ）**、ということがわかります。

　次の`RANK_DENSE`は文房具と電話機が同率9位で、その次の家具は10位となっています。最下位のテーブルも16位となっており17項目あるのに16位までしかありません。つまり、**RANK_DENSEは同率を許し、同率の後ろの項目の順位は1位から数えた〇位になる（同率があっても順位は飛ばない）**、ということがわかります。

　次の`RANK_UNIQUE`はこれまでの2つとは違い、文房具と電話機は販売数量が同じなのにも関わらず、文房具が9位で電話機は10位になっています。つまり、**RANK_UNIQUEは同率を許さない（同じ値であっても別の順位がつけられる）**、ということがわかります。

　次の`RANK_MODIFIED`は文房具と電話機が同率10位で、その次の家具は11位となって9位は存在しません。つまり、**RANK_MODIFIEDは同率を許し、同率の項目の順位は同率項目の数だけ飛ぶ**、ということがわかります。

　最後の`RANK_PERCENTILE`は少し毛色が違ます。順位付けの考え方は`RANK`と同じですが、値としては1位が1、最下位が0で、その間の順位の値は項目数で均等割りした値を引いていった値になります。具体的には、今回項目数が17なのでn位の値は次の計算式で求められます。

```math
1-\frac{n-1}{17-1}
```

## まとめ
　それぞれの関数の特徴を表にまとめました。違いは理解できましたが、正直RANK関数以外は使う機会なさそうだな～というのが正直なところ。あと、[検証用に作成したVizはTableau Publicにアップしています](https://public.tableau.com/app/profile/takahisa.okazaki/viz/RANK_16361185138000/RANK5)ので、よろしければそちらもご覧ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307669/4825ea83-c428-f6fe-c442-fd31590926dd.png)


## 　

https://qiita.com/zaki_001/items/f2e7087dc3b0fa2efae8
Pyhton_lambda式、無名関数


lambdaは引数として関数を呼ぶもので使用すると便利。(mapとか)


# lambda式で関数を表す

```
def 関数名(引数, 引数, ...):
    return 式

関数名 = lambda 引数, 引数, ...: 式
```

例

```py
def square(x):
    return x * x

square(s(5))
> 25
```

これをlamdba式で表すと、

```py
type(lambda x: x * x)
> function

s = lambda x: x * x
print(s(5))
> 25
```
neosでlogix その7

# 概要

niosでlogixやってみる。
パッキングやってみた。

# 参考にした動画。

https://www.youtube.com/watch?v=Bhg2zbBQUoY

# 写真

![2021-11-28 02.03.24.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/47c23cf7-a719-d80a-f013-53d046e3b3d6.jpeg)


# 嵌った所

- インスペクターを取り出す
　　　DevToolTip
- インターフェースを取り出す
   　　LogiXToolTip
- パックする
   　　LogiXToolTip


以上。
Clean Architecture 輪読会まとめ


### 第1部：イントロダクション & 第2部：プログラミングパラダイム

https://qiita.com/tkek321/items/1f9663bd5eb4474557d2

### 第3部：設計の原則

https://qiita.com/tkek321/items/58f35dc64f5a87b5c955

### 第4部：コンポーネントの原則

https://qiita.com/tkek321/items/4aa6732ff7e442fc9696

### 第5部：アーキテクチャ①

https://qiita.com/tkek321/items/e66e5ffe15ee35057bb7

### 第5部：アーキテクチャ②
https://qiita.com/tkek321/items/3ff45e6cf3825ed46261


### 第5部：アーキテクチャ③
https://qiita.com/tkek321/items/10e281cfc632a1f8533d

### 第6部：詳細
https://qiita.com/tkek321/items/8aba351f383f9cc052f0
バーチャルパッドを作成する

Scratchでアクションゲームを作るときには、十字キーとボタンをもつバーチャルパッドを用意することになると思います。スマフォなど画面を直接タッチして操作する方式と、PCなどキーボードで操作する方式のどちらも用意したい時があります。そのような時は、それぞれの条件を定義して、その結果起こるアクションをイベントで通知すると作りやすいと思います。
<img src="https://cdn2.scratch.mit.edu/get_image/project/607962792_480x320.png">
十字キーは押し続けている時に反応して、離したら反応しなくなるようにしたいので、十字キースプライトのコードに「〜〜が押された」という条件を使って作ります。
<img width="75%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75307/37e37aba-44e3-098b-5199-13ebedb4d0c4.png">
ボタンは押したときに反応すれば良いので、ボタンスプライトのコードに「〜〜が押された時」という条件を使って作ります。
<img width="35%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75307/c1eca580-5918-b183-1654-1e777291efd0.png">
あとは、動かしたいキャラクターのスプライトのコードに、イベントに対する動作を作ります。
<img width="75%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75307/3bb420ed-35c4-1c19-7012-6ab8f188d794.png">

サンプルプロジェクト
https://scratch.mit.edu/projects/607962792
チームで作成した出欠管理システムをAWSへ移行しました！

昨年、社内チームで作成したQRコードを認証を利用した出席管理システムをAWSへ移行しました！
この記事ではその概要について紹介します。

前回の記事はこちらになります。
https://qiita.com/Hiroki1928/items/d7eb5d819cc5e99e6d4c

#実施内容
今回は下記の４つを実施しました。

１．リモート開発作業の推進
２．前年度成果物のAWS移行
３．認証機能の追加
４．フロントエンド資産のビルド・デプロイ自動化


#リモート開発作業の推進
- Discordに複数ボイスチャンネルを開設してバーチャルオフィスとして利用しました。
- モブプログラミングを活用した作業効率化・技術スキルのフォロー  
  ※モブプログラミングはチームの何人かで1組になってコミュニケーションをとりながら  
  リモート作業を行うことです。  
  共有して1つの作業を行うため通常よりも効率よく作業を進めることができます。
- 月例社内ミーティングでの開発作業 ＋ 週次 or 隔週でのリモート開発作業

![スクリーンショット 2021-11-28 101837.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2283274/0bafd5a0-bb94-93e9-c3b1-85d0db027c1b.png)



#前年度成果物のAWS移行

- 移行前と移行後の比較

|   |移行前|移行後| 
|:--  |:--  |:--|
|クラウド基盤 |Dockerコンテナ  |Amazon Web Service|
|Web  |Webコンテナ(Nginx・JavaScript)  |Cloudfront・S3・JavaScript
|API  |APIコンテナ(Flask・Python)|APIGateway・Lambda・Python|
|DB   |DBコンテナ(PostgreSQL)|DynamoDB|

- AWS移行後の概要

![移行図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2283274/b1212682-6477-5f3b-ba5d-1d16c3987bfd.png)

- Web画面はS3+CloudFrontで実装しました。
- CloudFrontはHTTPSに対応するために使用しました。
- APIの実装はAPIGatewayとLamdaで実装しました。
- DBはRDBからDynamoDBに移行しました。

#認証機能の追加
- 認証機能はAWSCognitoを使用することで実装できました。
- ログイン認証画面はAWSAmplifyを使用することで短時間で作成することができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2283274/eba6be0b-4379-cf2f-7b1d-2e1765623327.png)



#フロントエンド資産のビルド・デプロイの自動化

- AWSCodePipelineを使用してビルドからデプロイまでを実装しました。  
  ソースの変更をトリガーにパイプラインが実行されます。
- GitLabで管理されているソースを取得することができないので  
  CodeCommitに同期して実装しています。
- CodeBuildでCodeCommitに同期された資産をビルドしてS3にデプロイします。

![自動デプロイ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2283274/ab95f0a7-0074-017d-d9f1-e2058c457a52.png)

#リモート作業をして感じたこと
- リモートでの作業だったので通勤時間などがなく効率的に作業ができる。
- リモートだと相手の反応から理解度を認識することが難しい。
- 複数人で作業をしているときは発言のタイミングが難しい 。
 
#課題
- 各メンバーがリモート作業に慣れていくことが必要。
Python コードの書き方

#はじめに
動くコードは書けるが、基礎となる部分が曖昧だったのでまとめることにしました。
Python 3.8.2
https://github.com/Hirakawa0123/python_learning/blob/main/syntax/how_to_code.py
#ステートメントの区切り
ステートメントとは命令文の構成単位

Pythonのステートメントの区切りは、セミコロン「;」もしくは改行

```python:how_to_code.py:how_to_code.py
a = 10; b =20; c = a + b
print(c)

a = 30
b =40
c = a + b
print(c)
```

#ステートメントの改行
折り返す際は「\」を入力

```python:how_to_code.py
a = 1 + 2 + 3 + 4 + 5 \
    + 6 + 7 + 8 + 9 + 10
print(a)
```

#コメントアウトの書き方
すでにコメントアウトしてきたが、「#」を書くとコメントアウトすることができる
複数行コメントアウトする際は以下のように記載する

```python:how_to_code.py
#一行のコメントアウト

"""
複数行の
コメントアウトの
書き方
"""
```

#変数 大文字と小文字
出力するとそれぞれ別の値が入っていることが確認できる

```python:how_to_code.py
a = 1
A = 10
print(a)
print(A)
```

#値の区切り文字、改行指定
sepで区切り文字を指定、endで行末文字を指定する

```python:how_to_code.py
a = 1
b = 2
c = 3
ans = a + b + c

print(a,b,c)
print(ans)

print(a,b,c, sep = "、")
print(ans)

print(a,b,c, sep = "!", end = "end")
print(ans)
```

実行結果

```
1 2 3
6
1、2、3
6
1!2!3end6
```

#endを更に詳しく
endを何も指定しない場合は、自動的に改行される
改行を明示的に書く場合は、「end = "\n"」とする

```python:how_to_code.py
l = ["This","is","a","pen"]

for word in l:
    print(word)

for word in l:
    print(word,end = "\n")
```

出力結果

```
This
is
a
pen
This
is
a
pen
```

「end = ""」と指定すると改行なしで表示される
「end = "　"」と指定すると改行の代わりにスペースで表示される
「end = "\t"」と指定すると改行の代わりにタブで表示される

```python:how_to_code.py
for word in l:
    print(word,end = "")

for word in l:
    print(word,end = " ")

for word in l:
    print(word,end = "\t")
```

実行結果

```
ThisisapenThis is a pen This    is      a       pen     %
```
以上
Visual Studio Code の Arduino 拡張機能にシリアルポートを認識してもらう

# 誰のための記事か
　「ubuntu 上の開発で，Arduino IDE が辛いので vscode に Arduino 拡張機能を入れたけど，シリアルポートを認識してくれなくてつらい（しかも書き込み先がOpenCR）」人のための情報です（さっきまでの私）．

# 問題点
　vscode がシリアルポートを認識しないのは，設定ミスではなくバグということらしいです．

　散々時間を溶かした挙句，[このような記事](https://tmoribanner.hateblo.jp/entry/2020/12/02/190542)を発見して小躍りしたのですが，リンク先にあるように，以下の内容の arduino.json を作成して，

    {
        "port":"ttyACM0"    
    }

のように書いても，フリだけして書き込んでくれませんでした．

# 結論
vscode ワークスペースの直下に .vscode/arduino.json を作って，

    {
        "port":"/dev/ttyACM0"    
    }

とシリアルポートを /dev から書けば幸せになれます．
（追伸：arduino.json には，対象CPUなどの情報も書き込まれますが，そこは自動でよしなにやってくれます）
ファイル名を難読化する方法

# はじめに
ファイルを先にサーバーにアップロードしておきたいけれど、そのファイルの存在は事前に知られたくない（URLを推測され画像を見られたくない）ということが稀にあります。
誰でも使えるようにシェルスクリプトを作成しましたので、備忘録として残したいと思います。

# 動作確認環境
- Windows10 Home
- Git Bash

# 使い方
拡張子が.shで終わるファイルを作成します。
以下のサンプルを貼り付けます。
ファイルをダブルクリックすると、シェルスクリプトと同階層にあるファイルのファイル名がすべて難読化されます。

# サンプル

```bash
#!/bin/bash

# ファイル名をハッシュ値に変換する
# 参考：
# https://stackoverflow.com/questions/8201729/rename-files-to-md5-sum-extension-bash

# コピー先のディレクトリを作成（-pをつけることで存在している場合は作成しない）
mkdir -p ../work

# もとファイルを作業ディレクトリにコピー
for filepath in `find  -name '*.png'`
do
  filename=`basename ${filepath}`
  cp ${filepath} ../work/${filename}
done

# 作業ディレクトリ内に移動し、ファイル内のものをハッシュ化
cd ../work
md5sum * | sed -e 's/\([^ ]*\) \(.*\(\..*\)\)$/mv -v \2 \1\3/' | sh

# 入力あるまで待機
read -p "Complete. Press any key: "

```

# 応用
サンプルをもとに、差分のテキスト出力やすでに難読化しているものは除外する処理の追加などの改良を加えました。
こちらの方がより柔軟な使い方がができるので、利用する際はこちらをオススメします。

```bash
#!/bin/bash

# ファイル名をハッシュ値に変換する
# ファイル名だけを変えてもハッシュ値は同じです。ファイルの中身によってハッシュ値が決まります

# コピー先のディレクトリ名
output_directory_name=output

# 現在のディレクトリ名を取得
current_directory_path=$(cd $(dirname $0);pwd)
directory_name=`echo "$current_directory_path" | sed -e 's/.*\/\([^\/]*\)$/\1/'`

# コピー先のディレクトリを作成（-pをつけることで存在している場合は作成しない）
mkdir -p ../$output_directory_name/$directory_name

# 実行回数カウンター
run_count=0

# もとファイルを作業ディレクトリにコピー
for file_path in `find  -name '*.png' -or -name '*.jpg'`
do
  # 拡張子の取得
  extension=${file_path##*.}

  # ファイル名の取得
  file_name=`basename ${file_path}`

  # ハッシュ値のみを取得
  hash_name=($(md5sum ${file_path}))

  # 出力先のパスを取得
  output_path=../${output_directory_name}/${directory_name}/${hash_name}.${extension}

  # ファイルが存在していなければ処理を実行（-eをつけることでファイルの存在をチェック）
  if [ ! -e ${output_path} ]; then
    # ハッシュへの変換履歴を残す
    echo "${file_name},${hash_name}.${extension}" >> ../${output_directory_name}/${directory_name}/hash_diff.csv

    # ハッシュ化したものを別ディレクトリにコピー
    cp -v ${file_path} ${output_path}

    # 実行回数を加算
    run_count=$(($run_count + 1))
  fi
done

# 何も処理しなかった場合は明示的に画面に表示する
if [ ${run_count} -eq 0 ]; then
  echo "There was no target."
fi

# 入力あるまで待機
read -p "Complete. Press any key."
```

# 参考ページ
https://stackoverflow.com/questions/8201729/rename-files-to-md5-sum-extension-bash

https://git-scm.com/

https://srkzhr.hatenadiary.org/entry/20081216/1229449984
STM32G031で4ピンから「hello...」をシリアル出力(VSC,cubeid)HAL(STM32)(LPUART)



目的
シリアルのテスト

x 過去ログをみよ->

x ----重要---- OBで4ピンをGPIOにする　わからない人は、やらない方がよい

x 7ビットらいし　要注意　わからない時は、誰かに聞いてね!!
x cubemxはdosco-g0316
x vscは、nucleo-g031


stm32g031_lpusrt1_1内をいろいろコピー





https://os.mbed.com/users/caa45040/code/f303_h_p1/






![o_con118.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/4fcb2814-70bb-3d27-c853-7c9f00adea0b.jpeg)



![o_con119.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/94918e92-6370-458b-fe72-7aaf995037bb.jpeg)



![o_con121.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/8c291939-509b-45fe-c05a-aad88ae213f0.jpeg)




主なプログラム　main内のwhile内


```c++



    HAL_UART_Transmit(&hlpuart1, (uint8_t *)"hello world\r\n", 13, 10);

    //HAL_Delay(500);



  
    
    
    HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
    HAL_Delay(500);
    
    HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
    HAL_Delay(500);
    
    
    

 



```
neosでlogix その6


# 概要

niosでlogixやってみる。
world作ってみた。

# 写真

![world.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/487c12f9-c1b6-66c6-4567-4e64c2b25a4a.jpeg)


# 手順

- 新規ワールドの作成をクリック
- GridSpaceを選択
- プライベートを選択
- セッション開始


以上。
Raspberry Pi ウェブサーバを1ヶ月と3日連続運用した

https://x.optgeo.org/kid-c などをホストしているサーバは、 [Raspberry Pi 4B で動かしています](https://docs.google.com/presentation/d/1z30VuPQpstpug8WvoXkBscxA8KGQuJDAuCPzFuoXU6Y/edit?usp=sharing)。1ヶ月と3日連続で nginx のウェブサーバを運用しましたが、Let's Encrypt からもらっているサーバ証明書の更新を反映するには nginx を再起動する必要があったので、 nginx を再起動しました。

結局のところ、私が取らなかったリスクは、どなたかが取ることになります。そうなるよりは、私がリスクを取ったほうが良いでしょう。結局のところ、エンジニアリングというのは、制御可能なやり方で連続的にリスクテークしていくプロセスなんだと思います。Happy [risk-taking](https://blogs.ibo.org/blog/2015/07/08/risk-taking-what-does-it-mean-to-you/)!
【図解解説】JOI2021-2022 一次予選 第2回 問題3 次の文字

## 図解解説シリーズ
競技プログラミングを始めたばかりでAtCoderの解説やJOIの解説ではいまいちピンと来ない…という人向けに、図解を用いて解説を行います。

## 問題文
### 情報オリンピック日本委員会に掲載されている問題

https://www.ioi-jp.org/joi/2021/2022-yo1/2022-yo1b-t3.html

### AtCoderに掲載されている問題
入出力など実際に確認して自分の作成したプログラムを採点することができます。

https://atcoder.jp/contests/joi2022yo1b/tasks/joi2022_yo1b_c

## 図解解説
今年度の一次予選のC問題は、以下の４つのスキルを確認する問題になっています。
１．入力・出力を正しく利用できる
２．算術演算子を正しく利用できる
３．条件分岐（if）を正しく利用できる
４．繰り返し処理を正しく利用できる

問題文を整理するために、具体的な数字を用いて、図示して考えてみます。
![スライド1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2211017/3b5db1c5-ab32-4f9f-0aa1-fa6fc062a788.png)
Pythonでの文字列は、1文字ごとに先頭から0,1,2,3,…と番号が割り当てられています。したがって、先頭の文字は「変数名[0]」と指定して取り出すことができます。この仕組みを利用して、この問題のルールと照らし合わせて整理をしていきます。

まず、ルールを確認します。1回目は先頭から2文字目を確認します。もし、2文字目がJなら、1文字目の文字を表示します。次に、2回目は先頭から3文字目を確認します。もし、3文字目がJなら、2文字目の文字を表示します。つまり、先頭からn文字目を確認し、n文字目がJなら、一つ手前の文字（n-1文字目）の文字を表示する…という操作を行っていきます。

具体的に入力例１を用いて考えてみます。1回目の操作は2文字目を確認します。2文字目はOなので、そのまま次の文字に移動します。2回目の操作は3文字目を確認します。3文字目はJなので一つ手前の文字である2文字目の文字Oを表示します。次に3回目の操作は4文字目を確認します。4文字目はOなので、そのまま次の文字に移動します。最終的に6文字目までこの操作を繰り返し行っていきます。

問題文のように一般化して考えると、『i+1文字目を確認し、i+1文字目がJなら、i文字目を表示する』ことになります。文字列の1文字目を指定するときは、上図の赤文字0を指定する必要がありますので、前述のiの値をいくつからいくつの値に設定すればよいでしょうか？

1回目では赤文字1を指定します。そのため、i=0を指定して1回目の操作を行えばよさそうです。最後は赤文字5を指定します。そのため、i=4を指定して最後の5回目の操作を行えばよさそうです。操作の回数は文字列の文字数N=6から1減らしたN-1回指定すればよさそうです。

## 解答例

```c1.py
N = int(input())
S = str(input())
#繰り返し処理を「文字数-1回」行います。したがってrangeに指定する値はN-1です。
#文字の指定は0番目から始まりますので、1番目の文字(2文字目)から
#順番に確認を行い、Jと一致する場合は一つ手前の文字を表示する
for i in range(N-1):
  if S[i+1]=='J':
    print(S[i])
```
[採点サイトに提出したプログラム](https://atcoder.jp/contests/joi2022yo1b/submissions/27557757)

## イラスト
スライド内で使用しているイラストはすべて「[いらすとや](https://www.irasutoya.com/)」の素材を利用しています。
【Nuxt.js・TailwindCSS】条件によって動的にクラスを付与する方法

#はじめに
こんにちは。
こちらの記事では、動的にクラスを付与する方法を記しています。
誤っている点がございましたらコメントいただけると幸いです。

#実装手順
バインドしたクラス`buttonColor`に対して、computedを使用することで条件ごとにTailwindCSSのクラスを変更する実装を行います。


```html:template
<button v-bind:class="buttonColor">
  送信
</button>
```

```javascript:script
export default {
  data: function () {
    return {
      formData: ""
    };
  },
  computed: {
    buttonColor: function () {
      return {
        "bg-gray-200": this.formData === "" ,
        "bg-red-500": this.formData !== "",
      };
    },
  },
}
```

フォームに何も入力されていないときは`bg-gray-200`を適用してボタンの背景色を変更する。フォームにデータが入力されている場合は、`bg-red-500`を適用する。
computedでは、データの参照にはthisを使用してreturnで値を返す。

##参考
* [クラスとスタイルのバインディング](https://jp.vuejs.org/v2/guide/class-and-style.html)
* [computed で classを動的に指定](https://qiita.com/t_109609akg/items/8a4ec11c52ee604d64c2)

<br>


#おわりに
ここまで動的にクラスを付与する方法についてまとめました。
これからも転職活動と並行してアウトプットも継続しながら、技術力の向上に努めていきます！

以上、最後まで読んでいただきありがとうございました！
よければLGTMを押してくれると嬉しいです！
CODE for GIFUの代表を辞めてからやったこと

この記事は[CivicTech ＆ GovTech Advent Calendar 2021](https://qiita.com/advent-calendar/2021/civictech)の1日目の投稿です。

2018年6月からコミュニティの代表になって、2021年1月に代表を辞めました。辞めた理由はシビックテックに疲れたとか、仕事が忙しくなったからではありません。CODE for GIFUでは役員（代表、副代表、事務局長、会計）は3年任期の交代制になっているからです。詳しくはこちらに投稿しています。

https://www.code4japan.org/news/civic-tech-fun-fun-report-2021-1





ちなみに2018年に代表になったときのAdvent Calendarの投稿がこちらです。

https://qiita.com/ishii-gifu/items/b8f1da665fe41ee7f60e

2018年の時点で、「CODE for の代表って何だろう？」ということを書いていましたね。このスタンスというか考え方は今も変わっていません。

- あるべき論は必要ない
- バランスをとれる人がいい
- 安心感を与える人になりたい

# 主体性を持たせることは難しい

代表として活動していく中で、ひとつ思ったことがあります。それは「主体性を持たせることは難しい」ということです。

シビックテックとは「テクノロジーを使って身の回りの困りごとを自分達の手で解決する」活動です。なので、コミュニティに参加する方は困りごとがあって、自分で解決していきたいと思っていることが理想です。そうであるなら必然的に「誰かが何かやってくれる」と思うのではなく、「自分がやらねば」という主体性をもって参加しているはずです。

でも、普段の生活でそんなに困っていることを感じないのも事実です。代表をやっていた私も同じです。特に困っていない（笑）。だから、理想としてはメンバーに主体的にかかわってもらって、それぞれでそれぞれの活動を続けてほしいけど、それは難しいのです。

# 主体性を持たせる必要はない

ただ、「主体性を持たせる必要はない」とも思うようになりました。そもそも主体性というのは他人が「持たせる」ものではなく、自分自身で「持つ」ものなんですよね。昨年2020年にはコロナ禍であるにも関わらずCODE for GIFUでは様々なプロジェクトが立ち上がりました。[新型コロナウイルス対策サイト岐阜県版](https://covid19-gifu.netlify.app/)や[OneDoc](https://protopedia.net/prototype/2058)、路地猫活動、等です。

これらの活動は代表からメンバーに呼びかけたものはなくて、メンバーがやりたいといって始まったことばかりでした。環境や状況や個人のタイミングによって主体性は湧いてくるのです。シビックテック活動では代表がみんなを引っ張る必要はないのです。メンバー同士でやりたいことを話し合って、それぞれのプロジェクトでリーダーがいて、それぞれのやり方で、それぞれの結果を出していくことが大切なのです。

# 辞めて、見方が変わった

もともと「代表」としてやっていたことは、年数回の総会や役員会を主催することでした。代表になって生活が変わったことがなかった時と同じ様に、辞めても生活は変わりませんでした。

ただ、CODE for GIFUの見方は少し変わりました。

- 安心感がある
誰かが引っ張らなくてもコミュニティとして継続してくことが分かったこと、代表をやってもらえる人がいることで安心感ができました。

- もっと長い目で見るようになった
コミュニティを運営していくことやイベントへの参加率とかはあまり気にならなくなりました。それぞれの主体性が持ち上がるまで気長に待てばよいのです。

# 代表を辞めてやったこと

代表を辞めて生活は変わりませんでしたが、やったことは３つあります。

- <strong>Fun!Fun!Reportを多めに投稿するようにした

Code for Japanが月１回各地のコミュニティの活動をレポートするCivic Tech Fun! Fun! Report!に積極的に寄稿するようにしました。コミュニティの活動を知ることができるレポートなのですが、代表じゃなくても書いていいんですよね。

https://www.code4japan.org/news/civic-tech-fun-fun-report-2021-4

https://www.code4japan.org/news/report/civic-tech-fun-fun-report-2021-6

https://www.code4japan.org/news/report/civic-tech-fun-fun-report-2021-8

https://www.code4japan.org/news/report/civic-tech-fun-fun-report-2021-10

- <strong>ポッドキャストはじめました

「シビックテックの入り口がちょっとでも広がるといいなあ」、と思い、9月から埼玉の太田さんと川崎の小俣さんと3人でポッドキャストをはじめました。すでに30回以上収録をしています。10分以内の短いポッドキャストになっているので、スキマ時間に聴いてくれると嬉しいです。Apple PodcastやGoogle PodcastやSpotifyにも配信しているので「シビックテック」で検索すると見つかります。

シビックテック井戸端キャスト
https://anchor.fm/civictechcast

- <strong>NPTech Studioに参加しました

Code for Japanが主催するNPTech Studioに参加しました。NPTech Studioとは、NPO団体の課題を一緒に考えて、テクノロジーを活用し解決していく取り組みです。9月からはじまって4か月間取り組んできました。なかなかのハードスケジュールですw

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151569/c942c62a-423a-c2a0-9018-be91cb120892.png)

12/4には成果発表会もあるので、気になっている方はご参加ください。

https://nptechstudio-c4j-20211204.peatix.com/


# さいごに

2022年はコロナも落ち着くと予想してミートアップ的なイベントを岐阜で開催したいと考えています。これからもシビックテックな活動に関わっていきますので、ご協力お願いします。
料理人からエンジニアになってみて

2020年の夏頃から約4ヶ月間「ポテパンキャンプ」というプログラミングスクールを受講してエンジニアに転職致しました。

■前職の内容
私は2016年から料理人として勤務しておりました。
婚礼料理を中心に主に懐石料理を作ることに従事しておりました。

■エンジニアになろうと思ったきっかけ
高校時代に商業高校の情報処理科ということもありPCを触ることやプログラミングについて多少知見がありプロゲートやドットインストールで学び始めてから「楽しい」と感じたためエンジニアになろうと思いました。

料理人からエンジニアになった経緯としては2020年にコロナウイルスが流行し、実家の飲食店を継ぐことが困難になり転職を考えました。
もともと家業を継ぐために、料理人になったため継がない場合は違う職種に転職しようと思っていました。
そこで、前述に記載したようにプログラミングが「楽しい」と感じた事が主なきっかけでございます。

■エンジニアとして働いてみた感想（前職と比べてどう変わったか）
感想としては、自由度が高く風通しの良い職場で毎日がとても充実していると思ってます。

前職の料理人時代では、年功序列だったりやりたいことをできるチャンスがなかったりという感じでした。
エンジニアとして転職してからはフルリモートOKのためどこで働いても良く、社員数が少人数で風通しも良いため自分の考えが社長まで届くので未経験から入社致しましたが沢山経験を積ませていただけることにやりがいも感じております。

また、自社開発系企業のためクライアントが存在せず納期がないため自分の裁量で仕事が進められることもすごいなと感じました。
また、納期がないビジネスモデルを確立できているため自身の副業に割く時間も増え本業＋副業が可能となり毎日が充実していると実感します。

■今後はどんなエンジニアを目指したいか
エンジニアとしての理想像はコードを記載するだけでなく基本設計〜リリースまで「この人に任せておけば問題ない」と思われる人材を目指したいと思っています。

エンジニアに転職してもうすぐ1年経ちますが、エンジニアはコードを記載するだけでなくどんな仕様にするのか、なぜその仕様なのか、そもそもこの機能は必要なのか...etc
上記の事を物凄く考えます。
いわゆる上流工程ですが、この上流工程でしっかりとした考えをたてておかないと機能をリリース出来ても効果が薄いなと感じました。
なので、基本設計〜リリースまでしっかりと出来るエンジニアになって信頼されるエンジニアになりたいと思います。
足掛け1年でAWSソリューションアーキテクトアソシエイト(SAA-C02)に合格しました。

# はじめに
[前回](https://qiita.com/e-takazawa/items/98c423fc9c800f68290d)まではAWSソリューションアーキテクトアソシエイト(SAA-C02)を取得するためにゆるっと勉強していたのですが、ちょっと前にソリューションアーキテクトに無事合格したので、その時に思ったことややったことについて書いていこうかな、と思います。
ソリューションアーキテクトの資格取得を検討している方、今勉強をしている方に少しでも参考になればと思います。

# 1回目は落ちて2回目で合格しました
初めて受けた時は 699点で不合格でした。
正直悔しかったのですが、よくよく考えてみると敗因は確かにあったなと感じました。
私が感じたこととしては以下の通りです。

- 判断に悩む選択肢があった。
- 知らないサービス名が出てきた。

選択肢の中には最良解と最適解があり、これが自分にとっては最良の選択肢だと思って選んでいても、実はこれこれこういう条件がある場合はそれとは別の選択肢を選ばなければならないこともあるので、そこをちゃんとジャッジしないとなと痛感しました。
また、知らないサービス名が出てきて悩むのは単純に勉強不足だなと思ったので、改めて勉強し直し、2回目は803点で合格しました。

# 受験1回目でやってきたこと
## 試験対策テキストの読み込み
私が読んだテキストは[こちら](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9A%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88-%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88-NRI%E3%83%8D%E3%83%83%E3%83%88%E3%82%B3%E3%83%A0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE/dp/4815607389/)です。
大まかに試験の出題範囲を確認するのに役立つかなと思います。
ただ、これを読み込んだだけでは合格できないかな、と思うのが正直なところです。
実際、この本に出てこないことが結構出てきたので、公式ドキュメントの読み込みが必須かなと思います。

## ハンズオン
[AWSの公式ハンズオン](https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-hands-on/)もありますが、私はUdemyさんの[こちらのハンズオン](https://www.udemy.com/course/aws-associate/)で一通り実施しました。
RDSの構築に時間がかなりかかるので、最悪ハンズオンの動画を見るだけでもいいかなと思いました。

## 模擬試験に取り組む
[Udemyさんのハンズオン](https://www.udemy.com/course/aws-associate/)に模擬試験も含まれるのでこちらである程度の試験慣れはできるかなと（受けるまでは）思っていました。
実際のところ、試験慣れすれば解ける問題は限られているので、単純に知識量を蓄えないと本番の試験では通用しなさそうです。

# 受験2回目に向けてやったこと
1回目の不合格が正直悔しかったので、2回目はかなりガムシャラに取り組みました。
なので、そこそこ非効率なこともやっています。
## AWS公式ドキュメントの読み込み
知らないサービス名に悩むのが嫌だったので、[全サービスのドキュメント](https://docs.aws.amazon.com/)を一通り読み込みました。
闇雲に見ても覚えられないので、以下の点を意識して読みました。

- 出題範囲のサービスについてはどのように使うか、どんなことができるかを一通り見る。
- 一見出題範囲ではないサービスについても概要レベルでできることを掴んでおく。

知識を溜め込むことで本試験でも自信を持って出題内容を検討することができたので、これが得点アップに一番効果があったかなと思います。

## 模擬試験にさらに取り組む
試験慣れしてないのが原因かなと思ったので、[Udemyさんの模擬試験集](https://www.udemy.com/course/aws-knan/)についても一通り取り組みました。
本模擬試験は難易度が高く一度も合格点は取れませんでしたが、そんな私が本試験で803点なので、それぐらいの難易度だと思ってよいかと思います。

## AWS BlackBelt Online Seminarの視聴
公式ドキュメント以外にも[動画によるセミナー](https://aws.amazon.com/jp/aws-jp-introduction/)が提供されているので、これを視聴しました。
個人的には動画視聴による学習が苦手で途中で眠くなってしまうので、勉強という意味ではあまり意味はありませんでした。
ただ、[AWS公式チャンネル](https://www.youtube.com/c/JPAmazonWebServices/featured)を登録することで、受験後も定期的に視聴し、新しいサービスをキャッチアップするのにいい機会になっております。

# おわりに
いかがだったでしょうか。
ソリューションアーキテクトの学習は公式非公式を問わず様々な教材がたくさんあるので、どの程度やればいいのかが難しいかなと思いますが、ご自身のあったやり方を選ぶのがよいのではと思います。
JavaでOutOfMemoryError: GC Overhead limit exceededを穏当に解決した話

この記事は、[シアトルコンサルティング株式会社 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/seattleconsulting)の3日目の記事です。
こんにちは、シアトルコンサルティングの長岡です。

## はじめに
業務で1000万件くらいのデータに対し、DB1のデータをマスタDBと比較し、一致したデータがあれば別名に変換しDB2へ出力するというようなプログラムを作成し実行した際に、OutOfMemoryError: GC Overhead limit exceededが発生し、現場メンバー揃って苦戦したのでその時のことを書いていこうと思います。

## OutOfMemoryError: GC Overhead limit exceededとは
Javaのヒープ領域にオブジェクトを割り当てるための十分な空間がない時に発生するエラーです。
冒頭でも触れた通り、処理すべきデータ量が膨大な時に頻発します。
JavaプロセスがGCの実行時間の98％以上を費やし、各実行で2％未満のヒープしか回復されない場合に、このエラーをスローするように設定されているみたいです。

## 試した事
調べてみるとヒープ領域のデフォルトサイズが512MBみたいだったので、JVMの起動時に-Xmx3Gを指定して、実行してみました。
すると数時間動いた末に、再度OutOfMemoryError: GC Overhead limit exceededが発生しました。
スケジュールの関係上あまり余裕が無かった為、対応できませんでしたが、メモリリークが発生しない実装ができれば解決する話です。

## 結果
試行錯誤は早々に諦めてプログラムで扱うデータ数を指定して分割して実行することにしました。
調べてみると、100万件を過ぎたあたりからプログラムのスローダウンが始まり、処理速度がどんどん落ちている事が分かりました。
その為、プログラムを10個に分けて100万件ずつデータを扱うように修正し、同時進行でプログラムを実行し約1時間で無事データを変換することができました。

## さいごに
今回はテストデータを作成する為に作成したプログラムだったので今回のような方法で穏当に解決しましたが、本番アプリケーションのプログラム内で同じようなことが発生した場合は今回のような対応ではなく、メモリリークが起きている原因を特定し、より良いプログラムに修正する必要があると思いました。
今回は１０００万件のデータに対し、メモリリークを意識しない実装が原因で起きたエラーだったので、大量のデータを扱うプログラムを組む際はお気を付けください。

## 参考
・[OutOfMemoryの公式ドキュメント](https://docs.oracle.com/javase/jp/8/docs/technotes/guides/troubleshoot/memleaks002.html)
・[参考にした記事](https://ja.getdocs.org/java-gc-overhead-limit-exceeded/)
主に使うファイル検索オプション

既出だと思うけど、メモ程度に

##ファイル検索
```
zombie:~/working$ ls
aaa.txt  dmy  python_file
zombie:~/working$ ls ./dmy/
abb.txt  abc.txt  abc2.txt  abc22.txt  abc3.txt
```
**findコマンド**
何もオプションつけずに.(コロン)だけ
→ディレクトリとその配下にあるファイルを表示

```
zombie:~/working$ find .
.
./aaa.txt
./python_file
./python_file/showHex.py
./dmy
./dmy/aaa.txt
./dmy/abb.txt
./dmy/abc22.txt
./dmy/abc3.txt
./dmy/abc.txt
./dmy/abc2.txt
```

ファイル名が分かっている場合(ワイルドカードなし)

```
zombie:~/working$ find . -name aaa.txt
./aaa.txt
./dmy/aaa.txt
```

ワイルドカード使っての検索
→【-name】を使用

```
zombie:~/working$ find . -name aa*
./aaa.txt
./dmy/aaa.txt
``` 

ディレクトリ(ファイル)だけ指定
→【-type d (-type f)】を使用

```
zombie:~/working$ find . -type d
.
./python_file
./dmy
```

検索該当以外のものを表示

```
zombie:~/working$ find . -not -name aa*
.
./python_file
./python_file/showHex.py
./dmy
./dmy/abb.txt
./dmy/abc22.txt
./dmy/abc3.txt
./dmy/abc.txt
./dmy/abc2.txt
```
Javaのマルチスレッド実装例(後編)（排他制御編）

この記事は、[シアトルコンサルティング株式会社 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/seattleconsulting)の2日目の記事です。
こんにちは、シアトルコンサルティングの長岡です。

## はじめに
前回はプログラムをマルチスレッドで実行してみました。
[Javaのマルチスレッド実装例(前編)](https://qiita.com/Ryooooo/private/c4fdffa50ad31c972bad)
今回はマルチスレッドでプログラムを実行した際の注意点として上げられる、排他制御について書いていこうと思います。
今回も前回同様駆け出しエンジニアの方達にも理解できる内容となっております！

## なぜ排他制御が必要なのか？
前回の記事でも書きましたが、マルチスレッドの処理で同じオブジェクトにアクセスしてしまうと同じフィールドの値を書き換えてしまう為、最終的に期待した値が帰ってこないことがあります。  
その為、同じオブジェクトにアクセスする場合はsynchronizedを使用し、排他制御を実装する必要があります。

## 排他制御の実装
排他制御を実装するにあたり、まずは排他制御なしでプログラムを動かしてみます。  
プログラムの内容は初期値0の共通オブジェクトに対し、1000追加するメソッドを1000スレッドで動かし、最後にオブジェクトの値を出力します。
想定通りの動きをするパターンもある為、上記のプログラムをfor文で10回動かしてみます。  

```java:Main.java
package main;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Main {

	public static void main(String[] args) throws InterruptedException {
		
		for(int i = 0; i < 10; i++) {
		    
			Bank.bank = 0;
			
			int threadNum = 1000;
			
			// 引数に生成するスレッド数を渡す
			ExecutorService exec = Executors.newFixedThreadPool(threadNum);
			
			Callable<String> sub1 = new Sub1();
			
			List<Callable<String>> tasklist = new ArrayList<>();
			
			for(int j =　0; j < threadNum; j++) {
				tasklist.add(sub1);
			}
			
			List<Future<String>> future = exec.invokeAll(tasklist);
			
			System.out.println(Bank.bank);
			
			exec.shutdown();
		
		}
	}
}

```

```java:Sub1.java
package main;

import java.util.concurrent.Callable;

public class Sub1 implements Callable<String>{
	
	public void addBank() {
		
		Bank.bank += 1000;
		
	}
	
	@Override
    public String call() throws Exception {
		
		addBank();
		
		return null;
    }
}
```
```java:Bank.java
package main;

public class Bank {

	public static int bank = 0;
	
}

```
```java:出力結果
999000
1000000
1000000
1000000
1000000
1000000
1000000
1000000
1000000
1000000
```

一番最初の出力が999000になっていますね。  
bankの値が998000のタイミングで同時に1000追加する処理を行った為、このような結果になったのだと思います。  
今回の様な結果を防ぐ為、排他制御を実装していきます。
排他制御の実装は非常に簡単です。  
下記の様にスレッドで呼び出すメソッドにsynchronizedをつけるだけです。  

```java:Sub1.java
public synchronized void addBank() {
		
		Bank.bank += 1000;

}
```

では、実行してみます。

```java:出力結果
1000000
1000000
1000000
1000000
1000000
1000000
1000000
1000000
1000000
1000000
```
全て想定通り出力されていますね。

## 参考
・[synchronizedについて](https://java-code.jp/295)
【学んだこと】CORSに対応したApache Solrの使い方

これ、結構はまりました。解決方法を学びましたのでメモしておきます。

LocalhostにPort80でWEBサーバを立てます。同じくLocalhostにPort8983でApache Solrを作動させます。Apache Solrの結果を参照するWEBページを作ります。CORSの制限に引っ掛かり、エラーになります。

CORSとは、Cross Origin Resource Sharing　の略です。複数のORIGINで構成する一つのWEBページは該当します。この方法をつかうと、ユーザーが意図しないアクセスをWEBページ側に仕掛けることができてしまうので近年、サーバー側およびクライアント側の双方でこれを許可する設定になっていないとエラーとし、内容データが取得できない結果になる仕組みです。

https://developer.mozilla.org/ja/docs/Web/HTTP/CORS

さて、そこで、サーバー側の設定を行います。

サーバー側はすなわちApache Solrです。これが公式の説明資料がない。検索して以下のサイトを見つけました。

https://opensourceconnections.com/blog/2015/03/26/going-cross-origin-with-solr/

こちらの情報に従い、Solrの設定ファイルを操作します。参考サイトは５年前、Ver.5のもので現在、ここで操作しているのは最新Ver.8.5.1・・・。通用するのか心配しましたが、結果としてうまくいきました。

${Solr_Home}/../server/solr-webapp/webapp/WEB-INF/web.xml　を編集。

<web-app ...>タグの直後に次のとおり挿入します。

    <filter>
       <filter-name>cross-origin</filter-name>
       <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
       <init-param>
           <param-name>allowedOrigins</param-name>
           <param-value>http://localhost</param-value>
       </init-param>
       <init-param>
           <param-name>allowedMethods</param-name>
           <param-value>GET,POST,OPTIONS,DELETE,PUT,HEAD</param-value>
       </init-param>
       <init-param>
           <param-name>allowedHeaders</param-name>
           <param-value>origin, content-type, accept</param-value>
       </init-param>
    </filter>

    <filter-mapping>
        <filter-name>cross-origin</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

この挿入部分の上から　６行目　が味噌です。ここに、プロトコル＋CORS許可するサーバー名を書き込みます。Originを書き込むので、ポート番号まで指定するほうがよいかもしれません。

これで Apache Solrを再起動。

いっぽう、クライアント側。

クライアント側はFetch APIを使ってみましたので、modeアトリビュートに’cors' を明記します。以下は、fetchして取得したテキストを動的に張り込むファンクションの例です。

        function updateDisplay(url) {
            fetch(url, {
                method: "GET",
                mode: "cors",　 // <- ここ。
                credentials: "include"
            }).then(function(response) {
                console.log(response.status);
                console.log(response.headers.get('Content-Encoding'));
                response.text().then(function(text) {
                    poemDisplay.textContent = text;
                });
            });
        }

このファンクションに、localhostのApacheSolrへのクエリーを含むURLを引数として渡すと、返信を受け取ることができました。

これって意外に情報少ないんですけど、みなさん、ApacheSolrをCORS対応しないで使えてるんですかね？
（参考注記：同じ記事をLinedInにも記載しています。）
Node.js・ブラウザ（JavaScript）で処理時間を測る方法のいくつか

JavaScript で処理時間を計測する場合の話で、複数の方法があるので、そのいくつかをまとめてみました。

Node.js は 2通り、ブラウザ（Chrome を利用）は 3通りの方法を試しています。

## Console API
最初は Console API です。

●Console API reference - Chrome Developers
　https://developer.chrome.com/docs/devtools/console/api/#time
![Console_API_reference_-_Chrome_Developers.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/6d456884-0aef-8554-3a42-973ed39bdd8e.jpeg)

以下、ブラウザと Node.js でそれぞれ動かしてみたものです。

### ブラウザ

```html
<html>

<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>

<body>
</body>
<script>
    console.log("start");
    console.time("test");

    let count;
    const num = 2000000000;
    for (let i = 0; i < num; i++) {
        let square = i ** 2;
    }

    console.timeEnd("test");
    console.log("end");
</script>

</html>
```

以下の出力が得られました。
![ブラウザで.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/ef8458b6-37f9-f46f-069d-6a7fc2b2dbf0.jpeg)

### Node.js

```javascript
console.log("start");
console.time("test");

let count;
const num = 200000000;
for (let i = 0; i < num; i++) {
  let square = i ** 2;
}

console.timeEnd("test");
console.log("end");
```

実行結果は以下の通りです。
![Node.jsで.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/09a19072-0ae3-ebb5-9574-9c8702707754.jpeg)

## Performance
次は以下を試します。

●Performance - Web API | MDN
　https://developer.mozilla.org/ja/docs/Web/API/Performance

●Performance measurement APIs | Node.js v17.1.0 Documentation
　https://nodejs.org/api/perf_hooks.html

以下、ブラウザと Node.js でそれぞれ動かしてみたものです。
Node.js の場合は `const performance = require("perf_hooks").performance;` という部分を追加しています。

### ブラウザ

```html
<html>

<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>

<body>
</body>
<script>
    console.log("start");
    const startTime = performance.now();

    let count;
    const num = 2000000000;
    for (let i = 0; i < num; i++) {
        let square = i ** 2;
    }

    console.log(`${performance.now() - startTime}`);
    console.log("end");
</script>

</html>
```

### Node.js

```javascript
const performance = require("perf_hooks").performance;

console.log("start");
const startTime = performance.now();

let count;
const num = 200000000;
for (let i = 0; i < num; i++) {
  let square = i ** 2;
}

console.log(`${performance.now() - startTime}`);
console.log("end");
```

出力は省略しています。


## ブラウザ（Chrome）の開発者ツール
以下の記事に、Chrome の開発者ツールを使った例が書かれていたので、それを試してみました。

●JavaScriptで任意の処理にかかる時間を計測する
　https://sbfl.net/blog/2017/12/01/javascript-measure-time/

手順は以下となります。

1. Chrome で開発者ツールを開く
2. Performanceタブを開く ⇒ 
3. 左上にある丸型のアイコンかその隣のアイコンを押して計測開始4
4. Stopボタンを押す」

以下は、計測結果が表示された場所のキャプチャです。

![開発者ツールで.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/975a4596-ff5e-e1f9-d013-881b829abb1b.jpeg)
pythonでファイルの中からランダムで一つの音源をとってくるプログラム

#目的と準備
ランダムでひとつのmp3を
とってきてほしい
という願望がでてきたため

準備として
音源をまとめたディレクトリを作っておく
今回はjapanese50onという
五十音をいれたものを使った

#音声ファイルを一つとってくる
以下のサイトを参照した

https://www.higashisalary.com/entry/python-random-choice

```
import glob
import os
import random
list=glob.glob('japanese50on/*.mp3')
data=random.choice(list)
```

このコードではjapanese50onのなかにある
mp3のファイルから一つをランダムに
とりだすということを行っています
dataのなかには相対パスで書かれた
ランダムなmp3の名前が入っています


#音声ファイルをコピーする

以下のサイトを参照した
https://techacademy.jp/magazine/46185


```
import shutil
shutil.copyfile(data,'sound.mp3')
```
これをつかうと
dataの相対パスのファイル（ランダムに選ばれたファイル）
をsound.mp3として今いるディレクトリにコピーすることができる

#これでできます
まるごとコピーすれば使えます

```
import glob
import os
import random
list=glob.glob('japanese50on/*.mp3')
data=random.choice(list)

import shutil
shutil.copyfile(data,'sound.mp3')
```

これをつかうと
５０音の中から選ばれた一つがsound.mp3としてコピーされたはずです