OmniAICreator/Qiita-1.07M huggingface dataset:
Herokuでデプロイ時にスクリプトを実行したい

# はじめに
Herokuでデプロイ時にスクリプトを実行したい！
具体的にやりたいことは、特定のディレクトリに権限を付加したい！

# 結論
ルートディレクトリに`.profile`[^1]を作成し、その中にコマンドを書けばよい。

```:.profile
chmod -R 777 /app/web/app/ewww
```

# 経緯
こちらの記事[^2]を参考にHerokuにWordPressを入れて、プラグインの`EWWW Image Optimizer`をインストールしたのですが、権限がないよってエラー[^3]が出て、指定でのディレクトリに権限をつけようといろいろ奮闘したのが始まりでした。。。

## エラー内容
>EWWW Image Optimizer could not create the tool folder: /app/web/app/ewww/. Please adjust permissions or create the folder.

# 作戦1: composer.jsonのscriptsにスクリプト書く → 失敗
[How can I give permissions to specific folders on heroku?](https://stackoverflow.com/questions/36455888/how-can-i-give-permissions-to-specific-folders-on-heroku)

```:composer.json
{
...

  "scripts": {
    "compile": [
      "chmod -R 777 /app/web/app/ewww"
    ]
  }
}
```

logを見る限り、正常に権限は付加されていたが、デプロイ完了後に`heroku run bash`して直接確認すると権限は元通り。。。

```:log
-----> Installing dependencies...
       Composer version 1.10.13 2020-09-09 11:46:34
       > pwd
       /tmp/build_fbd6e5b3_
       > ls -la web/app/
       total 28
       drwx------ 7 u11818 dyno 4096 Sep 21 12:23 .
       drwx------ 3 u11818 dyno 4096 Sep 21 12:23 ..
       drwx------ 2 u11818 dyno 4096 Sep 21 12:23 ewww
       drwx------ 2 u11818 dyno 4096 Sep 21 12:23 mu-plugins
       drwx------ 2 u11818 dyno 4096 Sep 21 12:23 plugins
       drwx------ 4 u11818 dyno 4096 Sep 21 12:23 themes
       drwx------ 2 u11818 dyno 4096 Sep 21 12:23 uploads
       > chmod -R 777 web/app/ewww
       > ls -la web/app/
       total 28
       drwx------ 7 u11818 dyno 4096 Sep 21 12:23 .
       drwx------ 3 u11818 dyno 4096 Sep 21 12:23 ..
       drwxrwxrwx 2 u11818 dyno 4096 Sep 21 12:23 ewww
       drwx------ 2 u11818 dyno 4096 Sep 21 12:23 mu-plugins
       drwx------ 2 u11818 dyno 4096 Sep 21 12:23 plugins
       drwx------ 4 u11818 dyno 4096 Sep 21 12:23 themes
       drwx------ 2 u11818 dyno 4096 Sep 21 12:23 uploads
```

# 作戦2: Procfileにスクリプト書く → 失敗
[herokuでデプロイ時に自動でスクリプトを実行する](https://e-tec-memo.herokuapp.com/article/298/)

```:Procfile
release: chmod -R 777 /app/web/app/ewww
web: vendor/bin/heroku-php-nginx -C config/heroku/nginx.conf web
```

logを見る限り、動いているっぽいが、デプロイ完了後に`heroku run bash`して直接確認すると権限は元通り。。。


```:log
-----> Discovering process types
       Procfile declares types -> release, web
```

# 作戦3: .profileにスクリプト書く → 成功！
https://devcenter.heroku.com/articles/dynos#the-profile-file

```:.procfile
chmod -R 777 /app/web/app/ewww
```

# おわりに
chmodに関してはこれでないとだめかもですが、composerに限らずパッケージ管理系のコマンドとかは作戦1とかでも動くと思います。しっかり調べてないのですが、、、。きっと、デプロイタイミングでdynoにファイル等々コピーされて権限等は戻っちゃうんではないでしょうか :thinking: 


[^1]: [https://devcenter.heroku.com/articles/dynos#the-profile-file]
[^2]: [驚くほど無料で一瞬でWordPressを用いたブログ環境を構築できた話](https://qiita.com/fuwamaki/items/8684003bb47197336645)
[^3]: [EWWW Image Optimizerを有効化するとエラーが出るときの対処法](https://hi3103.net/notes/web/876)
Rails gem Kaminariでページネーション機能を簡単に作る

ページネーション機能を簡単に作るための記述例です。
参考になりましたら幸いです。
また、間違いなどあればご指摘いただけますと幸いです。

なお、環境は
・macOS Catalina
・Ruby on Rails 6.0.3.3
です。

haml使ってます。erbやslim使ってる方は読み換えてください。
Bootstrap 4.4.1をyarnを利用してインストールしています。
jqueryもpopperも依存関係にあるので一緒にインストールしています。
（あくまで一例なので、別の方法でBootstrapを適用している場合はこの限りではありません）

```
% yarn add bootstrap@4.4.1 jquery@3.5.1 popper.js@1.16.1 
```
Bootstrapの適用方法は省きます。

# 以下、記述例です
```ruby:Gemfile
gem 'kaminari', '~> 1.2.0'
```
```terminal:ターミナル
% bundle install
% rails g kaminari:views bootstrap4
```

```ruby:config/kaminari_ja.yml
ja:
  views:
    pagination:
      first:    "&laquo; 最初"
      last:     "最後 &raquo;"
      previous: "&lsaquo; 前"
      next:     "次 &rsaquo;"
      truncate: "&hellip;"
  helpers:
    page_entries_info:
      one_page:
        display_entries:
          zero: ""
          one: "<strong>1-1</strong> / 1件中"
          other: "<strong>1-%{count}</strong> / %{count}件中"
      more_pages:
        display_entries: "<strong>%{first}-%{last}</strong> / %{total}件中"
```
```ruby:ページネーションしたいビューファイル.haml
# 記述追加
= page_entries_info @events
= paginate @events
```

こんな感じになるはずです。
![スクリーンショット 2020-09-22 11.18.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630925/41db2732-1aa5-43e3-0e90-04bce1b4f872.png)
Laravelでapi.phpに送れない

## 何をしているか
https://www.hypertextcandy.com/vue-laravel-tutorial-authentication-part-4/
上記サイトを参考にLaravel × Vue のアプリ開発の勉強をしています

ただ、Laravelの更新により、現在のバージョンではコピペでエラーが出てしまうことがありました。

##躓いた箇所
上記サイトのところで、api.phpにgetを渡したのにも関わらず、web.phpの
```Route::get('/{any?}', fn() => view('index'))->where('any', '.+');```
が参照されてしまいました。

##解決策
app\Providers\RouteServiceProvider.php の箇所で

```
public function boot()
    {
        $this->configureRateLimiting();

        $this->routes(function () {
            Route::middleware('web')
                ->group(base_path('routes/web.php'));

            Route::prefix('api')
                ->middleware('web')
                ->group(base_path('routes/api.php'));
        });
    }
```

となっている箇所を

```
public function boot()
    {
        $this->configureRateLimiting();

        $this->routes(function () {
            Route::prefix('api')
                ->middleware('web')
                ->group(base_path('routes/api.php'));
            Route::middleware('web')
                ->group(base_path('routes/web.php'));
        });
    }
```

に変更しました。
要するにwebとapi の読み込む順番を逆にするということです。

同じところで躓いた人は試してみてください。
Javascriptコードエディター

#JavaScriptコードエディター

**概要** : このチュートリアルでは、JavaScriptのコードエディター及び、Javascriptコードを記載するためのVisual Studio Codeのインストール方法について学習します。

#####ポピュラーなJavaScriptコードエディター
Javascriptコードを記載する基本的なエディターとして、Windows上のNotepadのようなテキストエディターがあります。
しかし、Javascriptコードの記載を簡単かつ早く行うためには、Javascriptコードエディターが必要です。

基本的なエディターに対しJavascriptコードエディターは、構文の強調表示、インデント、オートコンプリート、ブレースマッチング機能など様々な機能を提供しています。
また、いくつかのエディターはJavascriptやその他のコードをデバッグするのに便利な機能を提供しています。

Javascriptコードエディターとしてポピュラーなものに以下のようなものがあります。
* [Visual Studio Code](https://code.visualstudio.com/ "Visual Studio Code")
* [Atom](https://atom.io/ "Atom")
* [Notepad++](https://notepad-plus-plus.org/ "Notepad++")
* [Vim](https://www.vim.org/ "Vim")
* [Gnu Emacs](https://www.gnu.org/software/emacs/ "Gnu Emacs")

これらは全て無料で使用できます。ここではVisual Studio Codeを取り上げます。

#####Visual Studio Code
Visual Studio CodeはMicrosoftによって開発された無料のオープンソースコードエディターです。
Windows,Linux,MacOSを含むプラットフォームで動作します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519500/b1082925-ea52-ab02-f54a-cbf7b222d3bd.png)
Visual Studio Codeは高度にカスタマイズされており、テーマ、キーボードショートカットなどのような環境設定や、様々な拡張機能をインストールして使用できます。
また、インテリセンス、デバッグ、フォーマット、コードナビゲーション、リファクタリングの他多くの優れた言語機能を組み込みでサポートしています。

Visual Studio Codeでサポートされている全ての機能を理解するには以下を参照してください。
[JavaScript in Visual Studio Code](https://code.visualstudio.com/docs/languages/javascript "JavaScript in Visual Studio Code")

#####Visual Studio Codeのダウンロード
Visual Studio Codeは以下のリンクからダウンロードできます。
[Download Visual Studio Code](https://code.visualstudio.com/ "Download Visual Studio Code")

#####Visual Studio Codeのインストール
Visual Studio Codeは数分で簡単にインストールできます。

#####Live Server拡張機能のインストール
Live Server拡張機能は、Javascriptのコードを変更するだけでWebブラウザの更新をすることなくページを更新できる機能を持っています。
便利な機能なので是非使用してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519500/97b9ab76-7dec-bc3a-f39f-89b60835acd3.png)

このチュートリアルでは、Visual Studio Codeのインストール方法について記載しました。
kerasで再現性の担保(2020/09/22現在)

# 導入
kerasで学習の再現をするとき検索して最初に出てくる情報や公式の日本語ドキュメントが古いバージョンのやり方で，現在は方法が変わっているので記録．

バージョン

- Python 3.7.6
- Keras 2.3.1
- tensorflow 2.2.0

# 再現性の担保
## 環境変数の設定
python3.2.3以降はPYTHONHASHSEEDの値を固定することでpythonのハッシュベースの操作の再現性を担保できる．

```
export PYTHONHASHSEED=0
```
また，PYTHONHASHSEEDはコード内ではなくプログラムの実行前に設定する必要がある．

```
$ python -c 'import os;os.environ["PYTHONHASHSEED"]="0";print(hash("keras"))'  
2834998937574676049  
$ python -c 'import os;os.environ["PYTHONHASHSEED"]="0";print(hash("keras"))'  
-1138434705774533911  
$ PYTHONHASHSEED=0 python -c 'print(hash("keras"))'  
4883664951434749476  
$ PYTHONHASHSEED=0 python -c 'print(hash("keras"))'  
4883664951434749476
```

他の方の記事では環境変数を設定しなくても再現できたとあるのでもしかしたら必要ないかもいれない．
https://sanshonoki.hatenablog.com/entry/2019/01/15/230054

## ライブラリのシード値を固定
Kersa公式ドキュメントページから抜粋．このあたりのコードが以前のバージョンと変わっている．

```python
import numpy as np  

import tensorflow as tf  
import random as python_random  

# The below is necessary for starting Numpy generated random numbers  
# in a well-defined initial state.  
np.random.seed(123)  

# The below is necessary for starting core Python generated random numbers  
# in a well-defined state.  
python_random.seed(123)  

# The below set_seed() will make random number generation  
# in the TensorFlow backend have a well-defined initial state.  
# For further details, see:  
# https://www.tensorflow.org/api_docs/python/tf/random/set_seed  
tf.random.set_seed(1234)  

# Rest of code follows ...
```

# 最後に
ちゃんとドキュメントが最新バージョンのものに更新されているか確認する．(戒め)

#参考ページ
[Keras FAQ: How can I obtain reproducible results using Keras during development?](https://keras.io/getting_started/faq/#how-can-i-obtain-reproducible-results-using-keras-during-development)(2020/09/22閲覧)
そろそろ本格的にプログラミング用語を置き換える時期なのかも

先日GitHubから以下の発表がありました。
[GitHub to replace 'master' with 'main' starting next month /
GitHub来月10月からブランチの「master」を「main」に名称を置き換える](https://www.zdnet.com/article/github-to-replace-master-with-main-starting-next-month/)

以下のようになります。
![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253969/ef540f1e-30ce-d0ba-b4c3-1799269be3e6.png)

GitHubでは、来月から`master`ブランチという名称は使わず、`main`ブランチという名称に変更するという発表でした。来月ってもう普通にすぐだけど、、、。

実は元々数ヶ月前に発表はあったんだけど、そこまで日本では話題にならなかった。
[GitHub abandons 'master' term to avoid slavery row](https://www.bbc.com/news/technology-53050955)


#### 2020-09-30: 追記
あくまで上記強制ではないっぽいです。
今まで通りmasterを使いたい人はmasterで、mainを使いたい人はmainを。
あくまでGitHub側からの配慮ですね。変えたい人は変えられるよと。
![Repositories.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253969/f2356c5d-cfca-a392-311b-57f70ce5a331.png)

## なんでこうなった？

大体の人はニュースなどで話題になったり、最近ではテニスの大阪なおみ選手が身につけているマスクで再度日本中でも話題になったので知っている人がほとんどだと思いますが、アメリカで起きた黒人差別などの事件から起きた「black lives matter（通称：BLM運動）」から派生した動きです。

元々、プログラミング用語というかIT業界における用語には黒人差別に近いような言葉だったり、奴隷制度を連想させるような言葉があります。日本人だと特段横文字ってこともあって特に意識する人もそんなに多くはないと思いますが、大体のIT用語は世界共通で使われているので、外国の方では結構その用語を使うこと自体に抵抗があるらしい。

#### 具体例

- master / slave
    - 主人 / 奴隷といった事を意味する（奴隷制度連想）
    - こちらの業界で使う意味としてはサーバーなどの名称によく使います。日本人からするとslave = サブ機みたいな認識くらい
- Whitelist / Blacklist
    - ホワイトリスト / ブラックリスト（黒人/白人など"肌の色"を連想させるような用語）
    - これはIT業界に限らずまあまあ使う。「ブラックリスト = 除外対象/悪質対象」「ホワイトリスト = 非除外対象」的な感じ
    - 「ブラック = 悪い」　「ホワイト = 良い」みたいな連想を促すので、master/slaveより露骨な言葉かも

### これからどう変わっていくの？

既にTwitterやApple, GoogleやMicrosoftでは用語の代替が始まっているみたいです。

![IT用語も「奴隷」廃止の動き　「slave」は「フォロワー」や「レプリカ」に__l_koya_twitter_png__-_ITmedia_NEWS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253969/f281d99d-36ec-2d51-a433-93a5bd52c5b4.png)

まだ言語自体の大体は混在していて
`Master(マスター)/Slave(スレーブ）`の代替語

- **leader/follower**
- **primary/replica**
- **primary/standby**

Pythonはslaveを**「worker」「helper」**に、master processは**「parent process」**
プログラミング言語の中でも処理の名称が変わっていっている。

`Blaklist(ブラックリスト)/Whitelist(ホワイトリスト)`の代替語

- **blocklist/allowlist**
- **blocklist/safelist**
- **blocklist/passlist**
- **denylist/allowlist**
- **stoplist/golist**
- **redlist/greenlist**

とか会社によってまちまちだったりしているっぽい。
会社によって変わってくると職場が変わった時に混乱不可避になる（あと他社との打ち合わせの時とかに不便ちゃ不便

### 日本でもだんだんと差別用語を使わない流れに変わっていくかな

元々、上記で出てきた用語ってIT業界の中でもう既に定着してきている言葉で、会社の中でもめっちゃ普通に使ってしまうし定着してきている人からすると違和感が半端ないと思います。ただ時代はグローバル「日本だけまだ差別用語使って仕事してんの？w　遅れてんねw」とか外国の人に言われたりしたら単純に会社としても恥やん。
**特に外国の方がいる他社との取引がある会社では、上記の用語を気を付けなくてはいけない。**

て事で社内からまずは改革していくのが良いのかも。


#### ポエム
用語がツール毎や言語によって変わるの辛いから統一してほしい（ボソっ
GitHubがmainブランチに変更しているのに、Git自体がmaster使ってたりするとちょっと不便やで...!!
ついでにSourceTreeとかもどうなるんでしょか...!!
Google Earth Engineで植生

#概要

Google Earth Engineで、植生、計算してみた。

#写真

![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/ded3de5e-e923-e862-057e-b3fa90e2de52.jpeg)


#サンプルコード


```
var po = ee.Geometry.Point(140.429900, 37.796862);
Map.centerObject(po, 15);
function maskS2clouds(image) {
	var qa = image.select('QA60');
	var cloudBitMask = 1 << 10;
	var cirrusBitMask = 1 << 11;
	var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(qa.bitwiseAnd(cirrusBitMask).eq(0));
	return image.updateMask(mask).divide(10000);
}
var image = ee.ImageCollection('COPERNICUS/S2').filterDate('2018-01-01', '2018-06-30')
	.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20)).map(maskS2clouds).median();
Map.addLayer(image, {
	min: 0.0,
	max: 0.3,
	bands: ['B4', 'B3', 'B2'],
}, 'RGB');
var ndvi = image.expression('(G - R) / (G + R)', {
	'R': image.select('B4'),
	'G': image.select('B3'),
	'B': image.select('B2')
});
Map.addLayer(ndvi, {
	min: 0.0,
	max: 0.2,
	palette: ['white', 'green']
}, 'ndvi');


```

以上。
Rails 6で認証認可入り掲示板APIを構築する #17 管理者権限の追加

←[Rails 6で認証認可入り掲示板APIを構築する #16 policyの設定](https://qiita.com/rf_p/items/041e86fef26fb38fed5b)

# 管理者権限を用意する

前回までの実装で、投稿の編集や削除は投稿者本人だけできるようになりました。
ですがそこに拡張し、管理者としてログインしている時は誰の投稿でも編集・削除できるようにしてみます。

そのためにはuserモデルにadminカラムを追加しましょう。

```powershell
$ rails g migration AddAdminToUsers admin:boolean
```

```rb:db/migrate/xxxxxxxxxxxxxx_add_admin_to_users.rb
# frozen_string_literal: true

class AddAdminToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :admin, :boolean, default: false, null: false
  end
end
```

さて、今までは機能を実装してからテストを書いていましたが、punditの基本挙動は理解できたと思うので、先にテストから書いてみます。

管理者権限のない別ユーザーでログインしていた際に編集削除できないテストはすでに書かれているので、

* 管理者権限のある際に別ユーザーの投稿を編集できること
* 管理者権限のある際に別ユーザーの投稿を削除できること

を実装してみます。
厳密にはpolicyテストとrequestテスト両方実装すると万全ですが、ここはpolicyだけ実装してみます。

もし良ければここから書いてあるサンプルを見ずに、まずは自力で実装してみて見比べてみると、コードを書く練習になるのでやってみてください。

# post_policy_spec.rbの編集

```diff:spec/policies/post_policy_spec.rb
...
 RSpec.describe PostPolicy, type: :policy do
   let(:user) { create(:user) }
+  let(:admin_user) { create(:user, admin: true) }
   let(:post) { create(:post) }

...
     it "ログインしているが別ユーザーの時に不許可" do
       expect(subject).not_to permit(user, post)
     end
+    it "adminユーザーでログインしている時に許可" do
+      expect(subject).to permit(admin_user, post)
+    end
...
```

```diff:spec/factories/posts.rb
...
     remember_created_at { nil }
     name { "MyString" }
     tokens { nil }
+    admin { false }
   end
...
```

ここまで実装したらrubocopとrspecを動かして確認。
まだpolicyファイルを実装していないのでテストはコケます。

# policyの実装

まずは管理者であることを判定するprivateメソッドをapplication_policy.rbに生やします。

```diff:app/policies/application_policy.rb
...
   private

   def mine?
     @record.user == @user
   end
+
+  def admin?
+    @user.present? && @user.admin?
+  end
+
```

あとはpost_policy.rbのupdate?destroy?の2つの判定を変えるだけですね。

```diff:app/policies/post_policy.rb
   def update?
-    mine?
+    mine? || admin?
   end
 
   def destroy?
-    mine?
+    mine? || admin?
   end
```

なんとこれだけです。

# traitを使ってadminを簡単に作る

これだけだと少し中身の薄い記事なので、factoryBotを触ってadminユーザーをもっと簡単に作れるようにします。

```diff:spec/factories/users.rb
     name { "MyString" }
     tokens { nil }
     admin { false }
+
+    trait :admin do
+      admin { true }
+    end
   end
```

```diff:spec/policies/post_policy_spec.rb
 RSpec.describe PostPolicy, type: :policy do
   let(:user) { create(:user) }
-  let(:admin_user) { create(:user, admin: true) }
+  let(:admin_user) { create(:user, :admin) }
   let(:post) { create(:post) }
```

これでrspecを動かしてみるとどうでしょうか。
ミスなく書けていればテスト通過するはずです。

traitはご覧の通り、factoryBotの`create`等の第2引数に別名として渡すことで使うことができます。
adminフラグを立てるだけなら恩恵も少なく意味もあまりないのですが、例えばadminユーザーの場合に必ずセットで初期値を持っておきたいカラムがあったりすれば、いちいち`create`のたびに複数カラムの初期値セットをしなくて済みます。

ぜひご活用ください。


# 続き

→[Rails 6で認証認可入り掲示板APIを構築する #18･終 user controllerの実装](https://qiita.com/rf_p/items/3ef3bce9ee81b6de440f)
【[連載目次へ](https://qiita.com/rf_p/items/a846553c11571f4177eb#%E7%9B%AE%E6%AC%A1)】
Ruby による2021年の週カレンダー(システム手帳用リフィル)の作成

####目的：
週カレンダーの作成です。
####背景：
システム手帳のリフィルのサイズ(82mmW x 140mmL)が特殊で、使い始めたものの、入手困難であったため、いっそ手作りしてしまおうと考えたのは過去のことです。その際、リフィル用紙を特注で作ったことがありまして、その時の白紙が余っているので、来年は、久しぶりに手作りしようと考えたこと。
年に一度のことですので、手作りでも良いのですが、せっかくのプログラミング環境があるので、毎年、自動でカレンダーが出力できるような仕組みを作成してみようじゃあないか。という理由で、プログラミングしました。
####印刷：
ワープロソフトの「差し込み印刷」の機能を用います。従って、差し込み印刷用のカレンダーデータを作れば良い。「差し込み印刷」するテンプレートは、下図のような、見開きで1週間表示となるテンプレートとしました。能率手帳のように片側に1週間を詰め込むというテンプレートでも同様です。
![L_andR_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561584/e6cbcb94-e887-f253-d648-7aa3cfd9da92.png)
データ：1週間が1レコードになりますので、下図のようなカレンダーデータベースができれば、差し込み印刷に使用できます。この表を、ruby で作ってみました。
![weekly.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561584/449faac2-57d3-3a78-5e88-4a2028f0a95c.png)

ruby のコードは、下記になります。

```.weekly_calendar.rb

# weekly

require 'date'
day = Date.new(2020,12,28)  # 月曜日始まりの12月最終月日
last = Date.new(day.year+1, day.month, day.mday)
weekdays = {0 => '日', 1 => '月', 2 => '火', 3 => '水', 4 => '木', 5 => '金', 6 => '土'}
 while day < last do
  records=Array.new
  records.push(day.strftime("%Y%W,%Y,%W"))
  dday = day
    while dday < day+7 do 
     wday = weekdays[dday.wday]
     records.push(dday.strftime("%b,%-m,%d,%w,#{wday},%a,"))
     dday = dday+1
    end
  print records.join(',')
  print  "\n"
  day = day+7
 end
```

ヘッダーのファイルは下記コードで出力し、上の出力の上に貼り付けました。csvを 出力して、libreoffice calc に読み込ませれば、「差し込み印刷」のデータとなります。 

```.header.rb
# weekly header

printf "%s,%s,%s,","yrwk","yr","wkwk"
printf "%s,%s,%s,%s,%s,%s,%s,","mte1","mtn1","dyn1","wkn1","wkj1","wke1","s1"
printf "%s,%s,%s,%s,%s,%s,%s,","mte2","mtn2","dyn2","wkn2","wkj2","wke2","s2"
printf "%s,%s,%s,%s,%s,%s,%s,","mte3","mtn3","dyn3","wkn3","wkj3","wke3","s3"
printf "%s,%s,%s,%s,%s,%s,%s,","mte4","mtn4","dyn4","wkn4","wkj4","wke4","s4"
printf "%s,%s,%s,%s,%s,%s,%s,","mte5","mtn5","dyn5","wkn5","wkj5","wke5","s5"
printf "%s,%s,%s,%s,%s,%s,%s,","mte6","mtn6","dyn6","wkn6","wkj6","wke6","s6"
printf "%s,%s,%s,%s,%s,%s,%s\n","mte7","mtn7","dyn7","wkn7","wkj7","wke7","s7"

```
祝日情報は、手入力で修正になります。データを揃えたら自動的に差し込めるように改良したいですが、年に一回の作業ですので予定は未定です。
Vue.jsでwasm-bindgen(Rust+WebAssembly)の入出力を扱う（CSV編）

前に「[Vue.jsでwasm-bindgen(Rust+WebAssembly)の入出力を扱う](https://qiita.com/usop4/items/0e029cd1ff2b8302cda2)」という記事を書いたが、CSVで読み込めた方が色々と楽だ。

作成中のプログラムからCSVに関するところだけ抜き取ったので動作保証はできないが、雰囲気だけ感じていただければと思う。

環境構築は、こちらを参考に。

https://qiita.com/usop4/items/0e029cd1ff2b8302cda2

変更はConfit.tomlにcsvを追加するぐらいかな。

https://docs.rs/csv/1.1.3/csv/

CSVは、こんな感じの形式。

```csv:monster.csv
name,cost
ピカチュウ,10
イーブイ,9
```

前回と同じようにVue.jsでボタンを押すと発動するようにしておく。今回は手抜きでRust側からconsole.log()を呼ぶためにlog()という関数を定義しておく。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>wasm_csv_test</title>
  </head>
  <body>
    <div id="app">
      <button v-on:click="csvtest">test</button>
    </div>
    <script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="index.js" type="module"></script>
    <script>
      const log = (val) => {console.log(val);}
    </script>
  </body>
</html>
```

index.jsでは`mounted:`の中でCSVファイルを読み込んでおき、ボタンを押したらRustで定義した`csv_test()`にCSVの中身を渡す。

```js:index.js
import * as mod from "./wasm.js";
(async () => {
    await mod.default();
    var app = new Vue({
      el: '#app',
      data: {
        csv: null
      },
      mounted: function(){
        axios.get("./monster.csv").then(
          response => ( this.csv = response.data )
        );
      },
      methods:{
        csvtest: function(event){
          mod.csv_test(this.csv);
        }
      }
    })
})();
```

次にRust側。Monster(単体）とMonsters（複数）のstructを作っておく。

```rust:monster.rs
#[derive(Clone)]
pub struct Monster {
    pub id: usize,
    pub name: String,
    pub cost: usize,
}

#[derive(Clone)]
pub struct Monsters {
    pub monsters: Vec<Monster>
}

impl Monsters {
    pub fn new() -> Self {
        Monsters {
            monsters: Vec::new()
        }
    }
    pub fn add_monster(&mut self, m: Monster){
        self.monsters.push(m);
    }
}
```

lib.rsでは`csv::ReaderBuilder::new().delimiter(b',').from_reader(data.as_bytes())`でCSVファイルを読み込み、Monsterに格納しながら`log()`経由でブラウザのconsole.log()に出力する。

```rust:lib.rs
pub mod monster;

use wasm_bindgen::prelude::*;
use crate::monster::*;

#[wasm_bindgen]
pub fn csv_test(data: &str) {

    let mut m = Monsters::new();
    let mut r = csv::ReaderBuilder::new().delimiter(b',').from_reader(data.as_bytes());
    let mut id :usize = 0;

    for record in r.records(){
        let record = record.unwrap();
        m.add_monster(
            Monster {
                id: id,
                name: record[0].to_string(),
                cost: record[1].parse().unwrap(),
            }    
        );
        id = id + 1;
        log(&format!("{}",&record[0]));
    }
}

#[wasm_bindgen]
extern {
    pub fn log(s: &str);
}
```

今回はidの値をCSVと外で生成しているが、もしCSVの形式とstructが完全一致であればSerdeのdeserializeで一気に格納することもできる。

この仕組みを使って、ドラクエウォークのモンスターの最適な組み合わせを計算するサイトを作ってみたので、参考にしていただきたい。

https://github.com/usop4/dqw-wasm/
【React Native】 Xcode12でビルドするとiOS14で画像が表示されない問題に対処する

## はじめに

Xcode 12 でReact Native のプロジェクトをビルドしたところ、iOS 14 の端末 (実機・シミュレータ) でアプリ内の画像が表示されなかったので対処したメモです。

今回はReact Native のIssue で取り上げられているパッチを当てました。

### 追記
※React Native の新しいバージョンではXcode 12 への対応が行われているので、状況が許す限りReact Native のアップグレードを行うのがよいでしょう。
[Release v0.63.3 · facebook/react-native](https://github.com/facebook/react-native/releases/tag/v0.63.3)

## 検証環境

- React Native: v0.61.5
- Xcode: v12.0 (12A7209)

## 問題

Xcode v12.0 でアプリをビルドすると、iOS 14 の端末で `Image` コンポーネントの画像が表示されない。

### メモ

- Xcode 11, iOS 13: 画像が表示される
- Xcode 11, iOS 14: 画像が表示される (App Store からインストールしたアプリで確認)
- Xcode 12, iOS 13: 画像が表示される
- Xcode 12, iOS 14: 画像が表示されない 


## 対処方法

`patch-package` を利用します。

```
$ npm i -g patch-package
```

プロジェクトルートで `patches` ディレクトリを作成し、 `react-native+0.61.5.patch` を作成します。
`react-native+0.xx.x.patch`  のバージョン番号は、利用しているReact Native のバージョンと同じにします。

```
$ mkdir patches
$ touch patches/react-native+0.61.5.patch
```

パッチの内容を記述します。
Issue ではRN v0.63.0 の例が投稿されていましたが、古いバージョンでも上手くいくという投稿がありました。 今回検証したv0.61.5 でも同じ記述内容で大丈夫でした。

```react-native+0.61.5.patch
diff --git a/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m b/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
index 21f1a06..2444713 100644
--- a/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
+++ b/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
@@ -272,6 +272,9 @@ - (void)displayDidRefresh:(CADisplayLink *)displayLink
 
 - (void)displayLayer:(CALayer *)layer
 {
+  if (!_currentFrame) {
+    _currentFrame = self.image;
+  }
   if (_currentFrame) {
     layer.contentsScale = self.animatedImageScale;
     layer.contents = (__bridge id)_currentFrame.CGImage;
diff --git a/node_modules/react-native/scripts/.packager.env b/node_modules/react-native/scripts/.packager.env
new file mode 100644
index 0000000..361f5fb
--- /dev/null
+++ b/node_modules/react-native/scripts/.packager.env
@@ -0,0 +1 @@
+export RCT_METRO_PORT=8081
```

パッチを適用します。


```
$ patch-package
```

もう一度アプリをビルドして端末にインストールすると、 `Image` コンポーネントの画像が正しく表示されました。


## 参考

- [Image cannot show image in iOS 14 · Issue #29279 · facebook/react-native](https://github.com/facebook/react-native/issues/29279)
- [Image component does not load image from specific URI on iOS · Issue #29215 · facebook/react-native](https://github.com/facebook/react-native/issues/29215)
剰余とべき乗（冪乗）の演算子

【概要】
----------------------------------------
<b>1.結論</b>

<b>2.どのように使用するか</b>

<b>3.ここから学んだこと</b>



1.結論
----------------------------------------
<b>剰余</b>:%
<b>べき乗</b>:**
を使う！

<br>
2.どのように使用するか
----------------------------------------
今回は2桁の整数(桁数制限するプログラムはしていません。）入力「の10の位と1の位を足した合計を求めています。

```ruby:

def addition(a, b)
  a + b
end

def calculation(num)
 #10の位
 no1 = (num / 10) % 10
 #1の位
 no2 = (num / 1) % 10
  return no1,no2
end

puts　"2桁の整数を入力"
num = gets.to_i
a, b = calculation(num)
add_sum = addition(a, b)
puts "10の位と1の位の合計は#{add_sum}"
```
10の位を出すために10で割った数値をさらに10で割った余りを出しています
1の位も同様に1で割った数値をさらに10で割った余りを出しています。その際に"%"を使ってあまりを出しています。

```ruby:(例)28の場合
(num / 10)・・・・28 / 10 = 2.8
2.8 % 10 ・・・・0余り2　の"2"を返す。

(num / 1)・・・・28 / 1 = 28
28 % 10・・・・2余り8　の"8"を返す。
```

<br>
3.ここから学んだこと（エラーの時に使用）
----------------------------------------
算数要素が混ざったプログラムは、プログラムの知識はもちろんのこと、工夫して計算する発想が求められることを学びました。工夫した計算にプログラムの知識も必要ですし、「このメソッドは一体どこで使うんだろう？」と思っているとピンポイントで使うこともあるので非常に大事です。
<br>
よく使うものだけ！PrestoのURL関数をまとめてみた！

#この記事の内容
AWS-AthenaはPresto関数が利用でき、URL系の関数を利用することができます。
私もよく使用するのですが、よく間違って使用してしまうこともあるので、改めてまとめてみました。


#クエリ例
[Prestoのドキュメント](https://prestodb.io/docs/current/functions/url.html)の中からよく使用するもを抜粋しました。

```sql
url_extract_protocol(url) --URLのプロトコル部分
url_extract_host(url) --URLのホスト部分
url_extract_path(url) --URLのパス部分
url_extract_query(url) --URLのクエリ部分
url_extract_parameter(url, 'name') --URLのクエリ部分内の特定変数
```

非常にシンプルで便利ですね。
理解を深めてもらうために、このあとは実例もご紹介していきます。


#やってみた
https://qiita.com/otojima/items/67ef8e27320c826f5fde?utm_source=google&utm_medium=cpc
を対象のURL例として、クエリを実行してみます。

```sql
SELECT
  url_extract_protocol(url) AS protocol
  , url_extract_host(url) AS host
  , url_extract_path(url) AS path
  , url_extract_query(url) AS query
  , url_extract_parameter(url, 'utm_source') AS utm_source
  , url_extract_parameter(url, 'utm_medium') AS utm_medium
FROM (
  SELECT
    'https://qiita.com/otojima/items/67ef8e27320c826f5fde?utm_source=google&utm_medium=cpc' AS url
)
```

**結果**

|protocol|host|path|query|utm_source|utm_medium|
|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|
|https|qiita.com|/otojima/items/67ef8e27320c826f5fde|utm_source=google&utm_medium=cpc|google|cpc|



#最後に
この関数を利用すれば、URLから特定の値を取得したい際に、正規表現などを利用して置換する必要がなくなります。非常に便利なので、参考になれば幸いです！
【Flutter】テキストフィールドの初期値に動的オブジェクトを設定する

flutterのTextFormFieldにはinitial valueというプロパティが用意されています。

```dart
Widget build(BuildContext context) {
    return TextFormField(
       intitialValue: "初期値",
      );
 }
```
しかし、動的オブジェクトにはなぜか対応していないので、その場合は以下のような記述に擦る必要があります。

```dart
Widget build(BuildContext context) {
    return TextFormField(
       controller: TextEditingController(text: initialValue),
      );
 }
```
【初心者向け】データベースのテーブル設計で僕が意識している6つのこと


はじめまして、himakuroです。

2017年ぐらいからQiitaに記事を投下しようと考えていたのですが、なかなか筆が乗らずようやく初投稿です:relaxed:

軽く自己紹介をしておくと、普段は社内SEとしてPHP、Ruby、Golangを書いたり、
趣味の個人ブログ方ではプログラミング初心者に向けた記事や雑記的なものを書いたりしています。


今回は記念すべき1つ目の記事と言う事で
僕が普段テーブル設計（主に命名）で気をつけている6つの事を書きました。

僕の好みも含まれていますが、初心者の方がテーブルやカラム名を決める際の参考になればなと思います。


# テーブル名は必ず複数形にする
テーブルは一つしかないから単数形を使うべき！
Modelも単数形で定義するじゃん！

みたいな反論が聞こえてきそうですが、僕は複数形で定義する派です。

また複数形にする場合に、テーブル名の途中の部分を複数形にしている物をたまに見かけますが、僕は末尾を複数形で統一するのが好きです。

x `user_bank`
x `users_bank`
o `user_banks`

Railsで開発をしている方は、僕と同じ様に末尾が複数形の方が好きという人が多い（はず？）

# カラム名のsuffixとして_idを無闇に使わない
suffix(サフィックス)とは `user_id` や `post_id` で言う `_id` の部分を指しています。
要は末尾に付ける物ですね。

そしてこの `_id` は、他テーブルの主キーを指すのに利用して行きたいので　
categoriesテーブルが存在しないのに、 `category_id` をpostsテーブルに追加するなんて事はしません。

また命名規則としては `テーブル名（単数形）_id` で統一するのがおすすめです。

x `categories_id`
x `id_category`
o `category_id`

# 同じものを指すカラムは型を統一する
**※ コメントでご指摘を頂いたため2020-09-24に内容を更新しました**

1つ前の内容に少し関連しているのですが
他テーブルのauto incrementなid列と関連付けるための
`テーブル名（単数形）_id` カラムを定義する際には型はunsignedのbigintで統一しています。

理由としてはRailsやLaravelなどでauto incrementのid列を定義すると, `id` はunsigned bigintになるからです。

本来ならカラムの型は**どのようなデータが入るかを意識した上で選定するべき**ですが
フレームワークを使っていると自動で型が確定するものがあり、今回の内容がそれに該当します。

自動で型が確定するカラムは実際にどのような型になっているかを確認するのを疎かにしがちで、
今まで携わったLaravelやRailsのプロジェクトでも、 auto incrementな他テーブルのidを参照する `xxx_id` をbigintではなくintで定義しているのを多数見てきました。　

`xxx_id` に限らず同じ意味を持つカラムは同じ型で定義するように意識していきましょう。

# 履歴テーブルはhistory、ログテーブルはlog
履歴テーブルとログテーブルって何が違うの？

と聞かれたら僕は

履歴テーブルは画面に表示して **ユーザー（利用者）に見せるもの**
ログテーブルは **エンジニア（開発者）などが調査に使用するもの**

と答えます。

また命名に関しては、例えばゲーム開発などでユーザーがゲーム画面で閲覧する事が出来るプレゼント履歴用のテーブルを作る場合は `user_present_histories` と名付けます。

ユーザーからアイテム消えたんだけど？みたいなお問い合わせが来た場合に、エンジニアが調査が出来るようにユーザーのアイテム利用ログを残しておく場合は `user_item_logs` と名付けます。

人によっては `history` や `log` をprefix(プレフィックス)として先頭に持って来る方もいると思いますが、この辺りは好みかなと思います。

o `user_item_logs`
o `log_user_items`


# booleanのカラムはひと目で分かるようにする
型がbooleanのカラムはひと目でわかるように
`is_` `can_` `has_` の様なprefixを付けるようにしています。

例: `is_active`, `has_owner`


こうすることで、これらのカラム名を見ただけで
型がbooleanであることが推測でき、更にtrueやfalseなどの値が入っていた時に
何を意味するのかが明確になります。

ちなみに型がbooleanで `check_xxx` の様なカラムをたまに見かけますが
これでは `true` の場合にはチェックが必要なのか、それともチェックが終わっているのかが明確ではないので、booleanのカラム名として `check` はおすすめしません。

# 日付を保持するカラムの命名方法

日付を保持するカラムを命名する際に `finish_at` にするか `finished_at` にするかで迷ったことはありませんか？

これを迷わなくするためには **カラムで保持するデータが未来を指すのか、過去のものを指すのか** を考慮すると良いです。

## 過去形を使わない例
例えばゲーム開発でイベント情報を持つテーブルがあり、そのテーブルにはイベント開始時刻と、終了時刻を持つカラムがあるとします。

イベントの開催情報は事前告知するのが一般的であり、イベント開始時刻と終了時刻には**未来の時間**を保持することになります。

よって、カラム名も過去形にはせずに `start_at` や `finish_at` の様に命名をしていきます。

## 過去形を使う例
続いて過去形で命名をする場合を見ていきます。

`user_quests` と言うユーザーのクエスト情報を管理するテーブルがあり、そこにはユーザーがクエストを開始した時刻と終了した時刻を保持するカラムがあるとします。

これらのカラムにデータが入るのはユーザーがクエストを**開始した時、終了した時**なので、データとしては過去の時間を指していることになります。

よってカラム名は　`started_at` `finished_at` のように過去形で命名をします。


レコードの作成時間や更新時間を保持するカラムとして `created_at` や `updated_at` などがあると思いますが、これらのカラムのデータも**作成された時間、更新された時間**を保持するので過去形ですね。
# テーブルの設計って大変
一般的にテーブル設計って聞くと、正規化とかパフォーマンスを意識したインデックスの貼り方とか難しい事ばかりを意識しがちですが、それ以前にテーブル名やカラム名を意識するのも大切だよというのを伝えたかったのでこの記事を書きました。

これが正解と言うわけではありませんが、テーブル名やカラム名はとても重要なので
ネーミングセンスが無いから適当につけよ…とは思わずに、しっかりと考えて命名をするようにしましょう。

初投稿 完
【webGL】ブラウザだとカクついて動かなかったお話【chrome】

# この記事でできること
- unityroomで作品を公開した際、もしカクついて全く動かないなぁ、というときに、chromeの設定で解決できるかもしれない。
- キーワード…「ハードウェア アクセラレーション」

---

## 経緯と問題

[FieldWalking](https://unityroom.com/games/fieldwalking)をunity1weekGAMEJAMで公開後、評価期間が終了したのでアップデートを繰り返していました。

その途中、演出としてボリュームを上げたところ、ブラウザ上ではかくついて確認できなくなりました。

![スクリーンショット 2020-09-22 9.02.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/caf01001-327d-9cfd-fa92-02a1c7a49923.png)

あれこれと
Unityの描画クオリティであったり、
カメラのカリング設定もしましたが、
ブラウザ上では動作確認が難しい状態が続きました。

chromeの設定を見てみると、
「ハードウェア アクセラレーションが使用可能な場合は使用する」の項があったので
google先生に確認したところ、推奨としてはオンのようでした。(調査時点ではオフでした)
![スクリーンショット 2020-09-22 9.10.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/d02fca0c-97bf-8b60-7463-4c9983901665.png)

---

## 結果
chromeの「ハードウェア アクセラレーションが使用可能な場合は使用する」をオンをしたら、
ブラウザ上でも確認することができました。

---

## 宣伝
unityroomの1weekGAMEJAMで公開した2作品は、評価期間終了後もアップデートしています。
ぜひプレイしていってください。

- FieldWalking (https://unityroom.com/games/fieldwalking)

![FW11ss01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/3a1f7992-6470-1279-7c62-0ea20a675574.png)


- AddBalance (https://unityroom.com/games/addbalance)

![SS_AddBalance101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/ee59c635-3b0a-2acf-f7da-de23a7d3a273.png)


また、AddBalanceについては、cluster版も試作としてリリースしました。
こちらもみなさまアバターで遊びに来てくださいませ!!

- AddBalance for cluster (https://cluster.mu/w/ef49e840-f2a4-4eca-817d-9ef4b54060a1)

![AddBalanceForCluster2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/a36db9e2-cee3-8edf-e098-8ad3ac58a725.png)

![AddBalanceForCLusterAnim.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/f089e681-96bf-9bb9-2b93-f18e12c4442e.gif)
HTMLチュートリアル

#HTMLの紹介

####HTMLとは？
* HTMLはハイパーテキストマークアップ言語
* HTMLはWebページを作成するための標準的なマークアップ言語
* HTMLはWebページの構成を記載
* HTMLは一連の要素からなる
* HTMLはコンテンツをどのように表示するかをWebブラウザに指示
* HTMLは見出し・段落・リンクなどのような一連の要素を含む

####シンプルなHTMLドキュメント
#####Example

```HTML
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>

<h1>My First Heading</h1>
<p>My first paragraph.</p>

</body>
</html>
```
#####サンプル文の説明
* _<!DOCTYPE html>_ : このドキュメントがHTML5で記載されることを宣言
* _\<html\>_ : HTMLページのルート要素
* _\<head_> : HTMLのメタ情報を含む要素
* _\<title_> : HTMLのタイトル（ブラウザのタイトルバーあるいはタブに表示）
* _\<body\>_ : ドキュメントのボディを定義
* _\<h1\>_ : 最も大きな見出しの要素
* _\<p\>_ : 段落を表す要素

####HTML要素とは？

HTML要素は、開始ダグ及びいくつかのコンテンツ、終了タグで定義される。
　\<tagname\>Content goes here...\</tagname\>
HTML要素はすべて開始タグで始まり終了タグで終わる。
　\<h1>My First Heading\</h1\> 
　\<p\>My first paragraph.\</p\>

| 開始タグ | 要素の内容 | 終了タグ |
|:-:|:-:|:-:|
|\<h1\>   |最初の見出し   |\</h1\>   |
|\<p\>   |最初の段落   |\</p\>   |
|\<br\>   |なし   |なし   |

> いくつかのHTML要素は\<br\>要素のようにコンテンツを持たないものがある。
> これらの要素は空要素と呼ばれ、終了タグを記載しない

####Webブラウザ
Webブラウザ（chorome,edge,firefox,safari etc）は、HTMLドキュメントを読み込み画面に正確に表示する目的で使用されている。WebブラウザはHTMLタグを表示しないが、どのようにドキュメントを表示するかを決めるために使用する。

####HTMLページの構造

HTMLページの構造は以下の図のようになっている。
bodyセクションのみブラウザ上に表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519500/2ce17926-bd43-c1da-d95d-649e8bc0ee44.png)
【webGL】Uncaught RangeError: Maximum cal stack size exceeded【このエラーなに？】

# この記事でできること
- unityroomなど、webGL形式のものをブラウザで起動した際に起こる特定のエラーを解決することができます。

---

## こんなエラーが出たことありませんか？

- スクショはこんな感じ
![スクリーンショット 2020-09-22 8.39.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/240d8051-af6f-8fcf-b6b2-c270ee2adaf4.png)


- テキストで書くとこんな感じ

```
An error occurred running the Unity content on this page.
See your browser JavaScript console for more info.
The error was:
Uncaught RangeError: Maximum cal stack size exceeded
```

---

## 解決策

- chromeの場合は、キャッシュを削除したら解決しました。

![スクリーンショット 2020-09-22 8.39.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/7f754df4-2c40-99d6-6517-3da4a0a5bba3.png)
【Python】複数のディレクトリを作成する

# はじめに
毎回、大学の授業が開講するたびに15回分の授業数のディレクトリを作成するのが面倒だと思ったので、Pythonで複数のディレクトリを作成することにしてみました。

# コード
```multiple_dir.py
import os


dir_num = [i for i in range(1, 16)]

for num in dir_num:
    dir_name = 'No.' + str(num)
    os.mkdir(dir_name)
```
尚、カレントディレクトリで作成されます。
ラズパイのホーム画面からブラウザをショートカットキーで扱う

![photo_2020-09-24 08.41.28.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692893/d09f4f54-0628-49fd-76dd-04877b08aa85.jpeg)
ラズパイでアプリケーションランチャーはないかと検索したらあったのでメモ代わりに書きます！

#Gnome-Pie
『Gnome-Pie』は、ショートカットキーで呼び出すアプリケーションランチャーです。
 指定したショートカットキーを押すと、以下のようにリング状のランチャーを表示されます。

![スクリーンショット 2020-09-21 15.58.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692893/1312ca29-e1a8-fa30-b10b-a1bfb11b4c04.png)
起動するアプリの選択は、マウスやキーで選択します。

#Gnome-Pieのインストール
ターミナルで

```
sudo apt-get -y install gnome-pie
```
でインストールが出来ると思います。
#Gnome-Pieの起動、設定
インストールが出来たらメニューからアクセサリ➡️GnomeーPieをクリック
![20200922_072015.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692893/07f5f8b6-eae2-1100-8761-fcd0b01bd52a.jpeg)

New Pieをクリックし　➕　をクリック。

![2020-09-22-070014_706x556_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692893/048b77c8-207b-b4c7-5331-51ed7a7a44e1.png)

歯車をクリックすると⬇︎　使いやすいコマンドに変更できます。
![2020-09-22-070732_362x528_scrot (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692893/158c45ce-9bf2-1a92-7a3d-2627030d5e05.png)


➕　をクリックすると以下のようになります。
![2020-09-22-070044_560x714_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692893/9213b409-b38a-4560-998f-c96b562471cd.png)
Open URlを選択し、見たいサイトのURLと名前を入力します。
チェックを○にしてOKを押すと完成です。

#完成図
![photo_2020-09-24 08.41.28.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692893/0c821773-7e4f-27d8-98f8-bef69551339d.jpeg)
⬆︎Youtubeやインスタのアイコンを検索してダウンロードしたらこの様になります。

簡単にYouTubeやgoogleで検索が出来るようになりました。
設定次第で色々とショートカットが出来そうです。
【GCP】DataFlowを利用してDataStoreにデータを登録

# はじめに
GCPのデータパイプラインを構築するプロダクトである、Dataflowを利用して
DataStoreにデータを登録する方法を共有します。
最初に、以下の公式ドキュメントより何となくで構わないのでDataflowについて
ご理解をお願いします。
https://cloud.google.com/solutions/smart-analytics?hl=ja

# 前提
* Cloud Storageにファイルを保存できること
* GCPのコンソールからDataStoreの簡単な操作ができること
* CloudShellやSDKを利用してコマンドを実行できること

# できるようになること
* DataStoreにバッチ形式でデータを登録できるようになる
* とりあえずDataFlowが動かせるようになる

## テンプレートの準備
今回は、自分でApacheBeamのパイプラインを作成しません。
あらかじめ、Googleが準備しているテンプレートを利用します。
大まかに以下の手順となります。

1. GCPコンソールのDataflowのページより、「テンプレートよりジョブを作成」を選択
1. Dataflowテンプレートに「Text Files on Cloud Storage to Datastore」を選択
その他のパラメータは適宜、選択入力してください。
1. 画面下部の「同等のRESTまたはコマンドライン」というリンクから実行コマンドを取得
後の実行時に取得したコマンドを利用します。

## 取り込みファイルの準備
Inputに利用するファイルを作成します。
以下の形式で、レコードを任意の件数作ってください。
JSONの形式詳細は、以下のURLを参照ください。
https://cloud.google.com/datastore/docs/reference/data/rest/v1/Entity?hl=ja

```input.json
{"key": {"path":[{"kind":"test", "name":"VOg6lTbC2h"}]}, "properties": { "s": {"stringValue": "string"} }},
```
### 注意点
* 「name」は原則一意の値となること（大量データ作成時は厳密でなくても良いです）
* 文字コードは「UTF-8」であること

## 実行
GCPのコンソールで取得していたコマンドを実行します。
CloudShellかSDKを利用してください。
以下がコマンドの実行例です。

```
gcloud dataflow jobs run testText2Datastore --gcs-location gs://dataflow-templates-asia-northeast1/latest/GCS_Text_to_Datastore --region asia-northeast1 --staging-location gs://test-20200919/temp/ --parameters textReadPattern=gs://test-20200919/test3.json,datastoreWriteProjectId=edu-pubsub,errorWritePath=gs://test-20200919/error/failure.txt
```

## 実行結果確認
確認ポイントは２つです。

* DataFlowのコンソールから正常終了を確認
* DataStoreにデータが登録されていることを確認

## 感想
一番時間がかかったのは、取り込みファイルの準備です。
データ構造を理解するのに、試行錯誤をしました。
一般的な、CSVやTSVからデータをInportするには自分でテンプレートを開発するしか
無さそうです。このテンプレートは異なるプロジェクトのDatastoreのコレクションを
連携する時に利用できそうです。

## 最後に
DataStoreはDBプロダクトの中で唯一無料枠が設定されており、一番安価な
プロダクトです。そのため、コストを重視するプロジェクトで利用する機会
が増えると思います。一方、情報が無く利用に苦戦することが結構ありました。
一助になればと思います。

次は、Dataflowの特徴であるオートスケールとパフォーマンスについて共有
できればと思います。
【Google Meet】会議中にDJみたいなテクニックで笑いをとる


2020年9月20日のM5Stackハッカソンの発表のとき、画面共有のやり方がうまくいかず、あれこれいじっていたら、偶然ハウリングがいい感じにDJみたいになって、大爆笑の渦になりました。
せっかくなので、その方法を共有します。
<br>

##問題のシーン
- 前半：ここから約１分　(3:23:58 - )<br>
https://www.youtube.com/watch?v=iFU7hB0C5AU&feature=youtu.be&t=12238
- 後半：ここから約１分半　(3:25:58 - ) 　※前半よりカオス<br>https://www.youtube.com/watch?v=iFU7hB0C5AU&feature=youtu.be&t=12358

<A href="https://www.youtube.com/watch?v=iFU7hB0C5AU&feature=youtu.be&t=12238"><IMG SRC="https://i.gyazo.com/9787869e903882f4e52b5f2c3bf54e67.png"></A>






##再現

⒈　GoogleMeetの画面右下<B> 「画面を共有」</B>
⒉　<B>「Chromeタブ」</B>　を選択

![スクリーンショット 2020-09-22 7.23.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291592/48ab10b7-295a-d4d1-c38e-cd3b48bb1a74.png)


「画面を共有する」画面で、
<B>Chromeタブ　⇨　Meet</B>
もちろん「音声を共有する」にチェック（デフォルトでチェック入ってる）

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291592/7ba56125-8eea-233a-7a7b-ef23a04b4624.png)


##当たり前
Meetの音声を共有したから、ハウリングが起こるのは当たり前です。
参加者全員の声が無限にハウリングし、なぜかいい感じにDJのテクニックっぽくなったようです。

ただ、このときは、ハッカソンの発表の時で、Youtubeでもリアルタイム中継されていましたし、凄くあせってました。
今冷静にQiitaに記事に書いて、やっと「当たり前じゃん」と気づいています。


##偶然は発明の父
偶然なことが偉大な発見につながることは歴史上たまにあります。
もしかしたら、これからニューノーマルの新しい音楽表現が始まるのかもしれないですね。

>「必要は発明の母かもしれない。だけど、偶然は発明の父」
（デイル・ドーテン / 米 作家・実業家）


<BR>
とりま、
退屈な会議で、これで笑いをとってみたらいかがでしょうか？

<BR>
Macのスクリーンショット保存場所を変更する。

デフォルトでデスクトップに保存されるので、保存場所を変えました。コンソールで以下のコマンドで変更できます。下記ではユーザーの書類フォルダの下に作成した「スクリーンショット」が保存先になります。 
※事前にフォルダは作成しておきます。

```
defaults write com.apple.screencapture location ~/Documents/スクリーンショット/;killall SystemUIServer
```

元に戻す場合は以下を実行します。

```
defaults delete com.apple.screencapture location;killall SystemUIServer
```
PythonでMySQLにINSERTする【初心者向け】

◎下記を参照してDBへのコネクト、SELECT分をためしてみる。
パッケージはmysqlclientを利用する
[PythonでMySQLに接続する方法【初心者向け】](https://techacademy.jp/magazine/18691)

PythonでMySQLに接続する書き方は、そのままではエラーとなるので、下記を利用すること。

```py
#mysqlclientパッケージを利用する
import MySQLdb

# 接続する
conn = MySQLdb.connect(
user='root',
passwd='root',
host='localhost',
db='mstibqym_crontest')

# カーソルを取得する
cur = conn.cursor()

# SQL（データベースを操作するコマンド）を実行する
sql = "select * from test_table"
cur.execute(sql)

# 実行結果を取得する
rows = cur.fetchall()

# 一行ずつ表示する
for row in rows:
    print(row)

cur.close

# 接続を閉じる
conn.close
```
◎INSERT分は下記を参考に実施
[Python3でMySQLを使う – 基本操作からエラー処理までサンプルコード付](https://www.craneto.co.jp/archives/1219/)


```py
#mysqlclientパッケージを利用する
import MySQLdb

# 接続する
conn = MySQLdb.connect(
user='root',
passwd='root',
host='localhost',
db='mstibqym_crontest')

# カーソルを取得する
cur = conn.cursor()

# SQL（データベースを操作するコマンド）を実行する
sql = "INSERT INTO test_table (item) VALUES('xyzss')"
cur.execute(sql)

conn.commit()
cur.close

# 接続を閉じる
conn.close
```
chrome拡張 コンテキスト

createID = chrome.contextMenus.create({
        "title": "add video info", 
        "type": "normal", 
        "contexts": ["link"], 
        "onclick": function(info) {
            console.log(info);
            console.log(createID);

            //実現パターン
            //(1)一覧から選択
                //○手軽 
                //×GETで作品ページにアクセス必要
                //×どうせ動画見てから選択するんでしょ
            //(2)作品ページから選択
            //
            //参考
            //一覧で動画見れる
            //FANZA×
            //MGS○
            //ソクミル×

            //FANZA
                //一覧(レンタル)https://www.dmm.co.jp/rental/ppr/-/list/
                //一覧(動画)https://www.dmm.co.jp/digital/videoa/-/list/=/sort=date/
                //作品(単品) https://www.dmm.co.jp/rental/ppr/-/detail/=/cid=h_094ktra207er/
                //作品(月額)https://www.dmm.co.jp/rental/-/detail/=/cid=h_796much095er/
                //作品(動画)https://www.dmm.co.jp/digital/videoa/-/detail/=/cid=1stars00226/
                //作品(動画 素人)https://www.dmm.co.jp/digital/videoc/-/list/=/sort=date/
            //MGS
                //一覧
                //作品
            //ソクミル
                //一覧(最新作)https://www.sokmil.com/itemlist/t-premium/s-1/index.htm?ref=menu_new
                //一覧(素人)https://www.sokmil.com/av/shirouto/?ref=menu_genre
                //一覧(人妻)https://www.sokmil.com/av/hitozuma/?ref=menu_genre
                
                //一覧(最新作)https://www.sokmil.com/itemlist/t-premium/s-1/index.htm?ref=menu_new

                //作品 https://www.sokmil.com/av/_item/item334934.htm?ref=itemlist_hitozuma
                //作品 https://www.sokmil.com/av/_item/item334925.htm?ref=recent

            // img
            // editable: false
            // frameId: 0
            // linkUrl: "https://www.dmm.co.jp/rental/ppr/-/detail/=/cid=4ssni558/"
            // mediaType: "image"
            // menuItemId: 1
            // pageUrl: "https://www.dmm.co.jp/rental/ppr/"
            // srcUrl: "https://pics.dmm.co.jp/mono/movie/4ssni558/4ssni558ps.jpg"

            // chrome.tabs.create({
            //     url:'http://twitter.com/search?q='+ encodeURIComponent(info.selectionText)
            // });
        }
    });
Chrome拡張　contexMenuのcontexts調査【個人メモ】

chrome拡張のcontexMenuは以下の様に記述される

```js

createID = chrome.contextMenus.create({
        "title": "add video info", 
        "type": "normal", 
        "contexts": ["link"], 
        "onclick": function(info) {
               .....
        }
    });
```

contextsの設定について調査実施
[Oracle Cloud] Data Integration でコード変換してみた

# はじめに

Oracle Cloud Integration では、ETL 機能を提供する Data Integration サービスがあります。Data Integration は、様々なデータアセットからデータを取り込み、データのクレンジング・変換・再形成・変換などの ETL 処理が出来るフルマネージドサービスです。サーバー管理が不要で、GUI で視覚的にわかりやすく ETL 処理を表現できます。

今回は、データ変換の方法を簡単に紹介します。次のデータ変換を行ってみます。

データ変換前 : name と userrank が存在しています。

```
name,userrank
sugiyama,bronze
tanaka,silver
kimura,gold
satou,platinum
```



データ変換後 : userrank に応じて、userrankid を付与します。bronze は 1, silver は 2, gold は 3, platinum は 4 のコードを付与します。

```
name,userrank,userrankid
sugiyama,bronze,1
tanaka,silver,2
kimura,gold,3
satou,platinum,4
```



# データ準備

Object Storage に、Input 用のファイルをアップロードします。

![1600724492596.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/948baf21-b0d4-a28b-61db-db85400c42b9.png)



# Data Flow 作成

アップロードした、csv ファイルを受け取り、データ変換を行い、Object Storage へ Output する Data Flow を作成します。

csv ファイルを受け取る部分です。

![1600724766201.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/a0e5102e-1cf7-1290-ee63-f130756698a9.png)



データ変換を行う部分です。Expression Operator で新たな列を定義しています。

![1600725932159.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/29f6a0f8-0b51-588f-49a8-5c13c2ea153c.png)



CASE WHEN 句で、変換の条件を入れています。

```
CASE WHEN EXPRESSION_1.SOURCE_1.userrank='bronze' THEN 1
  ELSE CASE WHEN EXPRESSION_1.SOURCE_1.userrank='silver' THEN 2
    ELSE CASE WHEN EXPRESSION_1.SOURCE_1.userrank='gold' THEN 3
      ELSE CASE WHEN EXPRESSION_1.SOURCE_1.userrank='platinum' THEN 4
        ELSE 999
      END
    END
  END
END
```



Data タブで、追加した `USERRANKID` をリアルタイムに確認できます。CASE WHEN 句で指定した条件で正しく動作していることがわかります。Data Flow 編集中にリアルタイムに確認できるのは良いですね。

![1600725984620.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/4d0be968-e100-9b7e-ed70-b9aad003bcb6.png)



データ変換後に、Object Storafe へ出力する部分です。

![1600726313976.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/fab41916-98eb-8246-a6c5-667cfa004c0d.png)



最後に、Validate を押してエラーが無いことを確認して、Save and Close で閉じます。

![1600726426637.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/cf27ca31-2d4d-a167-e844-78dfb9282d48.png)



# 動作確認

作成した Data Flow の動作確認をしましょう。Integration Task を作成し、Application に Publish したあと、Run をします。

![1600726532380.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/f06674b6-3663-7d56-692b-bdfba51a88fa.png)



Task Runs で、正常に完了していることがわかります。

![1600726619038.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/06120e55-2a1a-ab4c-9f7b-76ef1e816b3f.png)



Output Bucket に、データ変換御のファイルがアップロードされています。

![1600726688855.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/cc95f3c6-15d5-dd39-901c-c6cc543d8d91.png)



ファイルの中身です。正常に `USERRANKID` が変換されています。

```
name,userrank,USERRANKID
sugiyama,bronze,1
tanaka,silver,2
kimura,gold,3
satou,platinum,4
```
【M5Stack初心者向け】Arduino IDEを使った後、UI Flowを使う方法

# Arduino IDEとUI Flowを同時には使えない

こんな単純なこともわからず、かなりハマりました。

もし同じような人がいた場合の参考として記事にします。


私の場合、**最初にUI Flowを使えるように、M5BunerでUIFlowをM5Stackに焼きました。**

その後、色々調べるうちに、Arduino IDEを使って、作り方が書いてあるサイトが多かったので、**Arduino IDEもダウンロードして、しばらくサンプルで色々使ってみて**いました。


で、いざ自分で開発しようと思うと、やはり、UIFLOWのビジュアルプログラミングを使った方がよさそうなので、切り替えようとしたのですが、


<img width="300" alt="IMG_0317.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664861/61bc6f59-e479-6513-fec5-a2ead2e0acfe.jpeg">

この画面から動かなくなってしまいました。さてどうしたものか。。。
電源ボタン押したり、色々してみるものの動かず。。

幸いなことに今回はハッカソンでサポートしてくれる方がいたので、聞いてみました。


すると、

## もう一度、M5BunerでUIFlowを焼き直してください。

そんなことか。。。

ただ、初心者の私としては、もう焼いたということはインストール完了、と思っているので、もう一度焼き直すという発想はありませんでした。


なので、同じような方のために、記事にしてみました。
誰かの参考になったら幸いです。
M5Stackを起動させるまでにハマったポイントと改善のヒント（Mac版）

# M5StackのUIFLOWを使えるようにするまでに、かなりハマった

以下のハッカソンに出場して、はじめてM5Stackを使いました。

https://mashupawards.connpass.com/event/188452/

が、ひとまず開発を始めるためのUIFlowを使えるようにするまでの段階で、かなりハマりました。

今回スイッチサイエンスの方のサポートがあったからなんとかなったものの、独学で初めてたら確実に折れてました。。。

なので、独学で始めようと思った方で、プログラミングのことがよくわからなくても、少なくとも、ビジュアルプログラミングが使えるところまでなるように、その対処法を忘れないうちにメモしておきます。

## 使ったもの

・Mac book Pro
・OS：Mac OS High Sierra
・M5Stack　basic
・USB-C Digital AV Multiportアダプタ


## 基本はこの流れで進めてください。

（公式サイト：英語）
https://docs.m5stack.com/#/en/quick_start/m5core/m5stack_core_get_started_MicroPython

（他、参考サイト）
https://m5stack.github.io/UIFlow_doc/ja/ja/base/Update.html


## ハマった点１：WiFiを接続がうまくいかない。

私の場合、なかなかWiFiが接続できませんでした。

### 解決策：2.4GHzで接続する

WiFiは、2.4GHzと5GHzの2種類ありますが、
**M5Stackに接続するWiFiは2.4GHzでしか動きません。**

通常、家庭のWiFiだと２つありますよね？

XXX-A、XXX-G　っていう感じで。
正直なぜ2つあるのか知らず、いつも通り、Aで接続していましたが、

XXX-A・・・5GHz
XXX-G・・・2.4GHz

らしいです。

なので、必ずM5Stackでは、Gの方のWiFiと接続してください。




## ハマった点２：USBポートがうまく反応しない。

M5Stackを接続すると、以下のようなエラーメッセージがでました。

![image04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664861/d453c861-fff7-77f6-8536-660d742ed003.png)


### 解決策１：M5BunerのBaudrateの値を一番小さいものに変更する。

写真にあるように、M5Bunerの上のBaundrateの値一番小さいものに変更してみてください。

![image05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664861/8c62e084-c05f-3610-e687-12271deb84f0.png)


### 解決策２：PCとM5Stackを接続しているもの（USBなど）を何度も接続し直してみる。

何度もUSBを付け直してみたら直りました。




## ハマった点３：WiFi接続後の設定で必要なスマホからのアクセスができない。

公式サイトで言うところの、AP hotspot configuration WiFiのところの2の中に、スマホのブラウザで**192.168.4.1にアクセスする**ところがあります。私の場合、アクセスしても表示されませんでした。


## 解決策：接続するデバイスを変更してみる。

私のスマホは、Androidなのですが、なぜか接続できませんでした。ただiPadでも試してみると、接続できました。正直理由はわかりません。

ですが、２つ以上接続デバイスを持っているようであれば、うまくいかないときは、別のデバイスでやってみることをおすすめします。


# M5Stackはおもしろい

私は、今回のハッカソンでこんなものをつくりました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">先日のハッカソンでつくったものは、「３歳のこどもから使える、LINEコミュニケーションデバイス」でした。<br><br>うちの子も、もう少しで使えるようになるので、楽しみです。<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://twitter.com/hashtag/M5Stack?src=hash&amp;ref_src=twsrc%5Etfw">#M5Stack</a> <a href="https://twitter.com/hashtag/%E3%83%92%E3%83%BC%E3%83%AD%E3%83%BC%E3%82%BA%E3%83%AA%E3%83%BC%E3%82%B0?src=hash&amp;ref_src=twsrc%5Etfw">#ヒーローズリーグ</a> <a href="https://twitter.com/hashtag/IoT?src=hash&amp;ref_src=twsrc%5Etfw">#IoT</a> <a href="https://t.co/lwwboxfZGS">pic.twitter.com/lwwboxfZGS</a></p>&mdash; 柳瀬浩之@人材開発×UX専門家 (@btap_hiro) <a href="https://twitter.com/btap_hiro/status/1308153952005795840?ref_src=twsrc%5Etfw">September 21, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ハッカソンでは、M5Stackを使ったアイデアが様々あって、面白かったです。
UIFlowを使えるようにするところまでで困難がありますが、ぜひ乗り越えて、開発を楽しんでください。

## もしよかったら、LGTMお願いします！