OmniAICreator/Qiita-1.07M huggingface dataset:
自動販売機のフローチャートの代わりに擬似コードで書いてみた

昨日以下のように自動販売機はフローチャートでなくて状態遷移図だろうとつぶやいた

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">昔ある人が「フローチャートの良い教材を見つけた。それは自動販売機だ」と言ったのを聞いて「自動販売機なら状態遷移図だろう」と思ったのだが、その人があまりにも自信満々で話が通じないだろうと思い、黙っていたことを思い出した。同意もしなかったが。</p>&mdash; 徳丸 浩 (@ockeghem) <a href="https://twitter.com/ockeghem/status/1289925369890344964?ref_src=twsrc%5Etfw">August 2, 2020</a></blockquote> 

実際、基本情報処理技術者の試験に自動販売機の状態遷移図の試験が複数出題されているようだし、自動販売機の処理はイベントドリブン（硬貨投入、商品ボタン押下、返金ボタン押下…）なのでフローチャートでは書きにくいと思うが、敢えてフローチャートを書いてみようと思った…が、チャートを書くのは面倒なので、C言語風の擬似コードで書いてみた。前述のようにイベントドリブンの処理にはなるのだが、擬似コードではイベント待ちのポーリングをしている風に書いた。

```
在庫 = ...; // 入庫時に設定
残額 = 0;
商品ランプ点灯中 = false;

while (true) {
  if (硬貨投入) {
　　if (残額 + 投入金額 > 上限金額) {
      投入金額返金;  // 入れたお金が戻ってくる
    } else {
      残額 += 投入金額;
      if (残額 >= 商品金額 && 在庫 > 0 && ! 商品ランプ点灯中) {
        商品ランプ点灯;
      }
    }
  }
  if (商品ボタン押下) {
    if (残額 >= 商品金額 && 在庫 > 0) {
      商品出荷;
      残額 -= 商品金額;
      --在庫;
      商品ランプ消灯;     // 残金を即返金する仕様
      if (残額 > 0) {
        返金;
        残額 = 0;
      }
    }
  }
  if (返金ボタン押下) {
    if (残額 > 0) {
      返金;
      残額 = 0;
      if (商品ランプ点灯中) {
        商品ランプ消灯;
      }
    }
  }
}
```

実際のプログラミングでは、個別の処理は上記のように書くしかないとは思うが、せっかく擬似コードを書いたのに、処理の正しさの実感が全然わかない（間違いや抜けがあれば指摘してほしい）。なので、マクロには状態遷移的に考えて、ミクロではフローチャート…ではないにしても手続き的に考えるのがよいだろう。
ちなみに、「自動販売機 フローチャート」で画像検索すると、ヘンテコなフローチャートが大量に見つかるが、それはイベント駆動を意識してないからで、結果としては問題ないかもしれない（例えば、お金が入ってないのに返金ボタンを押すことが考慮されていないが、単に無視すればよいので差し支えない）が、設計内容を検証する上ではそれは良くないと思う。
Tencent Cloudのライブ配信サービスLVBを使って、PCからライブ配信

## Tencent Cloudのご紹介
- Tencent CloudにはIaaS、Paas、SaaSに別れて、プロダクト数は２００以上
- アカウントは下記２種類
  - [中国サイト](https://cloud.tencent.com/)のアカウント：中国法人向け
  - [国際サイト](https://intl.cloud.tencent.com/)のアカウント：グローバル向け


## [LVB](https://intl.cloud.tencent.com/jp/product/LVB?lang=jp&pg=)の概要
Live Video Broadcasting（LVB）はTencentの長年に渡るオーディオとビデオ技術プラットフォーム、およびグロバール・大規模な加速ノードとトップのオーディオとビデオ AI 技術により、開発者にプロフェッショナル、安定なライブブロードキャスト プッシュ、トランスコーディング、配信および再生サービスを提供し、低ディレー、超高画質、大規模な並列処理アクセス量のニーズを全面的に満たします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/da4a13c6-1225-fb04-27ca-de1f88241d43.png)

## PCのOBSからライブ配信
有名なライブ配信ソフト[OBS](https://obsproject.com/download)または[XSplit](https://www.xsplit.com/)を使って、PCから配信することができます。今回はOBSとTencent CloudのLVBを使ってPCから配信の方法を説明します。
<img width="800" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/bb426434-30a6-2d7d-7195-755cac754929.png">

前提条件：LVBのサービスを有効していること 

### 配信のURLを取得
[LVBのコンソール](https://console.cloud.tencent.com/live/)をアクセスして、「Tools」の「Address Generator」をクリックすると、そこで配信のURLを生成できます。StreamNameのところに適当な名前を入力して、「Generate Address」をクリックすると、URLの生成が完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/582eab0f-6cf7-1b9c-edaf-770c22d20d4f.png)

配信URLの生成結果：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/3353256d-1042-71e8-8ae7-3f53b5a99cf5.png)
下記の二項をメモしておきましょう。
- OBS Push Address
- OBS Push Name

### OBSに配信のURLを設定
OBS画面に「設定-配信」をクリックすると、下記の画面が表示されます。
画面の以下のように設定します。

- サービス：カスタム
- サーバー：上記のOBS Push Address
- ストリームキー：上記のOBS Push Name
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/1958331d-9701-3921-2db9-48329262bb28.png)

ここまではPCのOBSからTencent Cloudまでの配信環境が用意できました。

### クラウドのコンソールでOBSから配信内容を確認
OBSの配信内容（ソース）色々の入力を選択できます。例えば、PCの画面の録画、PCのカメラ、ブラウザの入力できます。
今回のはYoutubeのある動画をOBSから配信を行いました。
[LVBのコンソール](https://console.cloud.tencent.com/live/)をアクセスして、「Manage Streaming」のところに、「test」をクリックすと現在の配信中の内容を確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/6183e28d-c422-f8cd-ed23-1144bdb00b23.png)

配信状況：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/9da295ea-e0cd-6319-c13f-7ae4e01890d5.png)


## まとめ
本記事はOBSからTencent Cloudにライブ配信について説明しました。
JavaScript: Promise.raceの基本的な使い方

`Promise.race`は2つ以上の`Promise`のどちらか早い方を戻り値として取得する関数です。

下の例では、100ミリ秒後に完了するPromiseと、200ミリ秒後に完了するPromiseのどちらか早く完了するほうを取得するものです。この例では、前者のほうが早いので、`Promise.race`で得られる値は`Promise<"100ミリ後に完了した処理">`のほうになります。

```javascript
async function test1() {
  // 100ミリ後に完了する処理
  const one = new Promise(resolve =>
    setTimeout(() => resolve('100ミリ後に完了した処理'), 100),
  )

  // 200ミリ秒後に完了する処理
  const two = new Promise(resolve =>
    setTimeout(() => resolve('200ミリ後に完了した処理'), 200),
  )

  const result = await Promise.race([one, two])
  console.log(result)
  //=> "100ミリ後に完了した処理"
}

test1()
```

* 公式ドキュメント→[Promise.race() - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race)
モデファイアーの設定順による影響

#前書き
Blenderをやっていると何とも不思議な現象に出会ってしまうものです。
どういう事かと言うとですね…
下の二つの物体はある共通点があります。なんだと思います?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/3b0b580b-0ed7-070a-b552-ca11bfd65cea.png)
なんと、この二つの物体はどちらも同じオブジェクト、モデファイアーを使っているんです!

なんでこんなにも違うんでしょうね…
ってことで、今回は複数のモデファイアーの付加順番による影響について実験をしながらみていきましょう。

#実験に使う物
今回は一つのオブジェクトと以下のモデファイアーを使用します。

* オブジェクト
    * キューブ（まぁ、何でもいいです）
* モデファイアー
    * リメッシュ
    * ディスプレイス

#実験の下準備

まずはオブジェクトのほうを少し編集しましょう。モデファイアーが反映したことが分かるようにいじれば大丈夫です。

ここではキューブを使っているので細分化して頂点を移動させました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/dc3a2fc0-5125-42ac-9e4b-8ad10fc580a4.png)
次にモデファイアーを追加します。
こんな感じで設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/921aad87-485f-8044-69dc-2ceac06d1a1e.png)

モードや使用テクスチャ、値は自由に設定してください。


これで下準備はおしまいです。
#実験

今回の実験内容は「モデファイアーの順番を入れ替える」です。どういうことかというと下の画像の三角部分をクリックして並んでる順番を変えるということです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/bf9c4acf-1690-65df-c78c-0c886e659736.png)
ちなみにそれぞれのみの時はこうなります。

ディスプレイスのみ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/eaa19725-3075-d59d-a15f-69179a959b98.png)
リメッシュのみ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/2c923788-27e2-3e96-5c79-15921aea3338.png)


それではリメッシュが上にある時とディスプレイスが上にある時についてみてみます。
##1:リメッシュを上にした時
モデファイアーをこの様にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/39bde93e-ec13-25d7-dc5e-a5712b63c054.png)
するとこうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/ebc768a0-bd98-c74e-9e5e-a486944bfff1.png)
ディスプレイスに似ていますね。

##2:ディスプレイスを上にした時
モデファイアーをこの様にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/4b4e7451-1bc4-d06a-4d7f-8df925b35f44.png)
するとこうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/aae9baee-0602-84fe-3724-1cd3af24ab15.png)
リメッシュに似ていますね。

#考察（？）

リメッシュを上にした時とディスプレイスのみの時を比べてみます。
リメッシュを上にしたときのほうが頂点が多く見えますね。これはディスプレイスの処理の前にリメッシュが処理されているからです。（ある程度の精度のリメッシュすると頂点の数が増えます）

次にディスプレイスを上にした時とリメッシュのみの時を比べてみます。
ちょっと分かりにくいですが、ディスプレイスを上にした時のほうが凸凹していますね。これはリメッシュの処理の前にディスプレイスが処理されているからです。（ディスプレイスは表面を変化させます）

#結論
今回の実験からいえることは
「複数のモデファイアーを設定したとき上にあるモデファイアーから順番に処理される」
ということですね。
株価データ取得Tips

# はじめに

今回は株価データの取得方法についてまとめておく。

身近なサイトでは、Yahoo!ファイナンスの時系列データがお手軽そうではあるがYahoo!ファイナンスはスクレイピング、すなわちWebページから株価データを抽出することは禁止されているようなので、<a href="https://pandas-datareader.readthedocs.io/en/latest/"  target="_blank" rel="noopener noreferrer">Pandas DataReader</a>を利用するとよい。

以下の記事を参考にした。
https://ntk-lab.com/import_stock_data/
Pythonで株価データを取得する方法

# Pandas DataReader

<a href="https://pandas-datareader.readthedocs.io/en/latest/remote_data.html" target="_blank" rel="noopener noreferrer">ここ</a>にPandas DataReaderで利用する株価データの入手元と、アクセス方法が載っている。

## IEX

NY市場上場銘柄ならば、<a href="https://pandas-datareader.readthedocs.io/en/latest/remote_data.html#remote-data-iex"  target="_blank" rel="noopener noreferrer">IEX</a>から取ってくるサンプルコードを容易に見つけることができるが、IEXから株価データを取得するには、アカウントを作ってAPIキーを取得する必要がある。
無料のAPIキーを取得可能だが、1日に取得できるデータ量には制限がある。
有料のAPIキーもそんなに高価ではないが、解約方法のページを探しきれなかったのでやめておく。

iex

~~~python
import os
import pandas_datareader as pdr
from datetime import datetime

os.environ['IEX_API_KEY'] = '取得したAPIキーの価'
start_date = datetime(2020,1,1)
end_date = datetime(2020,7,10)

df = pdr.data.DataReader(name='AAPL', data_source="iex", start=start_date, end=end_date)
df.to_csv("AAPL.csv")

~~~

## Stooq

使い勝手は良かったのは、<a htrf="https://pandas-datareader.readthedocs.io/en/latest/remote_data.html#remote-data-stooq" target="_blank" rel="noopener noreferrer">Stooq</a>。API キー取得は不要。
取得例は以下。


~~~python
import pandas_datareader.stooq as web
from datetime import datetime

start_date = datetime(2020,1,1)
end_date = datetime(2020,7,10)

dr = web.StooqDailyReader('^DJI', start=start_date, end=end_date)
df = dr.read()
df.to_csv('DOW30.csv')
~~~

各国インデックスや日本国内銘柄も取得可能。
海外銘柄はティッカーコードで、日本国内銘柄は4桁の証券コードに「.JP」の拡張子を付けたものを指定する。

|取得銘柄|指定コード|
|:--|:--|
|Apple|AAPL|
|DOW30|^DJI|
|NIKKEI225|^NKX|
|極洋|1301.JP|
|NF日経ダブルインバース|1357.JP|
|上場日経2倍|1358.JP|

# まとめ

Pandas DataReaderのstooqは、APIキー取得不要で使い勝手が良い。
日本の上場銘柄が取ってこれるんで、禁断のスクレイピングに手を染める必要がない。
AWS EC2 AmazonLinux2 Node.jsをインストールしてnpmコマンドを使用できる様にする

## 目的

- AWS EC2のAmazonLinux2インスタンスにNode.jsを入れてnpmコマンドを使用できる様にする方法をまとめる


## 前提条件

- 実施環境のリンク先の方法またはそれに準ずる方法で、AmazonLinux2インスタンスが作成され、ssh接続できること。

## 前提情報

- 下記で実行するコマンドはAmazonLinux2インスタンスにsshでログインしてから実行する物とする。
- 下記と同じ方法で構築したインスタンスでnpmコマンドを実行できる様にする。
    - [AWS EC2 をMacで使ってみよう!](https://qiita.com/miriwo/items/a1ab84c098008e43d042)

## 読後感

- インスタンス内でnpmコマンドを実行することができる。

## 概要

1. リポジトリの追加
1. インストール
1. 確認 

## 詳細

1. リポジトリの追加
    1. 下記コマンドを実行してリポジトリを登録する。（ちなみに下記はNode.jsのバージョン12系のRed Hat系LinuxのNodeインストールコマンドである。その他のバージョンがほしければこちらに記載がある。→ [https://github.com/nodesource/distributions#enterprise-linux-based-distributions](https://github.com/nodesource/distributions#enterprise-linux-based-distributions)）

        ```terminal
        $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash -
        ```

1. インストール
    1. 下記コマンドを実行してNode.jsをインストールする。

        ```terminal
        $ sudo yum install --enablerepo=nodesource nodejs
        ```
    1. リポジトリが「nodesource」になっていることを確認して`y`を入力してEnterを押下する。

        ![web_php_—_test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/a57a6c9d-7d1f-f20c-1ece-4679a2f4b97c.png)

1. 確認
    1. 下記を実行してエラーメッセージが出ないことを確認する。

        ```terminal
        $ npm
        ```
どうやらpip3でswitchbotのAPIがダウンロードできるみたいだ

なんの気なしに[pip3 install switchbotpy]を打ち込んだらswitchbotのAPIがインストールできたようだ。
片手団扇でインストールできるのは何より。

https://pypi.org/project/switchbotpy/

作者さんのgithubのアドレスをば。
https://github.com/nicolas-kuechler
https://github.com/RoButton

最新のファームで
https://github.com/RoButton/switchbotpy/issues/

switchbotを駆動させるのにハッスルしちゃった人たちにはこれは羨ましいと思う。
node.jsでsleep処理をasync awaitを使って書く

sleep処理を書くときはsetTimeoutを使うのが一般的だと思いますが、callbackを書きたくないので今風にasync awaitで書きます。

配列にある会社idの情報を1秒ごとに順番にリクエストする処理を書くと以下のようになります。

```JavaScript:index.js
async function sleep(ms) {
  return new Promise(r => setTimeout(r, ms));
}

async function request(id) {
    // 割愛
}

async function exec() {
  const companyIdList = [1, 2, 3, 4, 5];

  for (const id of companyIdList) {
    await sleep(1000);
    await request(id);
  }
}

exec();
```
DC計画問題への変換定理を証明する

初めまして．@miksです．
研究者を目指すにあたり知り合いを増やしたいので，興味分野のメモを残していきたいと思います．

非凸最適化で重要なConcave-Convex Procedure(CCCP)の論文[^1]で，定理1の詳しく証明を紹介するサイトが見当たらなかったのでメモ．

#### Theorem 1

$f:\mathbb{R}^{n}\to\mathbb{R}$が$C^{2}$級かつ有界なヘッセ行列を持つ時，ある凸関数$g:\mathbb{R}^{n}\to\mathbb{R}, h:\mathbb{R}^{n}\to\mathbb{R}$が存在して$f=g-h$と分解できる．

##準備
### ヘッセ行列とは
$x_{0}\in\mathbb{R}^{n}$における$f$のヘッセ行列とは

```math
\nabla^{2}f(x)|_{x=x_{0}}=
\left.
\left(
\begin{array}{cccc}
\frac{\partial^{2}}{\partial x_{1}^{2}}f(x)&\frac{\partial^{2}}{\partial x_{1}\partial x_{2}}f(x)&\cdots&\frac{\partial^{2}}{\partial x_{1}\partial x_{n}}f(x)\\
\frac{\partial^{2}}{\partial x_{2}\partial x_{1}}f(x)&\frac{\partial^{2}}{\partial x_{2}^{2}}f(x)&\cdots&\frac{\partial^{2}}{\partial x_{2}\partial x_{n}}f(x)\\
\vdots&\vdots&\ddots&\vdots\\
\frac{\partial^{2}}{\partial x_{n}\partial x_{1}}f(x)&\frac{\partial^{2}}{\partial x_{n}\partial x_{2}}f(x)&\cdots&\frac{\partial^{2}}{\partial x_{n}\partial x_{n}}f(x)\\
\end{array}
\right)\right|_{x=x_{0}}
```
で与えられる．

### (半)正定値行列とは
$A\in\mathbb{R}^{n\times n}$を対称行列とする．$A$が正定値行列であるとは，任意の$\boldsymbol{u}\in\mathbb{R}^{n}\setminus\\{0\\}$に対して

```math
\boldsymbol{u}^{T}A\boldsymbol{u}>0
```

が成立する時をいう．$A$が正定値行列であることを$A\succ O$と表す．
$A$が半正定値行列であるとは，任意の$\boldsymbol{u}\in\mathbb{R}^{n}$に対して

```math
\boldsymbol{u}^{T}A\boldsymbol{u}\geq 0
```

が成立する時をいう．これを$A\succeq O$と表す．

### 凸関数とヘッセ行列，正定値性の特徴付け

$f$が凸関数であることの必要十分条件は，任意の$x\in\mathbb{R}^n$に対するヘッセ行列が半正定値行列であることである．

## Theorem 1の証明
再掲
#### Theorem 1

$f:\mathbb{R}^{n}\to\mathbb{R}$が$C^{2}$級かつ有界なヘッセ行列を持つ時，ある凸関数$g:\mathbb{R}^{n}\to\mathbb{R}, h:\mathbb{R}^{n}\to\mathbb{R}$が存在して$f=g-h$と分解できる．

#### 証明
$F:\mathbb{R}^{n}\to\mathbb{R}$が正定値なヘッセ行列を持ち，固有値の集合の下界(最も小さい固有値以下の値)として$\epsilon>0$を持つとする．この時，ある$\lambda\in\mathbb{R}^{n}$が存在して，$f(\boldsymbol{x})+\lambda F(\boldsymbol{x})$が任意の$\boldsymbol{x}\in\mathbb{R}^{n}$に対するヘッセ行列に関して半正定値であることを示せば，$g(\boldsymbol{x})=f(\boldsymbol{x})+\lambda F(\boldsymbol{x})$，$h(\boldsymbol{x})=-\lambda F(\boldsymbol{x})$とすれば分解を構成できる．そこで，上記を示す．

$\boldsymbol{x}\in\mathbb{R}^{n}$と$\boldsymbol{u}\in\mathbb{R}^{n}\setminus\\{0\\}$を任意に取る．$f$のヘッセ行列の二次形式の絶対値が$m$以下であるとする．また$E$を対角成分が$\epsilon$である$n$次正方行列とし，$F$のヘッセ行列の対角化を$F(\boldsymbol{x})=V(\boldsymbol{x})\Lambda(\boldsymbol{x})V(\boldsymbol{x})^{T}$とする．この時$\lambda=\frac{m}{(V(x)^{T}\boldsymbol{u})^{T}E(V(x)^{T}\boldsymbol{u})}$とする．すると

```math
\begin{align*}
\boldsymbol{u}^{T}\nabla^{2}f(\boldsymbol{x})\boldsymbol{u}+\lambda\boldsymbol{u}^{T}\nabla^{2}F(\boldsymbol{x})\boldsymbol{u}&\geq - m+\lambda\boldsymbol{u}^{T}\nabla^{2}F(\boldsymbol{x})\boldsymbol{u}\\
&\geq-m+\lambda(V(\boldsymbol{x})^{T}\boldsymbol{u})^{T}E(V(\boldsymbol{x})^{T}\boldsymbol{u})\\
&=0.
\end{align*}
```

$\boldsymbol{u}=0$のときも$f(\boldsymbol{x})+\lambda F(\boldsymbol{x})$のヘッセ行列は非負であるので，半正定値行列である．

### 注意
凸関数どうしの和は再び凸関数になるのだから，Theorem 1のように凸関数を分解できるとしてはいけない．なぜなら，和が$f$となるような凸関数の分解は必ずしも存在するとは限らないからである．この定理の証明は，存在を具体的に示すことが主な関心である．


[^1]: Yuille, A. L. and Rangarajan, A. The concave-convex procedure (CCCP). *In Advances in Neural Information Processing Systems 14*. 2002.
[AWS CloudWatch]グラフの時間をUTC(協定世界時)からJST(日本標準時)に変更する

#デフォルトはUTC

グラフの時間軸がUTCとなっており、日本時刻にするにはプラス9時間脳内変換する必要があり見ずらいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/5ed4a573-5848-b293-07bf-15f2e1343009.png)


#変更方法

CloudWatchでグラフ表示している画面上部にある「カスタム」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/7a5c3de9-00c1-fd01-7d2c-ba6d82dc8650.png)


表示されたメニューから右上「UTC」をクリックし、リストから「現地タイムゾーン」をクリック選択します。
※OKボタンなどの確定する操作は不要

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/09c156b8-6dcf-d414-93e4-088a3a04639f.png)

グラフがローカル表記となり、日本環境の場合はJST(日本標準時)と見やすくなりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/83536e07-3488-7977-65c8-f3793d3625bc.png)
ActiveModelで生成したオブジェクトのdeep copy

## やりたいこと
タイトルのまま。ActiveModel::Modelで生成したオブジェクトをattribute含めて全て別のオブジェクトとして複製したい。

## ActiveSupportのdeep_dupを試してみた
結論を書くとattributeまで複製されなかったので失敗。

```ruby
class Test
  include ActiveModel::Model
  include ActiveModel::Attributes

  attribute :name, :string
  attribute :age, :integer
end

original = Test.new(name: "Abe", age: 65)
clone = original.deep_dup

# 表面のオブジェクトは別物が生成
original.object_id # => 33487180
clone.object_id    # => 33536560

# でも属性は同じものを指している
original.name.object_id # => 33576180
clone.name.object_id    # => 33576180
```

## Marshalしかないのか
オブジェクトの中身を全てダンプで吐き出して、それを再オブジェクト化するというワザ。これなら要素も複製できた。

```ruby
original = Test.new(name: "Abe", age: 65)
clone = Marshal.load(Marshal.dump(original))

# 要素も異なるオブジェクトIDになっている。
original.name.object_id # => 34629860
clone.name.object_id    # => 34628880
```


他に方法があれば誰か教えて下さいm(_ _)m
一番簡単なWindowsによるSpleeter使用環境構築

#はじめに
Spleeterとは？
⇒音楽データを機械学習でパートごとに分離してくれるすごいやつ！！

Windows用Spleeterの環境構築にGitをインストールしたりと不要な手順が含まれている記事が多く公開されているので、簡単な手順をまとめてみました。

#準備
1. 下記サイトよりMiniconda(Python3.xのWindows installers)をダウンロードします。
https://docs.conda.io/en/latest/miniconda.html


2. テキストエディタで「spleeter-cpu.yaml」を作成します。

```spleeter-cpu.yaml

name: spleeter-cpu

channels:
  - conda-forge
  - anaconda

dependencies:
  - python=3.7
  - tensorflow=1.14.0
  - ffmpeg
  - pandas==0.25.1
  - requests
  - pip
  - pip:
    - museval==0.3.0
    - musdb==0.3.1
    - norbert==0.2.1
    - spleeter

```

#インストール
1. 準備でダウンロードしたMinicondaをデフォルトのままインストールします。
2. スタートメニューよりAnaconda Prompt (Miniconda3)を起動します。
3. `conda env create -f [spleeter-cpu.yamlのパス]` を実行します。色々とダウンロードされるので完了するまで待ちます。
4. `conda info --envs` を実行し"spleeter-cpu"が作成されていることを確認します。

#使用方法
1. スタートメニューよりAnaconda Prompt (Miniconda3)を起動します。
2. `conda activate spleeter-cpu` を実行します。
3. `spleeter separate [音楽データのパス] -o [出力先のパス] -p spleeter:[2 or 4 or 5]stems` を実行します。

例: `spleeter separate D:\hoge.wav -o D:\hoge -p spleeter:2stems`

[2 or 4 or 5]の数字は分離したいパート数で使い分けて下さい。
2: ボーカル/伴奏
4: ボーカル/ドラム/ベース/その他
5: ボーカル/ドラム/ベース/ピアノ/その他

入力元のフォルダに機械学習データがダウンロードされるので入力元を統一すれば次回以降時間が短縮できます…
Pythonを脱出する自分なりのステップ

#その１
jupyternote を何とかする

カーネルを作れば拡張出来るらしい
https://dandy-tech.hatenablog.jp/entry/2019/06/20/000119

やはりPythonがPythonである理由は、
アプリケーション自体の作りだす、価値なんだと思う。

#その2
pandasを何とかする

これは絶妙なところ。pandasなきpythonなど、使う意味さえなくなりそうである。
Excel　→　pandasが唯一の入り口に思えてくる。

#その３
AIを何とかする

これは時間の問題のような気がする。
要するに計算の外の話なので、IN-OUTができたらShellでもいいかも


#Python

ここからは前の話・・・

元ネタ
https://towardsdatascience.com/10-algorithms-to-solve-before-your-python-coding-interview-feb74fb9bc27

#文字列の操作
##1. 逆整数
整数が与えられた場合, 桁を逆にした整数を返します.
注意: 整数は正負のどちらでも構いません.

```python
def solution(x):
    string = str(x)
    if string[0] == '-':
        return int('-'+string[:0:-1])
    else:
        return int(string[::-1])    
print(solution(-231))
print(solution(345))

Output:
-132
543
```
まずはスライスの練習。
負の整数を入れることがポイント


##2. 平均語数の長さ
与えられた文について、平均的な単語の長さを返します。
注意: 最初に句読点を削除することを忘れないでください.

```python

sentence1 = "Hi all, my name is Tom...I am originally from Australia."
sentence2 = "I need to work very hard to learn more about algorithms in Python!"

def solution(sentence):
    for p in "!?',;.":
        sentence = sentence.replace(p, '')
    words = sentence.split()
    return round(sum(len(word) for word in words)/len(words),2)
    
print(solution(sentence1))
print(solution(sentence2))

Output:
4.2
4.08
```
一般的な文字列を使った計算アルゴリズムでは
.replace()，.split()といったメソッドがポイントになる。

つづく
AIエンジニアではない観点で、機械学習・深層学習を整理する


# はじめに

私はAIエンジニアではないので、**機械学習とは？深層学習とは？**がパッとわかりやすく答えられないので、わかりやすさを重視して、自分のために整理をしたいと思いました。（いまさらですが）
また、**AIエンジニアやデータサイエンティストってどういうことができたらよいのだろう**、と漫然と思っていました。

# わかりやすい定義

いろいろ見聞きする中で、私は下記の定義がわかりやすかったです。

### 機械学習・Machine Learningとは

> ・機械（コンピュータ）に、大量データを分析させて、パターンや特徴を覚えさせる（学習・トレイニング）
> ・学習したモデルを使って、推定・分類・データ生成などを行う（推論）

### 深層学習・Deep Learningとは

>・人の脳の神経回路をモデルにした、多層のニューラルネットワーク(※)による機械学習の手法のこと

> ※ニューラルネットワーク
> ・学習時に脳の神経回路の仕組みを真似て計算式を定義し、パラメータを最適化したもの
>・神経回路に相当するノードを積み上げる（レイヤー）

単層のニューラルネットワークでは、精度に限界があったため、何度かおきたAIブームが終わることになり、いろいろな技法(隠れ層追加、畳込みなど)で、精度の劇的な向上がなされたため、現在のAIブームにつながっていると理解。

# AI(人工知能)の4レベル
※2021/3月追記
AIのレベルを整理。

> レベル1　単純制御：指示されたことをそのまま行う
> レベル2　ルールベース：外から見ればAIに見えるが、AならばBといったルールを規定する必要がある
> レベル3　機械学習：学習の着眼点は人間が教えるが対応パターンを自動的に学習する
> レベル4　深層学習：学習の着眼点を人間が教えなくても対応パターンを自動的に学習する

# AI(≒機械学習が組み込まれたシステム)の手法
※2021/3月追記
回帰・分類・クラスタリングなどときどき聞く言葉ではあるが、何をしているのか、何をさせようとしているのかなど、しっかりとおさえる必要があるなと思う。

> ①回帰：データセットから傾向を見つけ将来を予測する（線形回帰/決定木回帰/ポワソン回帰）
> ②分類：与えられた問題がどのパターンに該当するかを識別する（ニューラルネットワーク/ディープランニング・・・）
> ③クラスタリング：データセットから傾向を見つけ、いくつかのグループに分類する（k平均法）

# AIエンジニアの位置

AIエンジニア・データサイエンティストってどういうことができたらよいのだろう、疑問に対して、私には、こちらの記事の下図がとてもしっくりきました。
https://www.atmarkit.co.jp/ait/articles/1906/18/news012.html

ITエンジニアとして、少なくともレベル1・2は、できるようになっていないといけないのだと認識しました。

参考：AI・機械学習の開発／使用レベル
![202008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/0ef81f9d-c0c0-6ee4-6b0e-9256da3ceb45.png)

>レベル1
>クラウドのAIサービス／APIを使う（AIカスタマイズ機能も利用できる）
>レベル2
>学習済みのAIモデルを使う（転移学習で別領域に適用も）
>レベル3
>一般的なAIモデルを作る（ネットワークを自分で作る）
>レベル4
>最先端のAIモデルを使う（論文などを読んで作る）
>レベル5
>完全に独自のAIモデルを作る（理論を作って論文を書く）


# まずは、APIを使いこなせるようになろう

すばらしい世の中になったもので、たくさんの便利なAPIが提供されています。
APIを提供する側になるためにも、まずは、APIをしっかりと使いこなしていきたいと思います。


#### 参考①：Qiita - API紹介記事

- WEB開発に役に立つAPI一覧+API毎に関連するQiita記事を分類 ！
  - https://qiita.com/hamaup/items/cd7212aa1d0b1f0e37de

- 個人でも使える！おすすめAPI一覧
  - https://qiita.com/mikan3rd/items/ba4737023f08bb2ca161

#### 参考②：Rakuten Rapid API

- 検索や人気度なども確認できる
  - https://api.rakuten.co.jp/ja/

#### 参考③：これまで自分で使ってみたおすすめのAPI

- Watson API (Watson Visual Recognition (画像認識))
    - 【Line Bot】教えてピクトグラム Tokyo 2020
    -  https://qiita.com/yoshi_yast/items/feeb73bbe2de86cdd932

- Google Cloud Vision API
    - Pythonで画像の手書き数字を認識(OCR / Google Cloud Vision API)
    - https://qiita.com/yoshi_yast/items/bd5e1e91ac9f64157203

#### 参考④：API表
- クラウドの「AI」サービス／APIを比較表＆1行でまとめる（AWS／Azure／GCP／IBM対応）【2020年版】
  - https://www.atmarkit.co.jp/ait/articles/2006/22/news020.html

参考：上記URLより
![202008-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/be1f081b-47c0-558b-9a54-aa2c793941d6.png)

#### 参考⑤：API連携の重要さ
- SaaSとAPI連携がバックオフィスを変える理由
  - https://www.itmedia.co.jp/business/articles/2004/28/news003.html

# まとめ

###まずは自分がどこの部分を学習しているかを知ることが重要

検索すれば学べるコンテンツはたくさんありますが、自分がどこを目指して、どの位置を学習しているのかを知ることはとても重要だと思う今日この頃です。

# 参考URL
https://ai.gam-batte.com/2018/06/07/ai-public26/#AI3
Filydoc

## 参考

* [Filydoc：技術メモを公開するための何か - clock-up-blog](https://blog.clock-up.jp/entry/2014/07/07/filydoc)

* grep で検索するため、日本語での全文検索の問題が解決。


## 起動方法

* Apache が必要
* https://github.com/kobake/filydoc-core
* dataフォルダ内を編集。
* tmp フォルダのパーミッションは 777 にする。

```go
setlocale(LC_CTYPE, "en_US.UTF-8");
```

の箇所は場合によっては`C.UTF-8`にする必要があるかも。
[HTTPヘッダー]AcceptとContent-Typeについて

## Accept

クライアント側がどんなデータを処理できるかを表す。

例

```
curl -H "Accept: application/json" https://XXXX.com
```

## Content-Type

実際にどんな形式のデータを送信したかを表す。

第一義的にはサーバ側がクライアント側へ返すレスポンス内で使われる。

ただ、クライアント側がサーバ側へ`POST`や`PUT`メソッドで何かしらのデータを渡す際にも使える。

例

```
POST /foo HTTP/1.1
Content-Length: 68137
Content-Type: text/html; charset=UTF-8
```

### 値
Content-Typeには色々値が入れられる。アプリ開発などでは以下を使用することが多い。

- `application/json`
    - jsonフォーマットでデータが送受信される(` {“email”:"xxxxx",”id”:"YYYY"}`のような形)

- `application/x-www-form-urlencoded`
    - エンコードされたurlでデータが送受信される(`email=xxxxx&id=YYYYY`のような文字列がエンコードされる)

## 参考

[stack overflow - REST API - Use the “Accept: application/json” HTTP Header](https://stackoverflow.com/questions/43209924/rest-api-use-the-accept-application-json-http-header)
[MDN Web Docs - Content-Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type)
[Content-typeについて少し勉強してみよう：application/jsonとapplication/x-www-form-urlencodedの違い](https://admin-it.xyz/api/content-type/#toc3)
http sample with go.uber.org/dig

```go

package main

import (
	"fmt"
	"net/http"

	"go.uber.org/dig"
)

type Handler struct {
	Greeting string
	Path     string
}

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "%s from %s", h.Greeting, h.Path)
}

func NewHello1Handler() HandlerResult {
	return HandlerResult{
		Handler: Handler{
			Path:     "/hello1",
			Greeting: "welcome",
		},
	}
}

func NewHello2Handler() HandlerResult {
	return HandlerResult{
		Handler: Handler{
			Path:     "/hello2",
			Greeting: "😄",
		},
	}
}

type HandlerResult struct {
	dig.Out

	Handler Handler `group:"server"`
}

type HandlerParams struct {
	dig.In

	Handlers []Handler `group:"server"`
}

func RunServer(params HandlerParams) error {
	mux := http.NewServeMux()
	for _, h := range params.Handlers {
		mux.Handle(h.Path, h)
	}

	server := &http.Server{
		Addr:    ":8080",
		Handler: mux,
	}
	if err := server.ListenAndServe(); err != nil {
		return err
	}

	return nil
}

func main() {
	container := dig.New()

	container.Provide(NewHello1Handler)
	container.Provide(NewHello2Handler)

	container.Invoke(RunServer)
}

```
Microsoft 365 BusinessのメールボックスにWordPressのContact-Formからのメールが届かない

ちょっとハマった問題。

# 前フリ
NPO法人 まちづくりエージェント SIDE BEACH CITY.では現在、以下のような構成でホームページおよびメールサーバを運営しています。

┬──ホームページ(さくらインターネット sbc.yokohama)
│
└──Microsoft 365サーバ(Microsoft 365 Nonprofit sbc.yokohama)

このたび、Microsoft 365のOutlookをメールサーバとして正式に使うことになり、お名前.comのDNS設定をいじってMicrosoft 365のサーバにメールを流すようにしました。

設定は問題なく終わり、Microsoft 365サーバにメールが届くようになったのですが、ホームページに設置しているメールフォーム(WordPressのContact-Form 7)からのメールだけがなぜかさくらインターネット側のメールボックスに溜まってしまい、Microsoft 365の方に来てくれない。おかしいな と思って調べていました。

# 原因

原因としては、ホームページのドメインとMicrosoft 365で運用しているドメインが同じなため、Contact-Form 7側が、送信先ドメインを探す際に、自分のサーバのドメインがsbc.yokohamaな時点で送信先の探索をやめてしまい、DNSを見たりしないため。

このため、さくらインターネットに残っていた古いメールボックスにメールがたまっていたようです。

# 解決策

Microsoft 365では、契約時にこちらで設定できるドメインとは別に、**@[テナント名].onmicrosoft.com**というドメインが割り当てられ、これをメールのエイリアスに設定することができます。

そのため、Microsoft 365のメールアドレスには、@sbc.yokohamaと、.onmicrosoft.comの二つのメールアドレスを割り当て。Contact-Form 7からは.onmicrosoft.comのメールアドレスに宛ててメールを送ることにしました。

このようにすると、ちゃんとすべてのメールがMicrosoft 365のサーバに届くようになります。

ホームページと社内システムで使っているドメインが同じで、それぞれは独立したサーバにある ということは、ほかでもたまにあると思います。

そういうときに参考になればと思い書いてみました。
Python(boto3)でクレデンシャルを切り替える8つの方法

#はじめに
AWSの各種リソースをPythonでコントロールする際に使うboto3ですが、クレデンシャルを切り替える方法はいくつかの種類があり、優先順序が混乱しがちな為復習を兼ねて調べてみました。これでAWS環境の切り替えも楽々です。

#boto３のクレデンシャル検索順序
boto3は以下の順序でクレデンシャルを検索し使用します。

1. boto.client()メソッドのパラメータとして渡されたクレデンシャル
2. セッションオブジェクトを作成する際のパラメータとして渡されたクレデンシャル
3. 環境変数
4. 共有クレデンシャルファイル (~/.aws/credentials)
5. AWS  config ファイル(~/.aws/config)
6. Assume Role provider
7. Boto2  config ファイル (/etc/boto.cfg , ~/.boto)
8. IAMロールが設定されているAmazon EC2インスタンス上のインスタンスメタデータサービス



以下、YOUR_ACCESS_KEY、YOUR_SECRET_KEYは適宜自身の環境の値で読み替えてください。
## 1. boto.client()メソッドのパラメータとして渡されたクレデンシャル

```python:
import boto3

client = boto3.client(
    's3',
    aws_access_key_id=YOUR_ACCESS_KEY,
    aws_secret_access_key=YOUR_SECRET_KEY,
)
```

boto3.clientを呼び出すときに明示的に使用したい環境のクレデンシャル情報を渡す方法です。
実際の値は環境変数経由で取得するなどとし、コード内に生の値を書き込むことは回避する方が良いです。


## 2. Sessionオブジェクトを作成する際のパラメータとして渡されたクレデンシャル

```python:
import boto3

session = boto3.Session(
    aws_access_key_id=YOUR_ACCESS_KEY,
    aws_secret_access_key=YOUR_SECRET_KEY,
)
```

1と同様、boto3.Sessionを作成する際に明示的に使用したい環境のクレデンシャル情報を渡す方法です。

## 3. 環境変数
```bash:
export AWS_ACCESS_KEY_ID=YOUR_AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY=YOUR_AWS_SECRET_ACCESS_KEY
```

Pythonを実行する環境の環境変数にクレデンシャル情報をセットしておくと、boto3が参照してくれます。
クレデンシャルの切り替えが発生しない場合には簡単な方法であり、使用することも多いです。

## 4. 共有クレデンシャルファイル (~/.aws/credentials)

```:~/.aws/credentials
[your_profile_name]
aws_access_key_id = YOUR_ACCESS_KEY
aws_secret_access_key = YOUR_SECRET_KEY
```

```python:
import boto3

session = boto3.Session(profile_name='your_profile_name')
client = session.client('s3')
```
`~/.aws/credencials`にプロファイルごとの`aws_access_key_id`、`aws_secret_access_key`を設定した後、boto3では設定したプロファイル名を指定します。
awscliでおなじみの方法で設定したプロファイル情報を利用できるので視認性に優れており、ローカル開発環境でもよく利用します。

## 5. AWS config ファイル(~/.aws/config)

```:~/.aws/config
[profile YOUR_PROFILE_NAME]
region = YOUR_REGION
output = TOUR_OUTPUT
aws_access_key_id = YOUR_AWS_ACCESS_KEY_ID
aws_secret_access_key = YOUR_SECRET_KEY
```

`aws configure`コマンドでクレデンシャルを設定した場合、`access_key_id`及び`secret_access_key`はcredentialsファイルに記載されます。この内容はconfigファイルに記載することも可能な為、regionやoutput情報に加えて、上記のようにクレデンシャル情報を記載することができます。

## 6. Assume Role provider

```:~/.aws/config
[profile YOUR_TARGET_PROFILE_NAME]
role_arn = YOUR_TARGRT_ROLE_ARN
source_profile = YOUR_PROFILE_NAME
```

対象となるAWSアカウントのアクセスキー、シークレットキーを直接利用せず、IAMロールを通じて操作をする場合は対象のAWS環境へAssumeRoleをリクエストし、返されたクレデンシャルを用いることで操作することができます。
`~/.aws/config`へ利用するロールのARNと元となるプロファイル名を設定することで利用可能です。

## 7. Boto2 設定ファイル (/etc/boto.cfg, ~/.boto)
boto2との下位互換性がある為、`Boto_CONFIG`が設定されていれば`BOTO_CONFIG`が指定するファイルをチェックし、そうでなければ `/etc/boto.cfg`と`~/.boto`をチェックします。

## 8. IAMロールが設定されているAmazon EC2インスタンス上のインスタンスメタデータサービス
<img width="713" alt="スクリーンショット 2020-08-02 15.48.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671034/2adff69d-178f-7ab6-ac41-eb431ab7ee84.png">

Amazon EC2にはIAMロールを割り当てることができる為、EC2上で動作しており、上記のいずれも設定されていない場合はインスタンスのメタデータサービスから資格情報を読み込みます。
この機能を利用するには、EC2インスタンスの作成時に使用するIAMロールを指定しておく必要があります。


# 参考文献

この記事は以下の情報を参考にして執筆しました。

- [Credentials — Boto3 Docs 1.14.33 documentation](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html)
Excelのピボットテーブルで中央値の計算をする（ただしWindows版のみ）

Excelのピボットテーブルで中央値計算をしたかったメモです。

# 概要
ピボットテーブルを強化できるExcelのアドインを利用します。
なかなか日本語記事見当たらなかったので以下の記事を参考にしています。

- [Calculating the median in Excel PivotTables](https://www.masterdataanalysis.com/ms-excel/calculating-median-excel-pivottables/)

結果として今回調べた方法はWindows版のExcelでは可能ですが、Mac版ではまだできなさそうなので注意が必要です。悲しい。
詳しい対応バージョンは以下をどうぞ。

- [Power Pivot が含まれている Office のバージョン](https://support.microsoft.com/ja-jp/office/power-pivot-%E3%81%A8%E3%81%AF-aa64e217-4b6e-410b-8337-20b87e1c2a4b)


手順としては

1. PowerPivotアドインを有効にする
1. 対象範囲をデータモデルとして読み込む
1. 中央値計算のメジャー作成
1. ピボットテーブルで作成したメジャーを選択

# 設定手順
## Power Pivotの導入
Power PivotはMicroSoftから提供されているExcelを強化できる分析ツールの一つです。アドインの形で提供されています。

> Power Pivot は、データ モデルを作成し、関係を確立して計算を作成できるデータ モデリング テクノロジです。 

[Power Pivot - 概要と学習](https://support.microsoft.com/ja-jp/office/power-pivot-%E6%A6%82%E8%A6%81%E3%81%A8%E5%AD%A6%E7%BF%92-f9001958-7901-4caa-ad80-028a6d2432ed)

今回は中央値計算（計算式の拡張）をやりたかっただけですが、テーブルのリレーション表示などDBチックにも色々と使えそうです。

まず、アドインを以下のように有効化します。
[ファイルタブ] → [オプション] → [アドイン] → 「管理：COMアドイン」の設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83530/48a6086e-ccea-d84a-f14b-51b706f88cea.png)


## データモデル読み込み
計算対象のデータを読み込みます。

### 方法１
通常のピボットテーブル作成と同様に範囲を指定して、[挿入タブ] → [ピボットテーブル] を押します。
設定ダイアログで「このデータをデータモデルに追加する」にチェックをつけると、PowerPivotで利用するデータモデルが作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83530/4f6b6a9f-0de6-0fb5-9ecf-11011f1cdd8d.png)

### 方法２
新しく表示されれうようになっている[PowerPivotのタブ]からデータモデルに追加を選ぶと、現在選択されている部分を読み込めます。また、管理を押すとデータモデル一覧やそれに対する各種処理の設定が行えるウィンドウが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83530/56a3e2be-9268-4bc2-019f-c40ac2b988ba.png)


## 中央値計算のメジャー作成
PowerPivotが使用できるなりましたが、ピボットテーブル作成時に中央値がすぐに使えるようになった訳ではないようです。
ピボットテーブルで利用する計算を拡張して、使えるようにします。
[PowerPivotタブ]→[メジャー] を選ぶと計算方法を定義できるウィンドウが出てきます。
ここで中央値を設定します。
この時各種入力項目はピボットテーブルのこの部分に相当するので、わかりやすい命名にしましょう。

以下のようなテーブルがあったとして、金額列の中央値を出したい場合、 `=MEDIAN([金額])` のように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83530/4d39cb0b-6de9-7ea3-c8bc-8db0a0d7f4cf.png)


## 使ってみる
通常の項目と同じように選択し、値の枠に持っていくとこんな感じで表示されます。
他の「平均」や「合計」みたいにどこのピボットテーブルでも汎用的に使えるという形にはならないものの、ひとまずピボットテーブルで中央値を計算するという目標は達成できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83530/80f61007-1aa4-7cef-0907-5c10b775ec5f.png)

# まとめ
- PowerPivot
    - 計算を拡張することで中央値計算もできる
    - ただし使用できるExcelバージョンが限られている(2020/8現在)
    - テーブルモデル・項目ごとに設定しないといけないのはつらいところ
Pythonでリストを読み込んで複数フォルダ作成


同一フォルダにあるfol.txtを読みこんで、
そこに記載されている名前のフォルダを作成する

fol.txt(例)
AAA
BBB
CCC

だと、AAA, BBB, CCCのフォルダが作成される

短いVer

```
import os
f = open('fol.txt')
areas = f.read().split()
f.close()
for area in areas:
    if os.path.exists(area):
        print('フォルダ ' + area + ' は既に存在しています')
    else:
        os.mkdir(area)

```
短いVer2　コメントを参考に修正しました

```
import os
with open('test.txt','r') as f:
  for row in f:
    print(row.strip())
    if os.path.exists(row.strip()):
        print('フォルダ ' + row.strip() + ' は既に存在しています')
    else:
        os.mkdir(row.strip())

```

長いVer
 
```

import glob
import re
import os

f = open(r'fol.txt', 'r')
for line in f:
    
    myPath=os.getcwd()
    print(myPath)
    text=r"{}\{}"
    result=text.format(myPath,line.rstrip('\n'))
    print(result)
    os.mkdir(result)
    
f.close 

```

参考サイト
https://qiita.com/zaburo/items/0ba12417dfb39fcb1555
JS 配列の後方最初に一致したindex番号を返す（開始位置も指定できる）

## lodashのlastIndexOfを作成してみた
~~~javascript
const lastIndexOf = (array, selectNum, startIndex = array.length - 1) => {
  for (let i = startIndex; 0 <= i; i--) {
    if (array[i] === selectNum) {
      return i
    }
  }
  return -1
}

console.log(lastIndexOf([1, 2, 1, 2], 2))

// =>  3

console.log(lastIndexOf([1, 2, 1, 2], 5))
// => -1

console.log(lastIndexOf([1, 2, 1, 2], 2, 2))
//2番目から『2』の値が最初に一致したindexを返す
// => 1
~~~
Androidアプリ開発探求記（その４）

# 概要
今回は git の *.ignore* に関して、探求してみたいと思います。

# やること
Android Studio で作成したデフォルトの *.ignore* ファイルに対して、以下のことをしてみようと思います。

- 現在の実験コード[^2]上にフィルタリング対象が存在する項目に対してコメントを追加
- 現在の実験コード上にフィルタリング対象が存在しない項目を削除

※ 自明と思われるものについては例外的に *.ignore* に含めていこうと思います。[^1]

# 背景
*.ignore* に関してはネット上に様々な情報が存在し、[.ignore.io](https://www.toptal.com/developers/gitignore) のような便利な自動生成ツールも存在します。

しかし、状況によっては必要となるグレーゾーンのファイルまでバッサリ切り捨ててしまっているため、弊害もあります。

例えば、[開発プロジェクトでスペルチェック用辞書を共有する方法](https://qiita.com/beyondseeker/items/7e63e6a22d6ba3f9f2bd)では辞書ファイルは *idea/dictionaries* フォルダ以下に配置されますが、[.gitignore.io [AndroidStudio]](https://www.toptal.com/developers/gitignore/api/androidstudio) ではバッサリ切り捨てられてしまっています。

実際問題としては、Android Studio 上での辞書共有にはいろいろと欠点もあるため、デフォルトでバッサリ切り捨ててしまったほうが安全だと思います。しかし、最初から切り捨ててしまうと、存在自体を気づけないという弊害があり、これは探求記的には許容できません。

ということで、今後 *.ignore* に関しては、全項目を把握していこうと思います。

# Android Project
Android Studio で作成したデフォルトの *.ignore* ファイルは2つあります。

## ◆ Root Project
```
/build
```

## ◆ Sub Project
```
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
```

# .gitignore を削除してみる
*.gitignore* を削除し、*Reimport gradle project*, *Rebuild Project* を行い、差分を確認してみます。

```
$ git status
On branch comment_on_dot_ignore_files
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    .gitignore
        deleted:    app/.gitignore

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .gradle/
        .idea/caches/
        .idea/libraries/
        .idea/modules.xml
        .idea/modules/
        .idea/workspace.xml
        app/build/
        local.properties
```

# 必須の項目だけ復活させる
現状でフィルタが必要、もしくは自明の項目だけを復活させてみます。

```
### Android Studio ###

# IDEAのモジュール定義ファイル。自動生成されるものなので、commit されるべきではない。
*.iml

# IDEローカルのキャッシュ情報だと思われる。commit されるべきではない。
/.idea/caches

# IDE上で利用されるライブラリの情報だと思われる。自動制裁される情報であり、共有の必要もないので、commit されるべきではない。
/.idea/libraries

# IDE上のモジュール構成情報だと思われる。IDEの利用状況により異なる情報であり、共有の必要もないので、commit されるべきではない。
/.idea/modules.xml

# IDEローカルの情報なので commit されるべきではない。
/.idea/workspace.xml

# This file is automatically generated by Android Studio. This file should *NOT* be checked into Version Control Systems, as it contains information specific to your local configuration.
/local.properties

### Gradle ###

# gradle の work 領域。gradle により自動生成されるものなので commit されるべきではない。
.gradle

# gradle の build 成果物用フォルダ。build により自動生成されるものなので commit されるべきではない。
/build

### MAC ###

# MAC OS上の不可視ファイル。commit されるべきではない。
.DS_Store
```

# 削除された項目
```
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
/captures
.externalNativeBuild
.cxx
```

# まとめ
今回は、Android Studio で作成したデフォルトの *.ignore* ファイルに対して、現時点で必須なものだけに対してコメントを付与し、そうでないものは削除してみました。

今後も同様の対応をしていこうと思います。

[^1]: `.DS_Store` など
[^2]: [今回の作業直前の実験コード](https://github.com/beyondseeker/chrono0015/tree/b02b2a90b66f844af46b4705b87eaa0a975c8a6f)
【RaspberryPi】Wi-Fi接続設定

#はじめに
私はIoT開発を主とした部署に所属しています。
RaspberryPiで簡単なIoTシステムの構築し、検証をしています。

使い始めてある程度システムが構築できたので、無線でデータ収集しようとした思ったが、つながらない。。。

調べると起動後に自動でWi-Fiに接続できてない。
あーそういうこと。勝手に記録してくれないのね。

今後設定を忘れないように記事にしておきます。

#Wi-Fi設定
ターミナルで「wpa_supplicant.conf」を修正。

```shell
sudo nano /boot/wpa_supplicant.conf
```

下記を追記する。

```shell
ctrl_interface=DIR=/var/run/wpa_supplicant
GROUP=netdev
update_config=1
country=JP
network={
	ssid="接続したいSSID"
	psk="SSIDのパスワード"
}
```

再起動。はいこれだけ。

※2020/08/06追記
平文でパスワードを記載しとくのはまずいですね。
暗号化して登録しましょう。

wpa_passphraseコマンドでパスワードを暗号化する。
出力された暗号化パスワードをpskに記載する。

```shell
wpa_passphrase "SSID" "パスワード"
```

#IP固定化
ついでにIPの固定化もする。
「dhcpcd.conf」を修正。

```shell
sudo nano /etc/dhcpcd.conf
```

最終行に下記を追加する。IPは適当な値を記載しています。
※wlan0：無線用　eth0：有線用

```shell
interface wlan0 
static ip_address=192.168.1.45/24
static routers=192.168.1.1 
static domain_name_servers=192.168.1.1

interface eth0 
static ip_address=192.168.1.45/24
static routers=192.168.1.1 
static domain_name_servers=192.168.1.1
```

再起動。

#最後に
これだけで色々見返して時間食ったな～
つまらない記事で申し訳ないです。
頑張ろう。
Redmica 1.1.0 (Redmineの次期バージョン4.2.0 先行版)

## 参考

* [今日使える明日のRedmine「RedMica 1.1.0」リリース | Redmine.JP Blog](http://blog.redmine.jp/articles/mica-1_1/redmica-1_1_0-released/)
* https://hub.docker.com/r/redmica/redmica/tags

## docker-compose.yml

```yaml:docker-compose.yml
web:
  image: redmica/redmica:1.1.0-alpine
  restart: always
  volumes:
    - ./sqlite:/usr/src/redmine/sqlite
    - ./files:/usr/src/redmine/files
  ports:
    - 3000:3000
```


## nginxとの組み合わせ

```nginx:nginx/proxy 
server {
        listen 8080;
        location / {
                # uploadファイルサイズの上限を増やす
                client_max_body_size 50M;

                auth_basic "Basic Auth";
                auth_basic_user_file /etc/nginx/htpasswd;

                proxy_pass http://redmine:3000;
                break;
        }
}
```

```nginx:nginx/htpasswd
user1:{PLAIN}aaabbbccc
user2:{PLAIN}bbbcccaaa
```

```yaml:docker-compose.yml
redmine:
  image: redmica/redmica:1.1.0-alpine
  restart: always
  volumes:
    - ./sqlite:/usr/src/redmine/sqlite
    - ./files:/usr/src/redmine/files
  ports:
    - 3000:3000

nginx:
  image: nginx
  restart: always
  volumes:
    - ./nginx/htpasswd:/etc/nginx/htpasswd
    - ./nginx/proxy:/etc/nginx/conf.d/default.conf
  ports:
    - 8080:8080
  links:
    - redmine:redmine
```
Unityチュートリアルでビルドエラー解決方法

■現象
公式チュートリアルプロジェクトをインポートしたが、ビルドエラーが発生した。


■参考
https://forum.unity.com/threads/package-manager-throwing-numerous-errors.608191/

    I've just found the solution which is working perfectly for me, here it is:
    Create a new project, copy the manifest.json file from the "Package" folder(of a new project) and replace the Manifest.json file of your project(in which you're facing errors).

    Or You can simply delete the Package folder from your project and unity will recreate it by itself self and the problem will be solved.

■対応
上記に従って、Packagesフォルダを削除すると自動的に再作成してビルドが通るようになった。
データベースを構成する要素。

Qiitaを使用しプログラミングで学んだことを情報発信していきたいと思います！
アプトプットに対しフィードバックを頂けると幸いです！

データベースを構成する要素として以下の三つがあります

・サービスで扱う概念（エンティティ）
・エンティティの属性
・エンティティ同士の関係（リレーション）

エンティティとは
エンティティとは、サービスの中で管理する必要のある概念のこと。岩いる情報示しています。

例え話
インスタグラムで言えばユーザーや投稿する画像や動画、コメントなどの情報のこと。

エンンティティの属性
属性ってなに？
エンティティが個別に持つ情報である。
例えば投稿に対するエンティティの属性は投稿の本文、いいね数、投稿時間、投稿の写真。

要するにエンティティは抽象的な情報のこと。属性はエンティティを具体に落とし込んだ情報のことである。

リレーション
エンティティとエンティティの間に存在する関係性のこと。
リレーションの例え話
漫画には、その漫画を描いた漫画家がいる。こういった場合は漫画と漫画家の2つのエンティティには関係性がある事になる。
Androidアプリ開発探求記（その３）

# 概要
[前回](https://qiita.com/beyondseeker/items/2b1fba123efbab6c04ae)利用した Android project を起動したら、なにやら *.idea/gradle.xml* が変更されていました。

タイムスタンプを確認したところ、どうやら Android Studio でプロジェクトを開いたタイミングで変更が入ったっぽいです。

```xml
<component name="GradleMigrationSettings" migrationVersion="1" />
```

# 対応
特に問題なさそうなので、普通に commit しました。
[diff: GitHub](https://github.com/beyondseeker/chrono0015/pull/3/commits/b02b2a90b66f844af46b4705b87eaa0a975c8a6f)
AnsibleをDockerコンテナで実行

## 概要
コントロールノード（ホストOS）からAnsibleを実行し、ターゲットノードのDockerコンテナの環境を構築する。

## 背景
Dockerコンテナの環境をAnsibleで構築する際に、筆者はこれまでDockerコンテナ内にAnsibleをインストールして試したことしかなかった。
しかしDockerコンテナにAnsibleをインストールせずとも、ホストOSからAnsibleを実行してDockerコンテナの環境を作れることがわかったため、本記事で共有する。

## 本記事のポイント

* DockerコンテナにAnsibleはインストール不要。（ホストOSにはインストール必要）
* 通常Ansibleを実行するのに、デフォルトではコントロールノードからターゲットノードへsshでログイン可能な状態にする必要があるが、予め接続方法をDocker向けにカスタマイズするためssh設定は不要。また、Ansibleを実行するためにDockerコンテナの特定ポートをホストOSに向けて開ける必要も無し。

## 手順

### (1) 元となるDockerコンテナの準備

* CentOS7のコンテナを使う例
* 暫定で使うので、コンテナを停止したらコンテナが消える``--rm``オプションをつけている
* 対象コンテナを既に立ち上げている場合はこの手順はスキップしてOK
    * 以後に出てくる``centos7``も、各自のコンテナ名に置き換えて試していただく必要あり

```
$ docker run -dit --name centos7 --rm centos:7 /bin/bash
```

### (2) ターゲットノードのホスト情報を記述した設定ファイルの準備

* カレントディレクトリ（作業するディレクトリ）に、Dockerコンテナのホスト情報を記載した設定ファイルを用意

```ini:hosts
[servers]
centos7

[all:vars]
ansible_connection=docker
```

* 要点
    * ``[servers]``セクションにターゲットノードのホスト名（つまりDockerコンテナ名）を記載。
    * 変数を定義するセクション``[all:vars]``に、ターゲットノードがDockerコンテナであることを表す``ansible_connection=docker``を記載
* 余談
    * ``[servers]``セクションに複数のホストを指定することも可能。また、セクションはホストを例えばDB向け、AP向けなどのようにグループ化するために利用するもので、どのような名前にするかは任意。今回の例では、コンテナ``centos7``への接続を確認するだけなので、``[servers]``というセクションの記載がそもそも無くても（``centos7``のみ記載していれば）動作する模様。
    * ``ansible_connection``に関して。ssh無しで自分自身のマシンにAnsibleを適用したい場合は、``ansible_connection=local``にするといいみたい。

### (3) 動作確認

* 以下コマンドで、Dockerコンテナ内でpingできることを確認

```
$ ansible centos7 -i hosts -m ping
centos7 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
```

* ちなみにカレントディレクトリに``ansible.cfg``を用意して、ターゲットホスト（およびそれに付随する設定）を定義したファイル``hosts``を参照する旨を記載していれば、上記コマンドで``-i``オプションは不要。

```cfg:ansible.cfg
[defaults]
inventory=./hosts
```

## 注意点

本記事で扱う内容に限った話ではないが、Ansibleの裏ではpythonが動いているため、対象コンテナ内にpythonが入っていなければ動作しない。
また仮にpythonが入っていても、pythonの実行ファイルパスがAnsibleのデフォルトである``/usr/bin/python``でなければエラーになってしまう。その場合は、先に示したホストの設定ファイル``hosts``の変数セクションに、下記のように``ansible_python_interpreter``を追記してあげればOK。

```ini:hosts
(ホスト名の定義など）

[all:vars]
ansible_connection=docker
# 以下、追記した例
ansible_python_interpreter=/usr/bin/python3
```
【Laravel】ルートプレフィックスを利用して、見栄えの良いルート定義にする

ルートを定義している`routes/web.php`の見栄えをよくするために**ルートプレフィックス**を利用するのはいかかでしょうか？

## ルートにプレフィックス（接頭辞）を指定しよう
グループ内の全ルートのURIに特定の文字列を付け加えたいとき、`prefix`メソッドを利用することで、グループ内の各ルートに対し、指定したURIのプレフィックスを付け加えることができます。

```php:routes/web.php
Route::prefix('admin')->group(function () {
    Route::get('users', function () {
        // Matches The "/admin/users" URL
    });
});
```
上記例では、`Route::prefix`メソッドに`admin`を指定することにより、グループ内の各ルートは、すべてURIに`admin`が付くようになります。

今回の例では、`Route::prefix('admin')`のグループのなかに、`Route::get`のURI`users`が定義されているので、このルートに適応するアドレスは`/admin/users`ということになります。


## ルート名にも、プレフィックスが付けられる
ルート名もプレフィックスを付けることができます。`name`メソッドを使用することで、各ルートへ、指定の文字列をプレフィックスすることができます。

```php:routes/web.php
Route::name('admin.')->group(function () {
    Route::get('users', function () {
        // "admin.users"という名前へ結合したルート…
    })->name('users');
});
```
上記例では、`Rotue::name`メソッドに`admin`が指定されています。グループ内のルートには`name('users')`と定義されたルートがありますが、このルートは`admin.users`という名前へ結合されたルートになっていることに注意しましょう。

また、名前を付けたルートに対してURL生成したい、またはリダイレクトしたい場合は、`route`関数を使用しましょう。指定した名前付きルートへリダイレクトしたい場合は、`return redirect()->route('admin.users');`こんな感じでできちゃいます。


参考文献：https://readouble.com/laravel/7.x/ja/routing.html
初心者が1人で CircleCI で CI/CD できるようになるまで

# はじめに
「 CI/CD ぐらい一人でできるようになりたい！」と思い、実際にやってみた備忘録になります。

# 流れ
1. CI/CD 対象のプロジェクトの作成
2. CI
3. CD
4. CI/CD の結果を Slack に通知する

# "流れ" に対応する記事

以下の記事を投稿しました。

1. [vue-cliでプロジェクト作成してあれこれ試してみた（初心者向け）](https://qiita.com/sugurutakahashi12345/items/ed35018025a5732a46a5)
2. [CircleCI 試してみた](https://qiita.com/sugurutakahashi12345/items/aeca12d9c5a5526c724c)
3. [CircleCI から Firebase Hosting にデプロイするまで](https://qiita.com/sugurutakahashi12345/items/04b78b946322b8b410f7)
4. [CircleCI の Job の結果を Slack に通知する](https://qiita.com/sugurutakahashi12345/items/fd17fdf36b7b34f1fe31)

# 途中で挫折しないためのポイント 3つ

- CI/CD 対象のプロジェクトは作り込まない
- CI と CD の仕組みは分けて作成する
- 興味のあるサービスを選択する
【CSSinJS】 emotionまとめ

# 概要
create-react-app(ts)での実装でcomponentのstyleをemotionを使って実現したのでそれの共有。

## そもそもemotionって何？
JSXファイルの中にスタイルを直接書き込むタイプのCSSinJSライブラリの一つ
最近だとstyled-componentsはよく聞きますよね。。その中で注目度上げてきてるemotionを発見！！
emotionの機能としてとてもCSS prop形式というのがあるんですが、
なんとstyled-componentsと比べてコンポーネントのマウント速度で約4倍、レンダリング速度で約3倍は速いらしい！
使わないわけにいかないと思い使ってみました。

## 決まり事
emotionをreactで使うにあたって決まりごとがある

```
- emotionを使う場合は、`JSX Pragma`が必要
- emotionを使っているコンポーネントではフラグメントを使えない
```
ここだけ守ればemotionは通常に動作するはずです。

二つ目はなんとなくわかると思うので、一つ目を少し詳しく説明すると
JSX Pragmaとは簡単にいうと「僕, emotionで使ってJSX書いてるよ。少し特殊だからEmotion用のコンパイラ通します」
っていうのを明示的に表しています。emotionを使って書いたJSXファイルの冒頭に下記のように記述する感じです！ 

```tsx
/** @jsx jsx */
import { jsx } from '@emotion/core';
```
※ <strong>[注意] 親コンポーネントで JSX Pragma を使 用したら、子のコンポーネントでも JSX Pragma を使わなければなりません</strong>

## 基本的な使い方

適用したいスタイルを定義する。
その変数を適用したいElementにCSS prop形式を使って渡してあげる。
これだけです！！

```tsx
/** @jsx jsx */
import React from 'react';
import { css, jsx } from '@emotion/core';

const heading = css`
  color: #000;
`;

export const Sample: React.FC = () => {
  return <p css={heading}>サンプル</p>
}
```


## 共通スタイル適用

少し使い方を工夫すると以下のように、
共通のスタイルを他のスタイルの変数にextendsみたいなことができます！
直感的でわかりやすいですよね！

```tsx
/** @jsx jsx */
import React from 'react';
import { css, jsx } from '@emotion/core';

const base = css`
 margin: 0;
`;

const heading = css`
  ${base}
  color: #000;
`;

export const Sample: React.FC = () => {
  return <p css={heading}>サンプル</p>
}
```

## その他の情報

メディアクエリだって簡単！

```tsx
/** @jsx jsx */
import React from 'react';
import { css, jsx } from '@emotion/core';

const heading = css`
  font-size: 30px;
  @media (min-width: 420px) {
    font-size: 50px;
  }
`;

export const Sample: React.FC = () => {
  return <p css={heading}>サンプル</p>
}
```

イベントだって簡単！！

```tsx
/** @jsx jsx */
import React from 'react';
import { css, jsx } from '@emotion/core';

const heading = css`
  opacity: 1;
  &:hover {
    opacity: 0.5;
  }
`;

export const Sample: React.FC = () => {
  return <p css={heading}>サンプル</p>
}
```

アニメーションだって簡単！！！

```tsx
/** @jsx jsx */
import React from 'react';
import { css, jsx } from '@emotion/core';

const heading = css`
  animation: fadeIn 1s linear;
  @keyframes fadeIn {
    0% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }
`;

export const Sample: React.FC = () => {
  return <p css={heading}>サンプル</p>
}
```
Magentaチームによる機械学習＆音楽のリモートワークショップ＆ハッカソンイベント”Bit Rate”が開催


Google の機械学習音楽ライブラリーMagenta開発チームと、サンフランシスコのメディアアート機関”Gray Area”による機械学習＆音楽のリモートワークショップ＆ハッカソンイベント”Bit Rate”が８月７日〜９月７日に開催されます。

開催場所はもちろんアメリカサンフランシスコと言う事ですが、今回はコロナ禍の状況下でリモート開催と言う事で日本からも参加できるのではないかと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61803/770b4d29-2bd0-e75b-b723-b18d16924e9f.png)



https://grayarea.org/event/bitrate-ml-music-series/


主にJavaScriptの音楽ライブラリーやMagentaを組み合わせて、機械学習＆音楽の新しいアプリを開発するワークショップとハッカソンの組み合わせでスケジュールは下記の様になっています。



**INTRODUCTION & OPENING – AUGUST 7**
5:30 – 6pm PST: Introductions by Gray Area and Magenta team at Google Research.

**WORKSHOPS & LECTURES – AUGUST 7 – AUGUST 9**
August 7, 6-9pm PST: p5.js Workshop – Instructor: Rachel Rose Waterhouse
August 8, 11am – 2pm PST: Magenta.js Workshop – Instructor: Tero Parviainen
August 9, 12pm – 3pm PST: ml5.js Workshop – Instructor: Stephanie Andrews

**SERIES BEGINS – AUGUST 7**
Teams gather and begin prototyping process.

**PROJECT SUBMISSIONS – AUGUST 31**
Projects created will be submitted on devpost.com.

**CONCLUSION & AWARDS – SEPTEMBER 7**
Finalists selected and announced.



###Bit Rate概要
８月７日にスタート。
７、８、９日はそれぞれワークショップが開催され

**８月７日**
**Audio Visualization with P5.js + Tone.js Workshop**
P5.jsとTone.jsを使用したオーディオビジュアライゼーションワークショップ
https://grayarea.org/workshop/bitrate-series-audio-visualization/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61803/8ac5f829-e4ff-c1da-b743-36d110d34ae5.png)



**８月８日**
**Making Interactive Music Apps with Magenta.js Workshop**
Magneta.js（JavaScript版Magenta）を使用した音楽アプリのワークショップ
https://grayarea.org/workshop/bitrate-series-interactive-music-apps/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61803/7ddf9da3-e6f0-58db-852f-7b00fa06254d.png)





**８月９日**
**Building An Interactive Machine Learning Orchestra Using ml5.js Workshop**
JavaScriptでインタラクティブな機械学習オーケストラの作成ワークショップ
https://grayarea.org/workshop/bitrate-series-machine-learning-orchestra/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61803/3042386e-5a4d-7e7a-203b-648e2cf6739c.png)




その後３１日までハッカソンが開催されます。
通常リアル開催だと週末の３日間だけなどが多く、正直何かの開発をするのは時間的に厳しいのですが、開催場所を確保しなくても良いオンラインの場合、この様な長期のハッカソンも可能という事でしょう。
１ヶ月近くあれば実践的なアプリの開発も十分可能ではないかと思います。

８月３１日に締め切りで提出
９月７日に優勝チームが発表されます。

優勝チームには５００ドルの他、Magetna開発チームへのプレゼンテーション、その他Google Nest Hubなどが贈呈されるとの事です。

日本の方も（英語がある程度できれば）今回は参加できそうなので是非チャレンジしてみてはいかがでしょうか？