OmniAICreator/Qiita-1.07M huggingface dataset:
ECMAjavascript学习


1.create a function
// ES5
var x = function(x, y) {
   return x * y;
}

// ES6
const x = (x, y) => x * y;




2.create a object


class Car {
  constructor(name, year) {
    this.name = name;
    this.year = year;
  }
}
let myCar1 = new Car("Ford", 2014);
let myCar2 = new Car("Audi", 2019);



3.create a premise object//创建一个高级对象
let myPromise = new Promise(function(myResolve, myReject) {
// "Producing Code" (May take some time)

  myResolve(); // when successful
  myReject();  // when error
});

// "Consuming Code" (Must wait for a fulfilled Promise).
myPromise.then(
  function(value) { /* code if successful */ },
  function(error) { /* code if some error */ }
);


<html>
<body>

<h2>JavaScript Promise</h2>

<p>Wait 3 seconds (3000 milliseconds) for this page to change.</p>
<h1 id="demo2">this is 3333</h1>
<h1 tilte="this is a h1" id="demo"></h1>

<script>
let myPromise = new Promise(function(myResolve, myReject) {

  myResolve(document.getElementById("demo2").innerHTML+"this is a h1");
  myReject(345);
});

myPromise.then(function(value) {
  document.getElementById("demo").innerHTML ="this is a h1"+value;
});
</script>

</body>
</html>




4.the symbol type//给既存对象追加属性
const person = {
  firstName: "John",
  lastName: "Doe",
  age: 50,
  eyeColor: "blue"
};

let id = Symbol('id');
person.id = 140353;
Ruby CLIにて、実行部をクラス内でコードする

ロジックをクラス内で実装し、処理はメインメソッドにまとめたいときに使用した書き方です。
Rubyで使い捨てCLIを作成したときにお世話になりました。

```ruby
class SomethingTool
  def run
  end
end

if __FILE__ == $0
  something_tool = SomethingTool.new
  something_tool.run
end
```

`if __FILE__ == $0`は、明示的に「ここがメインの処理」と示すために使ってます。
詳しい説明は下記の記事を参考にして下さい。
[[Ruby] if __FILE__ == $0 ってなんなの！？](https://qiita.com/Kanezoh/items/93f186ab8b07919e8421)
AMD Ryzen の CPU 温度を Linux で確認する(kernel 5.4 or later)

Ryzen の CPU 温度を Linux で取得するのは長らくできませんでしたが, kernel 5.4 からめでたくサポートされました.


Linux 5.4 Brings Working Temperature Reporting For AMD Ryzen 3000 Series CPUs
https://www.phoronix.com/scan.php?page=news_item&px=Linux-5.4-Hwmon-Zen-2-Thermal

Ubuntu 20.04 では標準で 5.4 or later です.

Ubuntu 18.04 は HWE kernel を使うと 5.4 or later になります.

したがって 18.04 以降ではだいたい使えると思って良いでしょう.

`sensors`(lm-sensors package) コマンドで, Ryzen9 3950X で試してみます.

Monitor AMD RYZEN Temps in Linux
https://techhut.tv/monitor-amd-ryzen-temps-in-linux/

```
k10temp-pci-00c3
Adapter: PCI adapter
Tdie:         +67.8°C  (high = +70.0°C)
Tctl:         +67.8°C  

amdgpu-pci-0600
Adapter: PCI adapter
vddgfx:      1000.00 mV 
fan1:        1452 RPM  (min =  900 RPM, max = 5700 RPM)
edge:         +45.0°C  (crit = +104000.0°C, hyst = -273.1°C)
power1:       18.02 W  (cap = 168.00 W)
```

Voila! :tada:

GPU(FirePro W9100) のほうも表示してくれました


## 疑問点

Ryzen 1xxx 販売から 3 年くらいかかったのはなんででしょうかね?

## 今後

Kernel 5.6 ではより詳細なレポートしてくれるようです!

Ryzen CPUs On Linux Finally See CCD Temperatures, Current + Voltage Reporting
https://www.phoronix.com/scan.php?page=news_item&px=AMD-Ryzen-k10temp-CCD-V-Current
Vue.jsのvue-cursol-fxを使ってみる

最近は就活中で暇なんでちょこちょこVue.jsを触っています。Railsでのバックエンドばかりだったのでフロントの知識もなく、Vue用のプラグインでとりあえずそれっぽくしたいなと思いvue-cursol-fxを使ってみました。

githubのインストレーションを参考にしています。詳しくはREADME.mdを見てください。
https://github.com/LuXDAmore/vue-cursor-fx?ref=kabanoki.net
## 環境
- Windowns 10
- Node.js v14.15.1
- @vue/cli 4.5.9

言い訳なんですがバーチャルボックスだとnodeのサーバー立ち上げた際ホットリロードが異常に遅い(約1分)ため仕方なくWindowsに直接Nodeをインストールして最近は遊んでいます。仮想環境でホットリロードがなんで遅いのかはいまだ原因分からないです。誰か教えて...

## 導入
まずはvue-cliでプロジェクトを作ります。

```
vue create sample_app
```

作成時の設定はデフォルトで、Vue2にしておきます。

sample_appのディレクトリに移動して、vue-cursor-fxを入れます。

```
cd sample_app
npm install --save @luxdamore/vue-cursor-fx
```
次にApp.vueにてimportしてコンポーネントを書き加えます

```App.vue
<template>
  <div id="app">
    <cursor-fx color="#39B509" color-hover="#acf98e"></cursor-fx>
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Hello Vue"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue';
import { CursorFx } from '@luxdamore/vue-cursor-fx';
import '@luxdamore/vue-cursor-fx/dist/CursorFx.css';

export default {
  name: 'App',
  components: {
    HelloWorld,
    'cursor-fx': CursorFx,
  },
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```


これでカーソルが表示されます。

![2020-11-25_17h23_07.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667634/f5661775-ab4a-2042-c3f3-fde83f1a58cf.gif)

オプションでポインタの形や大きさなど変えられます。

```
<cursor-fx color="#39B509" color-hover="#acf98e" shape='square'></cursor-fx>
```

![2020-11-25_17h32_13.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667634/ebf4a9ae-7456-cad3-fdc0-cf0fc107497f.gif)

以上です。
Matplotlibのグラフを直接LINE Notifyに送信する

##やりたいこと
Matplotlibで生成したグラフを、ファイルに保存せずに直接LINE Notifyに送信したい。

##コード
```python

import numpy as np
import numpy.random as random
import matplotlib.pyplot as plt
import io
import requests

#適当にグラフを作る
random.seed(10)
x = np.arange(1, 101, 1)
y = random.randn(100)
y.sort()
plt.plot(x, y)

#メモリに画像を保存
buf = io.BytesIO()
plt.savefig(buf, format='png')
#グラフを表示しない
plt.close()

line_notify_token = 'LINE Notifyのトークン'
line_notify_api = 'https://notify-api.line.me/api/notify'
headers = {'Authorization': f'Bearer {line_notify_token}'}
data = {'message': 'matplotlib test'}
files = {'imageFile': buf.getvalue()}
result = requests.post(line_notify_api, headers = headers, data = data, files = files)
```

##結果
![_20201125_132903.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624097/40953bec-8e9d-c74e-c4b7-181a5c010c69.jpeg)


##参考文献
* [PythonでLINEにメッセージを送る](https://qiita.com/moriita/items/5b199ac6b14ceaa4f7c9)
* [matplotlibのグラフをローカルに一時保存せずにslackへ送信するサンプルコード](https://qiita.com/kaito__/items/9aa63cccc99261814065)
bundle installでAn error occurred while installing ffi (1.9.25), and Bundler cannot continue.というエラーになったときのメモ

メモなので詳しいことは省きます＞＜

---

`bundle install`したら↓のエラーで成功しません。
( `< ffi 1.9.25 >`の部分は他のgem（例えば、okogiri (1.10.9)）だったりもします。)

```
・・・省略・・・

Installing <ffi 1.9.25> with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

・・・省略・・・

An error occurred while installing <ffi (1.9.25)>, and Bundler cannot
continue.
Make sure that `gem install <ffi -v '1.9.25' --source 'https://rubygems.org/'>`
succeeds before bundling.

・・・省略・・・
```

# 解決策
エラー文の`Gem::Ext::BuildError: ERROR: Failed to build gem native extension.`がヒントになりました。
↓のコマンドを上から順に実施し、その後改めて`bundle install`、成功！

```
$ sudo rm -rf $(xcode-select -print-path)
$ sudo rm -rf /Library/Developer/CommandLineTools
$ xcode-select --install
```
【Rails】device機能【備忘録】

こんにちは。Web開発6週目、Rails初心者の あをか です。
初心者にとってdeviceというgemはブラックボックスで、何がどう繋がっているのか把握しづらかったです。

復習も兼ねて、deviceの導入過程を書いていきます。

<h4>■ ログイン機能（device）</h4>
<h5>①deviceを入れてモデルとテーブルを作ろう</h5>
　<b>gem 'device'</b>とGemFileに書き、
　ターミナルで①<b>bundle install</b>➡②<b>rails g devise:install</b>する。
　続いてログイン機能で欠かせないuser情報を扱うために、モデルとテーブルを作成したい。
　<sup>rails g model User string:name, string:email,...かと思いきや、deviceの時は違う。</sup>
　<b>rails g devise User</b>だけでUserテーブルの中身まで作成してくれる。
　ただしdeviceで作成したテーブルのカラムは、デフォルトではemailとpasswordだけ。
　ユーザー名を管理したい場合、
　db/migrateの下にあるマイグレーションファイルに<b>t.string :name</b>と追記する。
　（その他userテーブルで管理したいものはこの時に全て書いておくこと）
　マイグレーションファイルへの追記が終わったら、<b>rails db:migrate</b>する。

　（rails db:migrateをした後に間違いが見つかると少しめんどくさい。このコマンドで、この時のマイグレーションファイルがschemaファイルに反映され、マイグレーションファイルは読み取り専用になるから。ちなみにschemaファイルは現在のテーブル一覧が分かるので便利。
※詳しくは➡https://qiita.com/kakiuchis/items/2ed1604557ee29bbcbf7
※カラムを変えたくなったら➡https://qiita.com/azusanakano/items/a2847e4e582b9a627e3a)

<h5>②routesファイルとUserモデルを確認しよう（見るだけ）</h5>
　routes.rbに<b>devise_for :users</b>と書かれているはず。
　user.rbに <b>devise :database_authenticatable, :registerable,
         　　　　　　　　　:recoverable, :rememberable, :validatable</b>と書かれているはず。

<h5>③ユーザー登録画面とログイン画面のレイアウト</h5>
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908193/d850cebc-1940-cf7d-57b7-63bcac2cdf50.png)
　app/views/devise/registrations/new.html.erbがユーザー登録画面、
　app/views/devise/sessions/new.html.erbがログイン画面。
　適宜編集しましょう。name入力フォームを作る時はtext_field使うのに注意。emaiilとpasswordが特殊なんです。

<h5>④deviceのコントローラはどこ・・？</h5>
　結論から申しますと、deviceコントローラは触る事ができません（存在はするようです）。
　で、どうするかというと、application_controllerで操作します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908193/de0224d0-2927-8a25-abe0-c36b1b232166.png)
　1～4行目・13～16行目を書きましょう。
　privateではなくprotectedなのは、別のコントローラからも操作できるように。
　(5～11行目はログイン・ログアウト後のルートを変えたい場合の記述)

<h5>⑤バリデーション</h5>
　userテーブルのnameカラムにバリデーションを設定したいので、
　models/user.rbに記述する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908193/99357b04-4065-9a1d-1723-808a74972f22.png)


以上、device導入の備忘録でした。
初心者なので間違い等あるかもしれませんが、その際は教えて下さると幸いです！！
EcmaScript2017 Async await

Async/await

``` 
<html>

<body>
    <script>
        const sleep = (delay) => {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(delay)
                }, delay);
            });
        };

        async function sleepAsync() {
            const sleep1 = await sleep(100);
            console.log(sleep1); // 100

            const sleep2 = await sleep(200);
            console.log(sleep2); // 200

            console.log(await sleep(300)); // 300
        }

        sleepAsync();
    </script>
</body>

</html>
```
ASP.NET core + EF core コマンド「add-migration」にてエラー：Cannot resolve scoped service～ from root provider.

環境：ASP.NET core 3.1, Visual Studio 2019

以下の通り、同じDbContextを2つ登録していたのが原因。
InMemoryの方を消したら通った。

``` cs
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // InMemory
            services.AddDbContext<AppDbContext>(options =>
                options.UseInMemoryDatabase(nameof(AppDbContext))
                .ConfigureWarnings(m => m.Ignore(InMemoryEventId.TransactionIgnoredWarning))
                );

            // Postgres
            services.AddDbContextPool<AppDbContext>(options =>
            {
                options.UseNpgsql(Configuration.GetConnectionString(typeof(AppDbContext).Name));
            });
省略
        }
```
CocoaPods Version Update時に発生したライトプロテクション関連エラーの回避方法！

##事象

CocoaPodsのバージョンが古くインストールできないPodがあったため、CocoaPodsをアップデートしようとしたら、エラー発生！！以下のエラーの解決法法を紹介します。

※今回のリサーチでわかった解決方法は以下の通りですが、なにか他に方法がありましたら教えてください。

```terminal
You don't have write permissions for the /usr/bin directory
```

##事象発生までの流れ
###Cocoapodsのバージョンをアップデートしよう以下のコマンドを実行

```terminal
$ sudo gem uninstall cocoapods
```

###エラー発生
#### /usr/bin directory.に書き込む権限がないらしい。


```terminal
ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions for the /usr/bin directory.
```

##理由
#### Catalinaでは、Systemファイルにはライトプロテクトがかかっており、書き込みや削除ができない。
引用：
"Catalina has a new file system arrangement where most of the system files are write-protected. Apple uses two partitions, a read-only one for the main system files and a writeable one for other files, and melds them together and presents them as one to the user.
[For details see the WWDC video What's New in Apple Filesystems]"(https://developer.apple.com/videos/play/wwdc2019/710/#,"")


##解決方法

```terminal
$ sudo gem install cocoapods -n /usr/local/bin
```

#### "-n"は、既存のファイルを上書きしないという意味。これでライトプロテクトを回避できるのか！
![Screen Shot 2020-11-25 at 4.56.24 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/e31721b8-cfa3-f7ea-8850-4cb55b1aa906.png)
[出典:【 mv 】コマンド――ファイルやディレクトリを移動する／名前を変更する](https://www.atmarkit.co.jp/ait/articles/1606/13/news024.html)



#### pod setupはしなくてみいいみたいです。

```terminal
$ pod setup
```
引用：
"Yes that is intended. The current 1.8.0 pod setup does not do anything and we have kept it if we need it in the future and to avoid breaking systems that depend on it.

I can keep this open with a tiny enhancement that prints out a message the "Setup completed successfully." or something."
[Cocoapods GitHub: No output from pod setup #9184]
(https://github.com/CocoaPods/CocoaPods/issues/9184)


##参考文献
[1.CocoaPodsのバージョンアップの方法](https://qiita.com/Yuta/items/a20f4ea3207635b4ef9e)
[2.You don't have write permissions for the /usr/bin directory. while installing Cocoapods](https://stackoverflow.com/questions/50422786/you-dont-have-write-permissions-for-the-usr-bin-directory-while-installing-co)
[3.SIP is disabled, but /usr/bin is write protected anyway (macOS Catalina beta 10.5)](https://stackoverflow.com/questions/57440334/sip-is-disabled-but-usr-bin-is-write-protected-anyway-macos-catalina-beta-10/57445554#57445554)
Jupyter notebookの出力セルの大きさを無限にする

### TL;DR

以下のマジックコマンド（Cell magic）をセルに入れて実行。

```python
%%javascript
IPython.OutputArea.auto_scroll_threshold = 9999;
```

注意：`%matplotlib inline`のようなLine magicではないので，独立したセルを用意して実行しないとエラーが発生する．詳しくは[IPythonの公式ドキュメント](https://ipython.readthedocs.io/en/stable/interactive/magics.html) 参照．

- `%` - All available *line magic* commands - [check here](https://ipython.readthedocs.io/en/stable/interactive/magics.html#line-magics)
- `%%` - All available *cell magic* commands - [check here](https://ipython.readthedocs.io/en/stable/interactive/magics.html#cell-magics)



### Cf.

- [Magic functions - IPython公式ドキュメント](https://ipython.readthedocs.io/en/stable/interactive/tutorial.html#magic-functions)
- [comment:53708976 issue:2172 ipython github.com](https://github.com/ipython/ipython/issues/2172#issuecomment-53708976)
- [ipythonノートブックの出力ウィンドウのサイズを変更する](https://qastack.jp/programming/18770504/resize-ipython-notebook-output-window)
- [Jupyter notebookで列をすべて表示したい - Qitta](https://qiita.com/daifuku_mochi2/items/30258e58750ff8e85d37)
CatalinaのSIPでRead-only file systemエラーが/usr/領域操作で出てきたとき

# 前提

こちらでSIPのガードを外していること
[初心者向け　MacでOperation not permittedの解決方法](https://qiita.com/iwaseasahi/items/9d2e29b02df5cce7285d)

# 起こった問題

開発用にlibftd3xx.dylibをコピーしようとしたときのこと。

```
$ sudo cp libftd3xx.dylib /usr/lib/
Password:
cp: /usr/lib/libftd3xx.dylib: Read-only file system
```

Read-onlyということで結局コピーできない。

# どうやって解決したか

Catalinaの問題らしい？
こちらのStackOverflowで回答がありました：[Read-only file system" with SIP disabled in macOS Catalina](https://stackoverflow.com/questions/61131634/read-only-file-system-with-sip-disabled-in-macos-catalina)

```
$ sudo mount -uw / 
```
【Rails】1対多の作成

<h1>本投稿の目的</h1>
・Rails学習の議事録です。

---
<h1>学習に使った教材</h1>
Udemyの以下2つの教材を参考にまとめました。
・["はじめてのRuby on Rails入門-RubyとRailsを基礎から学びWebアプリケーションをネットに公開しよう"](https://www.udemy.com/course/the-ultimate-ruby-on-rails-bootcamp/) 
・["フルスタックエンジニアが教える 即戦力Railsエンジニア養成講座"](https://www.udemy.com/course/rails-kj/)

---
<h1>○1対多とは?</h1>
・紐づいたmodel間での関係の名称
・ex)ツイートmodelとコメントmodle
・この時,ツイート1つに対して複数コメントが可能
・この関係を"1対多"の関係と呼ぶ

**【説明の簡略のために書き省略記号を使用】**
・素となるmodel = model(1)
・紐づくmodel = model(多)
*(コーディング例では任意のmodel名が入る)

**【1対多の関係におけるmodel関係の名称を2つ示す】**
・has many = model(1)から見たmodel(多)の関係
・belongs to = model(多)からみたmodel(1)の関係

<h1>○model(他)作成後の操作</h1>
<h3>①model(多)の作成</h3>

```ruby:qiita.rb
rails g model model(多) model(1):references column情報
```
**【解説】**
○model(1): references
⇨ referencesでmodel(1)を紐けるように設定
⇨ これで,model(多)には, model名(1)_id というcolumnが作成される

**【例:Q&Aアプリケーションのmodelを想定】**

```ruby:qiita.rb
rails g model answer questin:references column情報 
```
**【解説】**
⇨ answer model　へ question  model  を紐付ける
⇨ questionのcolumnに answer_id が作成される

<h3>②model(多)のmigrationファイルへの記述</h3>
・model(多)を紐づけで作成しておけば自動記述される

```ruby:qiita.rb
class Create+model(多) < ActiveRecord::Migration[5.0]
  def change
    create_table :model(多)s do |t|
      t.references :model(1), foreign_key: true
      t.string :column名1, null: false
      t.text :column名2, null: false

      t.timestamps
    end
  end
end
```
**【解説】**
○null: faluse
⇨ column値に 空 を受け付けない

○t.reference :model(1), foreign_key: true
⇨ model(1)のid にないと,model(1)_idとしてmodel(多)で保存できない

<h3>③model(多)のdbの作成</h3>

~~~
rails db:migrate
~~~

<h3>④model(多)のmodelファイルへの記述(自動記述)</h3>
・model(多)作成時に,以下が,model(多)のmodelファイルへ自動で記述される

```ruby:qiita.rb
class model(多) < ApplicationRecord
  belongs_to :model(1)
end
```

**【解説】**
○belongs_to :model(1)
⇨ (*model(1)名称は単数係)

**【例:answer modelに紐づくquestion modelの場合】**

```ruby:qiita.rb
class Answer < ApplicationRecord
  belongs_to :question
end
```
○belongs_to :question⇨ 親がmodel(1) で 子がmodel(多)
⇨ (model(多)から見るとmodel(1)は1つに定まる)
⇨ (子供は複数人いるが,親や一位に定まるというイメージ)

<h3>⑤model(1)のmodelファイルへの記述(手動記述)</h3>
・model(1)については,追加で以下の記述を追加する

```ruby:qiita.rb
    has_many :model(多)s, dependent: :destroy
```

**【解説】**
○has_many :model(多)s
⇨ 一番上の行に記述する
⇨ (*モデル名(多)は複数形)

○dependent: :destroy
⇨ model(1)が削除されると紐づいたmodel(多)は自動で消される という設定

**【例:Answerの素となるQuesitionの場合】**

```ruby:qiita.rb
class Question < ApplicationRecord
    has_many :answers, dependent: :destroy
end
```

<h3>⑥rails routesの更新</h3>
・config/routes.rb ファイルを開く
・内容を次のように更新 (do 移行が追加で更新する部分)
*(model名は複数形)

```ruby:qiita.rb
resources :model(1)s do
 resources :model(多)s
end
```
子供向けの本でチャット風クイズゲームを作ってみた


最近やっとプログラミングがちょっとだけわかってきたので、
今まで苦手意識が強かったJavaScriptと向き合ってみようと思う。

楽しくできてわかりやすい物がいいなと思ったので、 [子供向けの本](https://www.amazon.co.jp/dp/4295007838/ref=nosim/?tag=impressjapan-22&linkCode=as1 "子供向けの本")買ってやってみた。

語学も絵本とかで勉強するといいって聞くし、人は成功体験が大切だし。

#チャット風クイズゲームを作ってみよう
本は動物の鳴き声が出されるので英語で動物の名前を答える作りなので、
そこは変えて世界遺産の問題にした。

```html:quiz.html
<DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>世界遺産一問一答</title>
    <link rel="stylesheet" href="css/quiz.css">
  </head>
  <body>
    <div class="chat-quiz">
      <h2>世界遺産一問一答</h2>
      <ul id="chat">
        <li>世界遺産の問題を出すよ！それでは問題です！！！</li>
        <li>ででん！</li>
      </ul>
      <input type="text">
      <button type="button">答え</button>
    </div>
    <script src="js/quizdata.js"></script>
    <script src="js/quiz.js"></script>
  </body>
</html>
```
吹き出しは本に付いていた画像を使用しています。
oddが奇数で出題者、evenが偶数で回答者です。
一問一答なので、連投はできません。

```css:quiz.css
.chat-quiz {
 width: 600px;
 margin: auto;
}

input {
 margin-left: 140px;
}

li:nth-child(odd) {
 background: url("../img/girl.png");
 width: 380px;
 height: 21px;
 padding: 20px 110px;
 line-height: 13pt;
 list-style: none;
}

li:nth-child(even) {
 background: url("../img/boy.png");
 width: 380px;
 height: 21px;
 padding: 20px 110px;
 line-height: 13pt;
 list-style: none;
}
```

#慣れないぜ、JavaScript
quizdata.jsでは問題と答えの配列を作ります。
できるまで次の問題になりません。

```js:quizdata.js
var quiz = [
 ['自由の女神はどこの国にあるでしょう？', 'アメリカ'],
 ['厳島神社に何県にあるでしょう？', '鹿児島'],
 ['モアイ像はどこの国にあるでしょう？', 'チリ'],
 ['姫路城に何県にあるでしょう？', '兵庫'],
 ['ナスカの地上絵はどこの国にあるでしょう？', 'ペルー'],
];
```
quiz.jsで処理を書いてます。
要素とかid取ってくるとjsやってる感じがする。

```js:quiz.js
var addMessage = (mes) => {
  // ul要素を取得
  var ul = document.getElementById('chat');
  // li要素を作成
  var li = document.createElement('li');
  // テキスト情報を作成
  var text = document.createTextNode(mes);

  // ul要素に追加
  li.appendChild(text);
  ul.appendChild(li);
}

// 問題追加
var qnum = 0;
addMessage(quiz[qnum][0]);

var btn = document.querySelector('button');
btn.addEventListener('click', () => {
  var ipt = document.querySelector('input');
  addMessage(ipt.value);
  if (ipt.value == quiz[qnum][1]) {
    qnum += 1;
    // 最後の問題の後は最初の問題に戻る
    qnum %= quiz.length;
    addMessage('正解！' + quiz[qnum][0]);
  } else {
    addMessage('違うよ〜');
  }
});

```
#確認してみよう
トップ画面。
問題が出題されています。

![スクリーンショット 2020-12-14 1.58.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893737/75c445b5-d59d-fa33-485a-c7a2ad53d382.png)

不正解の答えを入力してみます。
正解するまでこの問題です。パスはなし。
![スクリーンショット 2020-12-14 18.32.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893737/ed66de79-3351-c114-6333-3f17303258d4.png)

正解の答えを入力してみます。
正解したら次の問題がすぐに表示されます。
![スクリーンショット 2020-12-14 18.35.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893737/2007f48b-930b-a579-0487-e92e56debf13.png)

#所感
苦手意識が強い人には子供向けの本は良いと思った。
少し苦手意識が減ったので良かった。

もっとスマートな書き方があるんだろうなと思ったけど、
最初は愚直にやっていくのが一番だと思っているのでちょうどいいと思う。

お読みいただきましてありがとうございました。
[GCP]Cloud StorageにCloud CDNを設定する

Advent calendar2日目です🎉
[パーソンリンク](https://www.person-link.co.jp/)では[kibera](https://kibe.la/?gclid=CjwKCAiA8Jf-BRB-EiwAWDtEGhq_4-FdgaUqR29YRwpJmGgA_zwiHrzTk7Zq_qd-aUhQfkheIMHU1hoCPB8QAvD_BwE)というツールを使って社内で技術系の知見を共有しています。
そこで投稿したものを外部にも公表します🌞
普段はAWSを主に扱っていますが、業務で取り扱うことがあったので今回はGCPの内容です。

## 本題

GCPのCloud StorageにCloud CDNを設定する手順を書きます。
**CDN**とはオリジンサーバーの代わりにコンテンツをキャッシュしてユーザに配布してくれるやつで、高速化やオリジンサーバの負荷削減などの効果があります。

![CDN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140953/60d4dcad-ff57-e747-09e2-2e12b5fe383a.png)

GCPでは**ロードバランサの機能の一部**としてCDNを利用することができます。(下の記事曰く「巨大な CDN 機能付きロードバランサー」)

![1_jWfxrPkpQbca_oZ7BN6r4A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140953/30703002-3e2a-c9e7-6523-6bb0cd2c7604.png)
画像引用元：[Cloud CDN カスタムオリジン | google-cloud-jp](https://medium.com/google-cloud-jp/cloud-cdn-custom-origins-dd496092b395)

## 前提
以下は行っている前提で書きます。

- GCPアカウント作成
- GCPプロジェクト作成
- GCPアカウントの決済情報登録

## Cloud Storageの作成
[ホーム画面](https://console.cloud.google.com/) > メニュー > [Storage](https://console.cloud.google.com/storage/browser)

1. 「バケットを作成」をクリック
2. 名前、リージョン(asia-northeast1(東京))、ストレージクラス(Standerd)、アクセス制御(均一)を設定。
3. 「作成」をクリック

## Cloud Load Balancingの作成 ＆ Cloud CDNの設定
[ホーム画面](https://console.cloud.google.com/) > メニュー > ネットワーク サービス > [負荷分散](https://console.cloud.google.com/net-services/loadbalancing)

1. 「ロードバランサを作成」をクリック
2. HTTP(S)負荷分散の「構成を開始」をクリック
3. 「インターネットから自分のVMへ」を選択して「続行」をクリック
4. ロードバランサの名前を記入
5. バックエンドの構成 > バックエンドサービスとバックエンドバケットの作成または選択 > バックエンドバケット > バックエンドバケットを作成
6. バックエンドバケットの名前、Cloud Storageバケットの選択、Cloud CDN(**Cloud CDNを有効にする**)を設定。 ※画像参照
7. フロントエンドの構成 > 「完了」をクリック
8. 「作成」をクリック

![スクリーンショット 2020-11-25 15.18.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140953/cd301b4e-93e1-de0b-3fee-286b8aceb863.png)

## 確認
ストレージに適当なindex.htmlをpushして、アクセスしてみます。
https://storage.cloud.google.com/BUCKET_NAME/index.html
※ BUCKET_NAMEは作成したものに置き換えてください
上記のURLにアクセスすると別のURLへ飛ばされ、CDNのキャッシュサーバへアクセスしていることがわかります。

## 参考
[【GCP入門編・第29回】Cloud Load Balancing で Web アプリケーションにロードバランサーを設定する | 株式会社トップゲート](https://www.topgate.co.jp/gcp29-cloud-load-balancing)
[【GCP入門編・第30回】 Cloud CDNで静的ファイルの配布を行う | 株式会社トップゲート](https://www.topgate.co.jp/gcp30-cloud-cdn)
roman numerals



# code

```ruby
def check_column(i)
  case i
  when 1000
    r = 'M'
    s = ''
  when 100
    r = 'C'
    s = 'D'
  when 10    
    r = 'X'
    s = 'L'
  else
    r = 'I'
    s = 'V'
  end
  return r,s
end

def check_roman(i,q)  
  check = q.to_f / 4
  if check < 1
    r,s = check_column(i)
    r_num = r * q
  elsif check == 1
    r,s = check_column(i)
    r_num = r + s
  elsif check <= 2
    r,s = check_column(i)
    r_num = s + r * (q - 5)
  elsif check > 2
    r,s = check_column(i)
    r_n,s_n = check_column(i * 10)
    r_num = r + r_n
  end
  return r_num
end 

num = ARGV[0].to_i
r_num = ''
if num / 3000 > 1
  p " there aree not roman numerals over 3000"
else
  [1000,100,10,1].each do |i|
    q = num / i
    if q != 0
      r_num += check_roman(i,q)    
      p r_num

    end
    num = num - q * i
  end
end

```



------
 - **source** ~/classes/muli_scale/grad_members_20f/members/keita_k7/memo/l1.org
k3sをJetson AGX Xavierで動かすまで　

# 挑戦すること
この記事では

①エッジコンピュータでAIアプリケーションを構築したい

②kubernetesによるコンテナオーケストレーションを実感したい

という欲求のもと、やってきたことをQiitaにメモしていこうと思います。

※私は、アプリケーション開発やインフラ設計などを全くもってやったことがない、ド素人です。
誤った理解がありましたら、ぜひともコメントでアドバイスの方よろしくおねがいします。

# todoリスト
+ Jetson AGX Xavierにイメージを焼き込む
    + 仮想環境の構築
    + イメージの焼き込み
+ kubernetesの実装
    + k3sとは
    + アプリケーションの実行/コンテナオーケストレーションの確認
    + AIアプリケーションのログをfluentbitに送る
+ AIアプリケーションの作成/コンテナの立ち上げ
    + <a href="https://qiita.com/dokaben/items/95ea5971855fabaa6671">Flaskの理解</a>
    + <a href="https://qiita.com/dokaben/items/3e3fd038e437a7a76ece">レジストリ管理</a>
    + Yolo
    + Openpose
    + fluentbit
    + レジストリの勉強
    + docker-composeによるコンテナ間連携

# Jetson AGX Xavierにイメージを焼き込む
「なぜ仮想環境経由でエッジコンピュータにイメージを焼くのか」はなぞですが、これが一般的なやり方のようです。こちらについて何かご存知の方、コメントよろしくお願いいたします。

流れに関してはたくさんの参考記事が世に出回っているので、参考しまくります

1. 仮想環境のセッティング
1.1 VirtualBoxの立ち上げ
参考：https://eng-entrance.com/virtualbox-install
1.2 GuestAdditionの導入
参考：https://linuxfan.info/virtualbox-guest-additions


2. Jetson Xavierにイメージを焼き込む準備
2.1 NVIDIA SDK manager をインストール
参考：https://www.nakasha.co.jp/future/ai/vol9_yolov3nvidia_jetson_agx_xavier.html

# AIアプリケーションの作成/コンテナの立ち上げ
※のちに更新


# 結果
※出来上がり次第、更新
Rails チュートリアル_6章_学習メモ

#学んだ事
##findメソッドとfind_byメソッドの違い
+ findメソッドはidを起点として情報を探すが、id以外からは検索出来ない。
+ find_byはid以外も可能で、他のカラムで探す際に使用する。

##%w[]
配列を作成する際に便利な方法
```%w[4 4 5 6 4 ]``` → ```["4","4","5"...]```

##メールアドレスの正規表現
```VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i```
これを```format:{with:VALID_EMAIL_REGEX}```と記述する
一旦、メールの表記検証する際はこの書き方を丸暗記した方が良さそう。

##一意性の検証→今もよくわかってない
###重複を許可しないようにする
####dupメソッド
同じ属性を持つデータを複製するためのメソッド
重複アドレスを検証する際に用いる

```example:qiita.rb
test "email addresses should be unique" do
    duplicate_user = @user.dup
    @user.save
    assert_not duplicate_user.valid?
  end
```


####データベースの一意性を保証する
新たにuserモデルにマイグレーションファイルを作成し、```add_index```メソッドを使って一意性を強制させる
リスト6.29参照

##authenticateメソッド
>引数に渡された文字列（パスワード）をハッシュ化した値と、データベース内にあるpassword_digestカラムの値を比較します。一致していえば、ture、間違っていれば、falseを返す
C++をCで使えるようにする


C++に関数を埋め込み、Cのプログラムからその関数を呼び出すことでC++をCで使えるようにしました。

## 導入

```言語:ファイル構成
├── build/
├── main.c
├── test.cpp
├── test.h
└── CMakeLists.txt
```
以下が各ソースコードです。

```言語:main.c
#include "test.h"
int main() {

    print_cpp("hello cpp!");
}
```

```言語:test.cpp
#include "test.h"
#include <iostream>
void print_cpp(const char *s) {

    std::cout << s << std::endl;
}
```

```言語:test.h
#ifdef __cplusplus
extern "C" {
#endif

void print_cpp(const char *s);

#ifdef __cplusplus
}
#endif
```

```言語:CMakeLists.txt
cmake_minimum_required (VERSION 3.13)
add_executable(Main test.cpp main.c)
```

## 実行方法
(1) ビルドフォルダに移動

```言語:terminal
cd build
```
(2) cmake実行(out-of-source ビルド)

```言語:terminal
cmake ..
make
```
補足：cmakeを使わずにg++でコンパイルすると以下のようになります。(C++のバージョンはC++11)

```言語:terminal
g++ -o Main -std=c++11 ../test.cpp ../main.c 
```
(3) 生成された実行ファイル(Main)を実行

```言語:terminal
./Main
```

##実行結果
ターミナル上にc++経由で出力することができました。

```言語:terminal
hello cpp!
```
社内サーバのredmineをherokuに移行する（DB移行）

こんにちは。
この記事は前回の続きになります。
前回の記事は以下になります。

redmineをherokuにpushしようとしたときにエラーが出る
https://qiita.com/biz_saito/items/32e0f67e911f164bac5c

前回デプロイが完了して閲覧、スーパーユーザーでのログインが可能となりました。
新しく作るとここで終わりになるのですが、運用中のredmineがあるため、データ移行が必要です。

少し、苦労したのでメモです。




既にあるデータベースを削除します。

```
heroku pg:reset --app appname 
```

移行用データをダンプします。

```
pg_dump --no-acl --no-owner -h localhost local_db_name -f local_db_name.dump
```

移行用データをherokuのデータベースに流し込みます
（heroku pg:pushでもできますが、なぜか認証できなかったのでこの方法でやりました。）

```
heroku pg:psql --app heroku_app_name < local_db_name.dump
heroku run rake db:migrate
heroku restart
heroku open

```

流し込みを行った後、データは移行されていましたがInternal errorが発生したため
マイグレーションを行っています。

再起動後、今まで通り動くことが確認できました。

参考サイトさま

https://jade.alt-area.jp/archives/900

http://blog.319ring.net/2016/05/27/heroku_pg_push_error/

この記事が助けになれば幸いです。
最後までお読みいただきありがとうございました。
README.orgの雛形

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 


# qiita\_links

1.  [README.org](https://qiita.com/keita_k7/private/fbd8fe839ab0d1397c0a)

2.  [No.8 assert\_equal](https://qiita.com/keita_k7/private/cca5863aa118d5f572c1)

3.  [No.9 ruby-IV (Recursive Fibonacci)](https://qiita.com/keita_k7/private/008daa9292a4429463b6)

4.  [No.9: ruby-appendix-V(rubular)](https://qiita.com/keita_k7/items/fefe1680d9a6ca4eb924)

5.  [ruby-VI(hello class)](https://qiita.com/keita_k7/items/e75d78bfec312085de5b)

仕上げ 1. [roman\_numerals](https://qiita.com/keita_k7/items/a2292fcce213e2c005a8)

仕上げ 2. [Google recruit problem, exp and prime](https://qiita.com/keita_k7/items/93a1d54c1c87fd61eeca)



------
 - **source** ~/classes/muli_scale/grad_members_20f/members/keita_k7/README.org
【受験予定者向け、2020年11月時点】CIW Javascript Specialist資格試験に落ちました。

# tltr
Web開発経験1.5年とJS入門参考書2回読破で試験に挑んで、66/100で75点合格ラインに届かず落ちました。
公式の出題範囲は一般的なJS入門参考書の内容だと書いてありますが、実際の問題では2/3はCookieに関するマニアックな問題でした。落ちた原因は設問範囲が偏っていることだと考えています。運が悪くて範囲がおかしい問題セットに遭遇した可能性もあります。

# 試験自体
1D0-435 CIW Javascript Specialist (Japanese Only)を受けました。英語版の試験は1D0-735(2020年11月時点の番号です。番号は毎年変わる？)です。
[出題範囲](https://www.ciwcertified.com/resources/documents/course-descriptions/JavaScript_v2.0_CourseOutline.pdf)はJSの入門レベルの内容：文法、データ型、よく使うオブジェクトと関数、ブラウザDOM、Form、JQuery、AJAX、Web Storage API、Geo API、Canvas API
受験費は165ドルで約16500円です。
時間は90分で、50問の4択問題で、75点で合格です。

公式：https://www.ciwcertified.com/ciw-certifications/web-development-series/javascript-specialist

# 受験前
[公式テキストと過去問](https://ciwcertifiedstore.com/index.php?route=product/search&search=Javascript)は15000円で値段が高くて、それを買いませんでした。
公式以外の6000円くらいの[過去問](https://crammedia.topexam.jp/ciw-javascript-specialist-torrent-4870.html)も解きました。公式サイトに書いてある出題範囲と同じく、JSの入門レベルの内容です(実際の出題範囲は全然違いましたが)。

# 受験後
66/100点で75点合格ラインに届かずに落ちました。
運が悪いせいか、問題の2/3がCookieに関するマニアックな問題でした(e.g., Cookieの保存場所、Cookie複数サイト共有方法。JS入門書ではCookieをそこまで解説していません。~~CIW Cookie Specialist説~~)。実際の開発でもそんなにcookieを触っていません。検証したことないですが、1D0-435 Japanese Onlyだけ出題範囲がおかしくて、英語版の1D0-735は大丈夫かもしれません。

文法、関数、データ型、HTMLに関する問題は少ないです(8問くらい)。印象に残った問題は、HTMLのttタグを生成するjavascriptコードの問題で、そもそもttタグはHTML5で廃止されますし、実際の開発で一回も使ったことがないです。

日本語がおかしい問題も2、3問ありました。(e.g., ある人は配列の要素数を"確定"したい。選択肢の中でどの関数を使えば良いか?)

公式の出題範囲はJSの入門レベルの内容と書いていましたが、筆者は1.5年のWebサーバー開発経験があって、一般的なJS入門書([改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで](https://www.amazon.co.jp/%E6%94%B9%E8%A8%82%E6%96%B0%E7%89%88JavaScript%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80-%E3%83%A2%E3%83%80%E3%83%B3%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%AB%E3%82%88%E3%82%8B%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E7%8F%BE%E5%A0%B4%E3%81%A7%E3%81%AE%E5%BF%9C%E7%94%A8%E3%81%BE%E3%81%A7-%E5%B1%B1%E7%94%B0-%E7%A5%A5%E5%AF%9B/dp/477418411X))も2回読破しましたが、それでも落ちるというのは設問が偏っていると考えています。

# 最後に
これからの受験予定者のために、受験した方はコメント欄に試験の感想とか実際の出題範囲を載せて頂ければ幸いです。
CentOS8.2にhttpdをセットアップする手順

| [../](https://qiita.com/taconana/items/e45f19e83c825a9ba75e) |
---
VPSサーバー（CentOS8.2）にhttpdをインストールした。手順をメモしておく。

## httpdのインストールとサービス登録

httpd関係のパッケージをインストールする。

```bash

$ yum install -y httpd httpd-tools httpd-devel httpd-manual
$ httpd -version
Server version: Apache/2.4.37 (centos)
Server built:   Sep 15 2020 15:41:16
```

httpdサービスを起動する。また、OSの起動時に自動でサービスを開始してくれるように設定しておく。

```bash

$ systemctl enable httpd.service
$ systemctl start httpd.service
$ systemctl status httpd.service
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Wed 2020-11-25 11:00:57 JST; 30s ago
     Docs: man:httpd.service(8)
 Main PID: 33994 (httpd)
   Status: "Running, listening on: port 80"
    Tasks: 213 (limit: 24989)
   Memory: 44.2M
```

## ブラウザからの確認

以下のようなテスト用のhtmlを作成して、サーバーのGNOMEデスクトップ上でブラウザからURL(`http://localhost/`または`http://127.0.0.1/`)を指定してアクセスしてみる。GNOMEにはFireFoxがプリインストールされている。

```bash

$ vi /var/www/html/index.html
<!DOCTYPE html>
<html lang="ja">
<head/>
<body>
<h1>こんにちは</h1>
</body>
</html>
```
この時点では、サーバー外のPCなどからIPアドレスやドメインを指定でアクセスしてもつながらない。

## Firewallの設定と外部からの接続確認

Firewallに以下のようにhttpサービスを追加する。80/tcpポートは明示的に追加しなくてもいいようだ。

```bash
$ firewall-cmd --zone=public --add-service=http --permanent
$ firewall-cmd --reload
$ firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: dhcpv6-client http ssh vnc-server
  ports: 
  protocols: 
```
外部のブラウザから、固定のIPアドレスやドメイン名を指定して、http://153.xxx.xxx.xxx/ または http://xxx.com/ のように接続して「こんにちは」が表示されることを確認しておく。

## 補足1: centos-logos-httpdが足らない場合

`yum update httpd`の実行時に、依存関係のあるcentos-logos-httpdが足らないとアラートが出る場合は、centos-logos-httpdをネット上で探して、wgetでダウンロードするなどしてインストールしておくこと。

```bash

$ su -
$ cd Downloads
$ wget http://mirror.centos.org/centos/8/BaseOS/aarch64/os/Packages/centos-logos-httpd-80.5-2.el8.noarch.rpm
$ ls
centos-logos-httpd-80.5-2.el8.noarch.rpm

$ rpm -ivh centos-logos-httpd-80.5-2.el8.noarch.rpm 
```

## 補足2: GoogleChromeを使いたい場合

Firefoxがあれば、特にChromeは必要ないかもしれない。Chromeがお気に入りの場合には、yumのリポジトリにGoogleのサイトを追加してからダウンロードする。手順は、https://www.karelie.net/how-to-install-google-chrome-on-centos7/ などを参照のこと。

```bash

$ vi /etc/yum.repos.d/google-chrome.repo
[google-chrome]
name=google-chrome
baseurl=http://dl.google.com/linux/chrome/rpm/stable/x86_64
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub
$ yum install -y google-chrome-stable

# アプリのアイコンから起動できる。コマンドで開くなら、以下の感じ。
# --no-sandboxがないとワーニングが出るみたい。
$ google-chrome --no-sandbox

# userファイルのアクセス権限のワーニングが出る場合は権限を設定する。
# ユーザーIDごとにディレクトリがある。1000はtaconanaの場合。
$ chmod 777 /run/user/1000/dconf/user
```

以上

| [../](https://qiita.com/taconana/items/e45f19e83c825a9ba75e) |
---
Electronの`shell.openExternal`が上手く動かない際の注意すべき点

先日Electronを使用したWindowsアプリケーションを作成している際、Electronの[`shell.openExternal`](https://www.electronjs.org/docs/api/shell#shellopenexternalurl-options)が上手く動かないトラブルにハマりました。
原因としては非常に初歩的なうっかりミスだったのですが、誰か同じ点で躓いている方のお役に立てばと思い記事にさせていただきました。

## やりたかったこと

「外部ブラウザで何か画面を開き、自分のウィンドウは閉じる」みたいな処理をしたい

## ハマった点

Electronの`shell.openExternal`は非同期で開く処理をしています。
そのため、安直に

```typescript
shell.OpenExternal('https://example.com/');
//何か処理
window.close();
```

のように書いてしまうと開く前にレンダラプロセスが終了してしまい、意図したとおりに動かなくなってしまう可能性があります。

## 解決法

`shell.openExternal`が`Promise`を返してくれるので、それにメソッドチェーンとして

```typescript
shell.openExternal('https://example.com/').then(() => {
    // 何か処理
    window.close();
}).catch((e) => {
    // 何かエラー時の処理
    console.log(`Error!: ${e}`);
});
```

のように書くと、意図したとおり動いてくれます。
Azure Storage BlobにあるBlobをAuzre Functionsで監視して定期削除する

## 環境

- OS： win32 x64

## 参照

前回の記事の続き
https://qiita.com/yuuton8823/items/a690a7e15343d781bf97
👆でStorageに保管されているコンテナを取得しました。  
取得コンテナの最終更新日時を参照すれば定期的に削除が行えるようになります。
今回はその定期削除を実装していきます。

## Functions  

### ソリューションのパッケージの監理

以下インストールしておく。

- Microsoft.Azure.Storage.Blob
- Microsoft.NET.Sdk.Functions
- Microsoft.Azure.Functions.Extensions

### Timer Trigger

毎日走らせたいので、TimerTriggerを"0 0 0 * * *"に設定する。
CRON式なので慣れていない人は注意が必要です。

コンテナの最終更新日時と比較するためにトリガー発生時刻を格納する変数も用意する。  

``` C#
[FunctionName("Function1")]
        public async Task RunAsync([TimerTrigger("0 0 0 * * *")]TimerInfo myTimer, ILogger log)
        {
          //トリガー発生時刻
            DateTime deleteDay = DateTime.UtcNow;

          // *** 省略 ***
        }
```

### 変数用意

コンテナの生存期間を設定する。  

取得したコンテナの最終更新日時とトリガー発生時刻の差をとり、それが生存期間より大きいならばコンテナを削除する。

``` C#
        //生存期間(7日0時間0分0秒)
        static TimeSpan deleteLimit = new TimeSpan(7, 0, 0, 0);
```

### 削除処理

引数にblobClientと取得したコンテナ名を設定する。
Azure.Storage.Blobパッケージを使用してコンテナを削除する。

```C#
private static async Task<bool> DeleteAsync(string containername, CloudBlobClient blobClient)
        {
          CloudBlobContainer deletecontainer = blobClient.GetContainerReference(containername);

          return await deletecontainer.DeleteIfExistsAsync();
        }
```

### 取得コンテナリストを定期削除するロジック

foreachの中でcontainerリストをまわして、containerのLastModified(最終更新日時)プロパティを参照する。  
if で(deleteDay - lastModifiedTime > deleteLimit) を行い、true時のみ削除処理を行うようにすればオッケー。

```C#
            //対象のコンテナを削除
            foreach (CloudBlobContainer container in containers)
            {
                string containerName = container.Name;
                DateTimeOffset? lastModifiedTime = container.Properties.LastModified;
                if (containeNname.Contains("azure") == false)
                {
                    //生存期間を超過している場合は削除
                    if (deleteDay - lastModifiedTime > deleteLimit)
                    {
                       var isDeletedSuccessfully = await DeleteAsync(containerName, blobclient);
                        if (isDeletedSuccessfully)
                        {
                            _fileTransferLogService.InsertDeleteLog(containerName);
                        }
                    }

                }
            }
```

実装したら発行して確認してみよう。

## まとめ

Azure Functions 皆も使ってみよう！
マルチスケールシミュレーション特論：第 10 回をまとめてみた

\![ruby-2.5.5p157](<https://img.shields.io/badge/ruby-2.5.5p157-brightgreen>) 


# フィボナッチ数列(問題)

-   本日は Fibonacci 数列についての問題を解く
    
    ```
    fib(n) = fib(n-1)+fib(n-2)
    0 1 1 2 3 5 8 13 21 ...
    ```
    
    を recursion(再帰)で求めよ


## 進め方

前回と同様に **テスト駆動開発** で今後の学習を進めて行く

-   まずは初項から計算を行う
    -   red: 表示を行うred → p fib(0)エラーがおこる
    
    -   green: def をしてみる
        
        ```ruby
        def fib(n)
          if n==0
            return 0
          end
        end
        ```
    
    -   refactoring: assert\_equal.rb の assertion(確認)を試しておく

-   次は、2 項目を求める
    -   これは初項と同様に求める

-   次は 3 項目 = 2 項目 + 1 項目

この処理を逐一行っていく。エラーが現れたら随時処理を行っていく


## プログラム(最終版)

上記のようにプログラムを書き進めていくと以下のようなプログラムができます

```ruby
def fib(n)
 return 0 if n==0
 return 1 if n==1
 return fib(n-1) + fib(n-2)
 end

 require './assert_equal'
 # assert_equal.rb  は同じディレクトリにある事を想定
 [[0,0],[1,1],[2,1],[3,2],[4,3],
 [5,5],[6,8],[7,13],[8,21]].each do |index, expected|
   puts assert_equal(expected, fib(index))
 end
```


# class 化

次にクラス化について学習を行ったオブジェクト指向という考え方がある。このキーとなる考え方が，

-   隠蔽(capsulation)
-   継承(inheritance)
-   多形(polymorphism)

である


## クラス化とは

[クラス化について](https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%A9%E3%82%B9_(%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF))

簡単にまとめると、オブジェクト指向プログラミングにおけるクラス（英:class）とは、オブジェクトを生成するための設計図あるいはひな形に相当するものである


## プログラムをクラス化すると

まずは class なしのプログラム

```ruby
def puts_hello name
  puts "Hello #{name}."
end
def gets_name
  name = ARGV[0] || 'world'
  return name
end
```

次にクラスありのプログラム

```ruby
class Hello
  def initialize
    # インスタンス変数
    @name = gets_name(name)
    puts_hello
  end

  def puts_hello
    puts "Hello #{@name}."
  end

  def gets_name
    name = ARGV[0] || 'world'
    return name
  end
end
```


## インスタンス変数について

-   宣言

変数の初めに「@」をつけることで宣言を行うことができる

-   スコープ

インスタンスメソッド内でのみ使用できる変数。インスタンスごとに異なる値を持つことができ、メソッドを超えて参照することができる


# 参考文献

-   <https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%A9%E3%82%B9_(%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF)>



------
 - **source** ~/Downloads/git/grad_members_20f/members/taiseiyo/memos/class10.org
Pythonで文字列からUnicode変換「u''」と「.decode('utf-8')」 

```
[\u30d7\u30ed\u30c0\u30af\u30c8\u30c7\u30b6\u30a4\u30f3]
```

このコードは、Unicode文字のエスケープシーケンスというらしいです。
（情報源：https://blog.xin9le.net/entry/2015/02/08/212947）

python 2.x（3の前のいろいろ）バージョンでは、日本語をこの状態に変換しないといけません。
そのために、文字の前に「u」をつけてください。するとunicode変換されます。

```
u'プロダクトデザイン'
```

ですが、もしここに変数を入れようと思った場合、「u」をつけても、新しい変数の名前になってしまいます。
これでは何もできません。

```test.py
test = 'プロダクトデザイン'

nanika(utest)
# nanikaは適当です。
```

なので、.decode('utf-8')を使います。以上！
（情報源：https://qiita.com/yubessy/items/9e13af05a295bbb59c25）

```test.py
test = 'プロダクトデザイン'

nanika(test.decode('utf-8'))
# nanikaは適当です。
```

あと補足ですが、文字列とunicode文字エスケープシーケンスなどをwebサイト上で変換することができるサイトがあります。
こちら。どうぞ。
http://0xcc.net/jsescape/

あと、unicode文字エスケープシーケンスを普通の文字列にjavascriptで変換しやすいように関数を作った方がいます。
素晴らしすぎる..。感謝しかないです。
https://shanabrian.com/web/javascript/unicode-unescape.php

```
var unicodeUnescape = function(str) {
    var result = '', strs = str.match(/\\u.{4}/ig);
    if (!strs) return '';
    for (var i = 0, len = strs.length; i < len; i++) {
        result += String.fromCharCode(strs[i].replace('\\u', '0x'));
    }
    return result;
};
```

```
var result = unicodeUnescape('abc123\\u3042\\u3044\\u3046\\u3048\\u304a');
 
console.log(result);
```
psqlでダンプデータのリストア中に「invalid command \N」エラーが出るのを回避する

ダンプデータ生成時にcopyではなくinsert文を生成するようにする

```
pg_dump -h ${ホスト} -p ${ポート} -U ${ユーザー名} --inserts -v ${schema名} > ${ファイル名}.sql
```

参考URL
https://qastack.jp/programming/20427689/psql-invalid-command-n-while-restore-sql
golangで先週の〇〇曜日をtime.Timeで取得するコード

```golang
type Weekday struct {
	Now time.Time
	Loc *time.Location
}

func (w Weekday) LastWeekOf(weekday time.Weekday) time.Time {
	levellingOffset := int(w.Now.Weekday())
	weekDiff := 7-(int(weekday))

	return time.
		Date(w.Now.Year(), w.Now.Month(), w.Now.Day(), 0, 0, 0, 0, w.Loc).
		AddDate(0, 0, -levellingOffset).
		AddDate(0, 0, -weekDiff)
}
```

こう使う

```go
package main

import (
	"fmt"
	"time"
)

func main() {	
	now := time.Date(2020, 11, 27, 0, 0, 0, 0, time.UTC)	
	fmt.Println(now.Year(), now.Month(), now.Day())

	w := Weekday{
		Now: now, 
		Loc: time.UTC,
	}	
	r := w.LastWeekOf(time.Monday) // 先週の月曜日を取得する
	fmt.Println(r.Year(), r.Month(), r.Day())
}
```

結果

```
2020 November 27
2020 November 16
```
【備忘録】docker環境にサーバーを立てる時のIP指定注意

# はじめに
dockerでサーバーを立てるときにIPアドレスの指定でハマってしまったので備忘録として残します

#docker内でサーバーを立てる時のIPアドレスは「0.0.0.0」にする
以下のようにdocker内では、0.0.0.0を指定しておけば、ホスト環境の「127.0.0.1:繋ぎ込みしたポート番号」からアクセスできるようになる

**djangoの場合**

```bash:サーバー起動時のコマンド
$python manage.py runserver 0:8000
# 0 = 0.0.0.0を表す
```




**jupyter-labの場合**

```bash:/root/.jupyter/jupyter_notebook_config.py
c.NotebookApp.allow_root = True
c.NotebookApp.ip = "0.0.0.0"
c.NotebookApp.token = "xxxx"
c.NotebookApp.port = 8888
c.NotebookApp.open_browser = False
```
EC2でyum installしようとしたらno space left on deviceが出た

# ディスクの利用状況確認
いっぱいだった

```
df
```
# メモリの利用状況確認
Swap領域(4G)は殆ど使われていなかった

```
free
```

# Swap領域への割当を減らそう
## 4Gで作ったあったものを破棄
```
swapoff /swapfile
rm /swapfile
```
## 2Gで作成
```
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
```

## ちゃんと減っているか確認
```
free
```

参考URL
https://qiita.com/cyborg__ninja/items/891a1f5acf7c14237939
https://www.wantanblog.com/entry/2020/04/11/183201
[AWS] Terraform AWS Provider 3.0.0以降のACM書式変更について

## 概要

Terraform で`ACM(AWS Certificate Manager)` を使用しSSL証明書を作成する際に、`AWS Provider`のversionによって書き方が異なっていたため変更点をまとめます。

## 環境

* Mac

```
$ terraform version
Terraform v0.13.5
+ provider registry.terraform.io/hashicorp/aws v3.17.0
```

### Version3.0.0以前

無料証明書の検証用レコードは以下の様に`[0]`としてリスト形式で記載する必要があります。

https://registry.terraform.io/providers/hashicorp/aws/2.70.0/docs/resources/acm_certificate_validation

例

```
resource "aws_route53_record" "example_certificate" {
  name = aws_acm_certificate.example.domain_validation_options[0].resource_record_name
  type = aws_acm_certificate.example.domain_validation_options[0].resource_record_type
  records = [aws_acm_certificate.example.domain_validation_options[0].resource_record_value]
}
```

3.0.0以降、上記内容で`terraform plan`を実行すると、`Error: Invalid index`としてエラーが返却されます。

```
Error: Invalid index

  on route53.tf line 36, in resource "aws_route53_record" "example_certificate":
  36:   type = aws_acm_certificate.example.domain_validation_options[0].resource_record_type

This value does not have any indices.
```

### Version 3.0.0以降

公式ドキュメントに記載がある通り、`for each`を使用し値を展開する必要があります。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate_validation

```
resource "aws_route53_record" "example_certificate" {
  for_each = {
    for dvo in aws_acm_certificate.example.domain_validation_options : dvo.domain_name => {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  }
  allow_overwrite = true
  name = each.value.name
  records = [each.value.record]
  type = each.value.type
  zone_id = data.aws_route53_zone.example.zone_id
  ttl = 60
}
```

## まとめ

少し古めの書籍は基本的に3.0.0より前のversionが多いため、注意が必要です。
困ったら公式ドキュメントを読むことをおすすめします。

https://registry.terraform.io/providers/hashicorp/aws/latest
【PostgreSQL】コマンドプロンプトの文字化け

###環境
- OS Windows10
- ツール コマンドプロンプト
- データベース PostgreSQL

###現象
コマンドプロンプトでSQLファイルを実行した時のエラーメッセージが文字化けする

###解決策
*postgresql.conf*の設定を変更

```:PostgreSQL/12/data/postgresql.conf
// 665行目あたり
lc_messages = 'Japanese_Japan.932' // デフォルト
↓
lc_messages = 'en_UC' // こっちに変更
```

###chcpでは解決しなかった

```
chcp 65001
```
試してみたけど文字化けしました。他の解決策を探して莫大な時間を費やしてしまったけど、

`postgresql.conf`をいじればいいということになかなか至りませんでした。


PostgreSQLで文字化けに苦しんでいる人がいたら参考にしてみてください。
Coopelで業務効率化

# Coopelで業務効率化

## RPAを使って業務効率化の指令が！
弊社ではビジネスサイドの個々がそれぞれで抱えていた毎日の定型業務がありました。
人員の増員もそう簡単にいかないということもありますが、RPAツールを使えば日々のとらわれていた業務から開放されより重要な仕事に集中できることから導入の検討が始まりました。

## RPAとは
RPAは定型業務を自動化することですが、例えば、、、
1. とある画面から数値をコピーし
2. スプレッドシートに貼り付け
3. 数値がXXならば、管理画面でYYYを登録
といった複数の画面(アプリ)をまたいで使うという様々な会社で発生していそうな日々の業務フローを自動化によって解決するものです。

### 今回弊社で決めたポイント
RPAで解決できるものの多くはエンジニアが何らかのシステムを開発することによって解決できます。
RPAを使えばそのエンジニア業務の工数短縮につながるのかもしれませんが、やはりRPAの本質としては非エンジニアが実装できるようにするというところがポイントかと思いますので、非エンジニアでも実装できそうなRPAツールを選定するというのも重要になりました。
情報収集をしようとするとRPAを導入したもののうまく実装できなかったりメンテナンスができなかったりといったことがあったので、選定は慎重に行いました。


## Coopelを選んだ理由
結果的にDeNA社製のCoopelを選びました。理由が下記になります。

- ブラウザ操作に特化
- 非エンジニアが直感的操作で構築可能(変数とかの概念もない)
- 低価格

まずRPAツールとして有名なものを見てみましたが、エンジニアの私でもたまにマニュアルを見たくなるようなところがあったり、非エンジニアの人には理解しづらいところがあるなというところが多々ありました。その中でCoopelと出会いましたが、自分が

1. 管理画面ログイン
2. とある画面に遷移
3. 必要なフォーム情報を入力
4. ファイルダウンロード

といったフローを5分程度で自動化できたことに驚きました。マニュアルも見ずにここまでできたことに非エンジニアでも実装できるのではと期待が持てました。
それと同時に業務フローをヒアリングをした結果、ブラウザ操作とファイルをダウンロード・アップロードでほぼほぼ完結していることがわかりCoopelで対応できそうなことがわかりました。
無料のお試し期間で実装して結果、問題なさそうだったのでCoopelの採用が決まりました。


### とはいえ問題点も、、、
実装して運用も開始しつつありますが、このままエンジニアなしであとはお任せといったことは難しそうでした。

- 複雑な仕組みとなるとやはり実装する人にはEXCELのマクロを組むといったようなある程度のコンピュータの知識が必要になる
- 動かなくなったときの対応力

CSSの多少の知識IFの概念であるとかフローチャートのようなことは前提知識としてあるべきな人がやると運用が進めやすいでしょう。またCoopelはユーザーがブラウザ操作をしたものを記録することができますが、CSSセレクタの「:nth-child()」でクリックが記憶されていたりして、のちの改修で順番が狂うと操作が進まなくなるので、こういったつまづきポイントは事前に共有すべきです。

## まとめ
CoopelはほかのRPAツールと比べても直感的操作が可能ですが、やはりポイントポイントではエンジニアが介入すべき点が出てくるかと思います。RPA全般に言えることですが、始めるときにはエンジニアと非エンジニアの責任範囲を明確にすることや実装時のエンジニアがレビューをするなど定期的なエンジニアの介入が必要なのではと感じました。
Laravel × nginx でログやキャッシュ書き込み時のPermission Deniedを回避

ディレクトリとファイル権限を以下に変更

```
find ./ -type d -exec chmod 755 {} \;
find ./ -type f -exec chmod 644 {} \;
```

所有者をnginxへ変更

```
chown -R nginx. ${laravelディレクトリ}
```

参考URL
https://www.geekfeed.co.jp/geekblog/laravel6_docker
JavaScript基礎まとめ③

1.オブジェクト

Javascriptにおけるオブジェクトは
大きなオブジェクトの中に、またオブジェクトがあり、その中にまたオブジェクト、
プロパティがある。

例えば

```javascript

let human = {
  men:{
   name: "yamada",
   age : 20,
  }
 }
 
 console.log(human.men.name)


///yamadaと表示されます///

```

ここでオブジェクト名がｈuman、プロパティ名がnameになる。

プロパティを追加、今ある値を変更するときには

```javascript
let human = {
  men:{
   name: "yamada",
   age : 20,
  }
 }
human.age = 25
/// age を変更///
human['address'] = 'Tokyo'
///addressのプロパティを追加///
```

となる。


２．documentオブジェクト

```javascript

document.getElementById("id名")
	
document.getElementsByClassName("class名")

document.querySelectorAll("セレクタ名")
	
document.querySelector("セレクタ名")


```


3.イベント発火
〇〇したら＊＊するの
〇〇したら　＝イベント
〇〇したら＊＊するの一連の流れをイベント発火という。

イベント発火に使う関数はaddEventListenerメソッド。

```javascript
要素.addEventListener('イベント名', 関数)
```

イベント名は「クリックしたら」とか「カーソルが来たら」とか
それぞれ定義されている。


〇〇したら＊＊するの
＊＊するもう少し深堀りすると
例えばカーソルが指定の要素に乗っているときは色が変わり、
要素から外れたときには色が戻るととかは

```javascript
要素.setAttribute(name, value)
/// nameのvalue(値）を指定する///
要素.removeAttribute(name, value)
///　nameのvalue(値）をとりのぞく////
```


普段使っているサイトを見ていくとJavaScriptかなり使われていそうだなと
基礎を勉強していくだけでも感じました。

間違い等あればコメントお願いいたします！