OmniAICreator/Qiita-1.07M huggingface dataset:
[Angular] 西暦から和暦への変換CellRenderer

##やったこと
西暦の年月日時刻データ（'yyyy-MM-dd HH:MM:ss.SSS')を和暦に変換するCell Rendererの実装メモ。
参考：[西暦を和暦に変換する](http://cly7796.net/wp/javascript/convert-western-calendar-to-japanese-calendar/)

##コード

```typescript:japaneseCalender.ts
  // transform Dataformat ('yyyy-MM-dd HH:mm:ss.SSS') into Japanese Style
  japaneseCalenderRenderer(param: any) {
    const splitDateString = param.data.printTime.split(/[\s]+/);
    const splitTimeString = splitDateString[1].split(/[:.]+/);
    // transform YYYY into 令和yy
    const target = new Date(splitDateString[0]);
    function japaneseCalenderConverter(yearTarget: Date): string {
      const jaCalender = [
        {
          era: '明治',
          start: '1868-01-25',
        },
        {
          era: '大正',
          start: '1912-07-30',
        },
        {
          era: '昭和',
          start: '1926-12-25',
        },
        {
          era: '平成',
          start: '1989-01-08',
        },
        {
          era: '令和',
          start: '2019-05-01',
        },
      ];

      for (let i = jaCalender.length - 1; i >= 0; i--) {
        const t = new Date(jaCalender[i].start);
        if (yearTarget >= t) {
          return (
            jaCalender[i].era +
            (yearTarget.getFullYear() - t.getFullYear()) +
            '年' +
            (yearTarget.getMonth() + 1) +
            '月' +
            yearTarget.getDate() +
            '日 '
          );
        }
        if (i <= 0) {
          return '対象範囲外です';
        }
      }
gerritへのgit review時に"no new changes"と出てpushできない

[こちらを読んで解決しました](https://gerrit-review.googlesource.com/Documentation/error-no-new-changes.html)
以下のようにgerritへのgit review時に"no new changes"と出てpushできない場合、

```
$ git review
...
xxx(no new changes)
...
```

かつ、以下にも該当しない場合、

>1.your changes were successfully committed locally (otherwise there is no new commit which can be pushed)
2.you are pushing the correct commit (e.g. if you are pushing HEAD make sure you have locally checked out the correct branch)


既存のcommit IDと重複している可能性がある。

> If you are sure you are pushing the correct commit and you are still getting the "no new changes" error unexpectedly you can take the commit ID and search for the corresponding change in Gerrit. To do this simply paste the commit ID in the Gerrit Web UI into the search field. Details about how to search in Gerrit are explained here.


`git commit --amend`で`commit ID`を更新すれば解決するかもしれない

> If you need to re-push a commit you may rewrite this commit by amending it or doing an interactive git rebase, or see exception. By rewriting the commit you actually create a new commit (with a new commit ID in project scope) which can then be pushed to Gerrit.

# 参考
[https://gerrit-review.googlesource.com/Documentation/error-no-new-changes.html](https://gerrit-review.googlesource.com/Documentation/error-no-new-changes.html)
Ubuntu20.04LTSにsambaをインストール

N番煎じで申し訳ないが何度も間違えるので備忘録。
以下は`/home/ubuntu/Public`にsambaサーバを立てる場合の例です。

環境

```
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
```

sambaをインストール

```
sudo apt install -y samba
```

共有用のディレクトリを作成（今回は、`~/Public`に作成）

```
mkdir -p ~/Public
chmod 777 ~/Public
```

sambaのコンフィグファイルを更新
`sudo nano /etc/samba/smb.conf`などで

```text:/etc/samba/smb.conf
# globalが以下のようになっていることを確認
[global]
   dos charset = CP932
   unix charset = UTF-8
   display charset = UTF-8
   security = user
   map to guest = Bad User
   account = nobody
# Change this to the workgroup/NT-domain name your Samba server will part of
   workgroup = WORKGROUP

# 最後に以下を追加
[Public]
   path = /home/ubuntu/Public
   writable = yes
   guest ok = yes
   guest only = yes
   create mode = 0777
   directory mode = 0777
```

保存した後、sambaサーバを再起動、自動起動設定する。

```
sudo systemctl restart smbd
sudo systemctl enable smbd
```

windowsのファイルエクスプローラにから`\\xxx.xxx.xxx.xxx\Public`を指定して共有できていれば一旦OK

# 参考
[Ubuntu 20.04 でファイルサーバー（NAS）を作ろう！](https://beightlyouch.com/blog/programming/ubuntu-fileserver-nas/#toc1)
[Ubuntu server 18.04Samba 自宅サーバーに Samba(version 4.7.6-Ubuntu)をインストール](http://www.yamamo10.jp/yamamoto/comp/home_server/WEB_server3/samba/index.php)
[ubuntuにsambaを使用してファイルサーバにする。](https://qiita.com/h-ueno2/items/ec0eedf3925f396f0775)
MatlabによるCSVデータを自動読み取り，グラフを自動で特定のファイル形式で保存する．

#初めに
MATLABを用いてCSVファイルを自動で読み取りグラフ化，グラフを特定のフォルダに自動保存する方法を今回まとめようと思う．少しずつ更新していこうと思うので歯抜けの形になってしまうことをお許しください．また，情報が専門ではないので利用している専門用語がめちゃくちゃな部分もあるかもしれません．その点もお許しください．

#データ取得
今回例として利用するcsvファイルを現在探しているところなので具体的な形であまりできていません．先に謝罪しておきたいと思います．時間をうまく見つけて充実した記事にしていきたいとは考えているのでお許しを．．．
データの取得について，まずcsvファイルが保存されているディレクトリを指定する必要がある．また，データを取得する際，パスをつなぎそこからフォルダ内のデータをリスト化して保存すると余分なデータが入るので最後にいらない部分を削除する

```matlab:read_csv.m
% csvファイルが入っているフォルダを入力します
rootname = 'csv';     %%  csvを参照するフォルダを指定する．これが出来上がるグラフの名前の先頭につくので注意
% 検索パスにフォルダを追加します
addpath(rootname) ;                                                         %%　パスをつなぐ
folderInfo=dir(fullfile(rootname));                                         %%　同じフォルダ内のcsvファイルのリスト化
list = folderInfo(~ismember({folderInfo.name}, {'.', '..'}));               %%　必要ないフォルダ.,..を削除する
```

#データからグラフの作製
今回データをプロットし2次元のグラフを書き出したいと思う．そのためにlist化したものからデータをとりそちらから，x軸とy軸のデータをとってくることで最後にplotを用いてグラフ化することができる．凡例や軸などの名前等については今回は特に指定していない．


```matlab:make_graph.m
data1=readmatrix(list(1).name)
x1=data1(:,1);
y1=data1(:,2);
plot(x1,y1);
```

#グラフを特定ファイルに保存する
グラフを特定のディレクトリを指定しそこに保存することができる．これを用いるとどういった点で便利かというと，latexを特に用いる場合シミュレーションなどのデータを簡単に参照することができ，また，シミュレーションデータが変わった場合でも自動でグラフが切り替わるということができる．

～以下編集途中～

mファイルのあるデイレクトリから一個上にあるfigsという名前のフォルダの中に保存できるようになる．

```matlab:auto_save.m
path_fig = '../figs\'; %   保存先を指定(相対パス)
% ファイル名指定
filename='filename_01';
tag = '_tag_'; %   グラフのファイル名に名前を追加できる
filename_fig = [path_fig,rootname,filename,tag];
% fig，epsデータ保存
saveas(fig,filename_fig)            %%  .figで保存
saveas(fig,filename_fig,'jpeg')  
```

# 参考文献
>[matlab ヘルプセンター](https://jp.mathworks.com/help/index.html)
Laravel6.x インストール方法

## 前提
composerはインストール済みであること。
> composerとは,PHPアプリケーションのライブラリ、パッケージの依存関係を管理するツール。

[composerインストール方法](https://mebee.info/2020/01/03/post-5092/)




## 1.composerを使用してLaravel6をインストールする。
```
 composer create-project --prefer-dist laravel/laravel プロジェクト名 "6.*"
```
* crete-project --- composrでプロジェクトを作成
* --prefer-dist --- リリース版、安定版をダウンロードする
* laravel/laravel --- ヘッダー名/パッケージ名
* "6.x" --- バージョンの指定(指定していないと最新バージョンがインストールされる)



## 2..envの設定
```php
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=データベース名
DB_USERNAME=ユーザー名
DB_PASSWORD=パスワード
```

## 3./strageのパーミッションの変更
```
chmod 777 -R storage
```

## 4.bootstrap/cacheのパーミッションの設定
```
chmod -R 777 bootstrap/cache
```


これで__http://[IPアドレス]/[Laravelファイル名]/public__にアクセスするとLaravelのホーム画面が表示できるようになります!!!
ポートフォリオ作成日記＠1日目

行ったこと
・M1　MacbookにRubyとRailsをインストールして、開発環境を構築(https://github.com/osmszk/m1-mac-rails-install)

学んだこと
・1つ1つインストール出来ていることを確認することが大事。
・エラーコードを見てググルことが大事

つまづいた点
・rails newを行った際に、「An error occurred while installing sqlite3 (1.3.13), and Bundler cannot continue.」と表示された。
解決方法：「gem install sqlite3 -v '1.3.13' --source 'https://rubygems.org/'」のコマンド入力
原因：rails6ではsqlite3のgemは1.4以上が必要になるため、SQLite3自体のバージョンが低かった

・VScode上のターミナルで「rails server」を行った際に起動できず、「Please run rails webpacker:install Error: No such file or directory(一部抜粋)」と表示された。
解決方法：「rails webpacker:install」コマンド入力
原因：webpacker がインストールされてなかったため

所感
ポートフォリオ作成に取り掛かり始めようとしたが、
Cloud9を基本学習の時に使用していたので、
PC上での開発環境の構築が意外に時間がかかってしまった。
(M1 Macbookを使用しているという理由もあるが...)

現状、M1Macでしか起こらないエラー等が様々なソフトにあるそうなので、
根気強くググって解決していこうと思います！！

また、本日の開発環境構築によって、
エラーコードをみることに対する毛嫌い感が減少していることを実感した。

以前まではコーディングが一発で上手くいくことに楽しさを感じており、
実行した際にエラーコードが出ると気持ちが萎えてしまっていた。

しかし、エラーコードと向き合ってエラーの原因を解決することが、
基本中の基本だがプログラマーとして一番大事だと改めて再認識できた。

今後もエラーコードと向き合ってエラーの原因を対処し、
「なんか動いているからヨシ！」とならないようにしていこうと思います。
【JavaScript】テキストボックスに「リンク名」と「URL」を入力しボタンをクリックすると、入力されたリンク名とリンク先URLが設定されたa要素を追加するプログラムを作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/db9dc2cf-51f0-e3f3-a362-ad702097ed86.png)

```javascript
<!DOCTYPE html>
  <html lang="ja">
      <head>
          <meta charset="UTF-8">
          <title>8-5 課題</title>
          <script>
          function add_element(){
//-------------リンク名とURLのIDを取得----------------------------------------------------
             var inputText = document.getElementById("txt").value;     //#txtの値を取得 テキストボックスの値
             var inputUrl  = document.getElementById("url").value;     //#urlの値を取得
//-------------------------------------------------------------------------------------
//-------------<a>要素を作成------------------------------------------------------------
             var element_a = document.createElement('a');       
//-------------------------------------------------------------------------------------
             element_a.innerHTML = inputText;   // テキストを指定 txtのid
             element_a.href      = inputUrl;    //<a>タグのURLを指定  urlのid
//-------------output要素のIDを取得----------------------------------------------------
             var output = document.getElementById('output');
//-------------------------------------------------------------------------------------
//-------------output要素にリンクを挿入-------------------------------------------------
             output.appendChild(element_a);   //アペンドチャイルド   aタグがoutputのidの子供の要素として追加
//-------------------------------------------------------------------------------------
          }
//-----------javascriptの開始----------------------------------------------------------
          window.onload = function(){
//-------------addのIDを取得-------------------------------------------------------------
              var add = document.getElementById("add");
//-------------------------------------------------------------------------------------
//---------------リンク追加ボタンを押下することで、イベント発火、add_element関数を実行---------------
              add.addEventListener('click',add_element,false);
//-------------------------------------------------------------------------------------
          }
          </script>
      </head>
      <body>
         <form>
              リンク名:
              <input type="text" id="txt" >
              URL:
              <input type="text" id="url" >
              <button id ="add" type="button" >リンク追加</button> 
         </form>
          <!-- ------------------------------------------------------- -->
          <div>
             <p id="output"></p>
          </div>
      </body>
          <!-- ------------------------------------------------------- -->
  </html>

```
Next.js プロジェクト環境構築

# Next.js プロジェクト環境構築 with typescript , tailwind css

### 環境構築
- **①プロジェクト作成**

```
npx create-next-app プロジェクト名
```

- **②TypeScriptの導入**
 
 つづいて、作成したアプリケーションにTypeScriptを導入していきます。

 まず必要な型定義を取得しましょう。

 ``` 
 yarn add --dev typescript @types/react @types/node
 ```

TypeScriptの導入は、簡単でプロジェクトのルートディレクトリに`tsconfig.json`を作成して、`yarn dev or npm run dev`のコマンドを叩くだけ！

```
// 作成したプロジェクトに移動しましょう。
cd プロジェクト名

// Typescript導入に必要なパッケージを取得
yarn add --dev typescript @types/react @types/node

// tsconfig.jsonを作成して、アプリ起動
touch tsconfig.json

yarn dev
```

`pages/index.js`を`index.tsx`に変更して、`localhost:3000`にアクセスして、問題なく画面が表示されていればTypeScriptの導入は完了です。

- **③Tailwind Cssの導入**

はい。とりあえず、インストールしましょう。

※Next.jsのバージョンによってインストールコマンドが異なるので、自分のバージョンに適応したモノをインストールしましょう。

```
yarn add -D tailwindcss@latest postcss@latest autoprefixer@latest
```

次に、構成ファイルを作成します。

下記コマンドを実行すると、ルートディレクトリに`tailwind.config.js` と `postcss.config.js`が作成されます。

```
npx tailwindcss init -p
```

>To make the development experience as productive as possible, Tailwind generates thousands of utility classes for you, most of which you probably won't actually use.

[公式ドキュメント](https://tailwindcss.com/docs/optimizing-for-production)に、↑のように記載されていますね。

実際は使わないようなモノも多く含んだ状態で大量のクラスを生成して容量が大きいから、不要なものを除外してしまいましょうってことですね。

```
// tailwind.config.js
purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
```

次にTailwindをプロジェクトに適用する方法が２つあって

 - 1.`_app.ts`に直接インポートする方法
 - 2.`globals.css`にTailwindを含める方法


とはいえ、この環境構築では、`.style/global.css`作れていないが、チュートリアルを進めるにあたって作成する予定なので、２つ目の方法で行きたいと思います。

```
/* ./styles/globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
```

```
// pages/_app.js
import '../styles/globals.css'
```
 
以上で、環境構築については終了です。
Python boot camp by Dr.Angela day13

#Debug
以下に示すプログラムのどこが問題なのか指摘していく。

```python3:#Describe_Problem
def my_function():
  for i in range(1, 20):      #1から20まで連番で繰り返す
    if i == 20:               #もしiが20だったら
      print("You got it")     #printする

my_function()                 #my_function()を呼び出す。

#出力結果
何も出力されない
```
__原因>>__ for i in range(4)が0から数えて4回繰り返すことをふまえると、カウント変数は0ベース（0オリジン）でカウントされると分かる。range(開始数, 終了数)という書き方で、range(1, 20)と書くことで添え字(index)が1番(=1)から19番(=19)までの19個のオブジェクトを生成するので、i=20になることはありえないため、printされない。
__解決策>>__ L2→ for i in range(1,21)にする

[参考] 
https://techacademy.jp/magazine/15828
https://naruport.com/blog/2019/8/14/python-tutorial-for-statement-and-range/

```python3:#Reproduce_the_Bug
from random import randint
dice_imgs = ["❶", "❷", "❸", "❹", "❺", "❻"]
dice_num = randint(1, 6)
print(dice_imgs[dice_num])

#出力結果 (何回かrunするうちにたまにこうなる)
Traceback (most recent call last):
  File "main.py", line 14, in <module>
    print(dice_imgs[dice_num])
IndexError: list index out of range
```
__原因__>> L3でdice_num = randint(1,6)にしているが、dice_imgsには①(index:0)～⑥(index:5)しかなく、仮にdice_num=6が選ばれてしまったらout of rangeになるのでErrorになる。さらに、index:0 (つまり"①")が出力されなくなっている。Errorにならない場合、出力される数としては②～⑥になっている。
__解決策__>> dice_num = randint(0,5)とする

```python3:#Play_Computer
year = int(input("What's your year of birth?"))
if year > 1980 and year < 1994:
  print("You are a millenial.")
elif year > 1994:
  print("You are a Gen Z.")

#出力結果
What's your year of birth?1979
>                              
```
__原因>>__ 1980年～1994年より前,1994年以降で場合分けをしているので、1994年丁度に生まれた人と1980年以前に生まれた人に対しては何のアクションも示さず、突然プログラム終了となっている。
__解決策>>__ どちらかの「>,<」に等号(=)をつけるのと、else: でそれ以外の場合にどうするかを追記する

```python3:#Print_is_Your_Friend
1   pages = 0
2   word_per_page = 0
3   pages = int(input("Number of pages: "))
4   word_per_page == int(input("Number of words per page: "))
5   total_words = pages * word_per_page
6   print(total_words)

#出力結果
Number of pages: 2
Number of words per page: 89
0
```
__原因>>__ L4→ 「==」になっていることで、左辺と右辺が等しいかどうかを見て、True or Falseを返している。runする中でこれは実際に何の影響も及ぼしていない(ただ0を入れない限りFalseがreturnされているだけ)が、word_per_pageには入力値が渡されていないのでL2で定義したままのword_per_page=0であるため常にtotal=0になっている。
__解決策>>__ L4「==」を「=」に直す 

```python3:#Use_a_Debugger
1   def mutate(a_list):
2     b_list = []
3     for item in a_list:
4       new_item = item * 2
5     b_list.append(new_item)
6     print(b_list)

mutate([1,2,3,5,8,13])

#出力内容
[26]
```
__原因>>__ L5→ b_list.appendがfor文の外にあることで、L3&L4で2倍にしたnew_itemが全くb_listに追加されず、最後にnew_itemに格納された26だけがL5のnew_itemに渡されてappendされているため、常に[26]のみが出力されている。本当はa_listの各項目をそれぞれ2倍した値をb_listに格納したいのだろう。
__解決策>>__ L5→ インデントをfor文と揃えて、for文で毎回appendを回すようにする

続きはまた明日...
【Nuxt.js】ハンバーガーボタンとグロナビを実装する2

[こちらの記事](https://qiita.com/MasayukiAbe/items/c4ed2d788fbd80b85506 "【Nuxt.js】ハンバーガーボタンとグロナビを実装する")の続き
ハンバーガーボタンクリックでそこそこいい感じにグローバルナビを
表示する実装ができたと思ったらPC閲覧時に全然だめだったので
どうにかしなければならないということ。

#問題
グローバルナビがPCだと表示されない

#原因
`components/organisms/HtmlHeader.vue`で、
`gnaviOn`がtrueかfalseかで表示非表示を制御しているため、
そもそもハンバーガーボタンを表示していないPC版では
グロナビを表示させる手段がない

#解決策
表示させる条件を、

- gnaviOnがtrueのとき
- スマホじゃないとき

の2つが揃ったときに変更する（してはどうだろうか）

ということで、調べてみると、すごくわかりやすくまとめて
くれている人がいた。

https://mykii.blog/nuxt-hamburger-menu/

最初からここに書いてあるとおりにやっていればよかった。
と思ったけれど、まずは自分で考えたことに意味があると言い聞かせつつ、
~~コピペ~~ 参考にして`components/organisms/HtmlHeader.vue`を
修正していく。


##HtmlHeader.vue

```components/organisms/HtmlHeader.vue
<template>
  <header id="l-header">
    <div class="l-header_inner">
      <h1>Header</h1>
      <BtnHamburger
        :class="{active : gnaviOn}"
        @btnMenu="toggleMenu"
      />
    </div>
    <transition
      @before-enter="beforeEnter"
      @enter="enter"
      @before-leave="beforeLeave"
      @leave="leave"
    >
      <nav
        v-if="gnaviOn || !isMobile"
        class="gnavi"
      >
        <LstNavi />
      </nav>
    </transition>
  </header>
</template>

<script>
import BtnHamburger from '@/components/atoms/buttons/Hamburger'
import LstNavi from '@/components/molecules/lists/NaviList'
export default {
  components: {
    BtnHamburger,
    LstNavi
  },
  data () {
    return {
      gnaviOn: false,
      wWidth: 1025
    }
  },
  computed: {
    isMobile () {
      return this.wWidth < 1024
    }
  },
  mounted () {
    this.wWidth = window.innerWidth
    this.$nextTick(() => {
      window.addEventListener('resize', () => {
        this.wWidth = window.innerWidth
      })
    })
  },
  methods: {
    toggleMenu () {
      this.gnaviOn = !this.gnaviOn
    },
    beforeEnter (el) {
      el.style.height = '0'
    },
    enter (el) {
      el.style.height = el.scrollHeight + 'px'
    },
    beforeLeave (el) {
      el.style.height = el.scrollHeight + 'px'
    },
    leave (el) {
      el.style.height = '0'
    }
  }
}
</script>
```

- `v-if="gnaviOn || !isMobile"`に条件を変更
- dataでwWidthをreturn
- computedでisMobileを設定
- mountedでウィンドウの横幅を取得（リサイズ時にも対応してる）、wWidthに代入

##結果
これでばっちりPCでもグロナビが表示されるようになった。
いいね！

と、思ったものの、作業を進めていくうちに別の問題が発生した。
やっぱりいろいろ難しい……。
【Laravel】【備忘録】リソースコントローラーを使ってみよう

Laravelのリソースコントローラについてのメモです。

#リソースコントローラーとは？

データの追加、読み取り、更新、削除について決まりきった処理を簡潔にできる機能です。

#使い方

以下のコマンドを実行します。

```php:ターミナル
php artisan make:controller ArticleController --resource
````

上記のArticleControllerは例ですので、任意で指定してあげてくださいね！

実行すると以下が作成されると思います。

```php
app
┣ http
 ┣ Controllers
  ┣ ArticleController
```
中身を見てみましょう！

```php:ArticleController
<?php

namespace App\Http\Controllers;

use App\Article;
use Illuminate\Http\Request;

class ArticleController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Article  $article
     * @return \Illuminate\Http\Response
     */
    public function show(Article $article)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Article  $article
     * @return \Illuminate\Http\Response
     */
    public function edit(Article $article)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Article  $article
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Article $article)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Article  $article
     * @return \Illuminate\Http\Response
     */
    public function destroy(Article $article)
    {
        //
    }
}
```

できました！
syslog-ng とは

## 勉強前イメージ

syslogの改善版？
rsyslogとの違いはなんだろう

## 調査

### syslog-ng とは

syslog-next generation の略で、
GPL(GNU General Public License)で利用できるオープンソースのソフトウェアです。
syslogの問題点を改良したsyslogデーモンになります。

### syslog-ng の主な特徴

- ログの出力が詳細に制御できる

フォルター機能で、ファシリティやプライオリティ、
またアプリケーション名などでも出力先の変更が可能

- syslog-ngサービスをroot以外で起動可能

syslogではrootでしか稼働できなかったが、
syslog-ngではroot以外でも動作可能

- ネットワーク転送はTCPとUDPを使用可能

syslogではUDPでポート番号は固定だったが、
TCPも使用でき、ポートも任意に指定が可能

- 設定ファイルはsyslogと互換性がない

設定ファイルの書式がsyslogと異なるので互換性がありません

## 勉強後イメージ

syslog → syslog-ng → rsyslog のイメージだったけど、
syslogの改良版がsyslog-ng と rsyslogだったのね。
別物か。。。

## 参考

- [syslogとrsyslog、syslog-ngの挙動の違いをまとめた](https://webnewage.com/syslog)
- [syslogdの限界と次世代シスログデーモン](https://www.atmarkit.co.jp/ait/articles/0807/15/news131_3.html)
- [安全性の高いログ・サーバへの乗り換えのススメ（1）～ syslogサーバからsyslog-ngへの乗り換え ～](https://www.atmarkit.co.jp/ait/articles/0403/27/news018.html)
Tips: heroku deploy時にCloudflareのキャッシュをpurgeする

## これは何
herokuで運営しているサービスでCloudflareを使っている場合、デプロイ後にキャッシュをpurgeする必要がある場合は多いと思います。
キャッシュを削除したい際に、毎回手動でやるのではなく、APIを用いてheroku deploy時に自動でpurgeされるようにする方法を記事にしたものです。

## 削除APIを実行するためのシェルスクリプトを用意するスクリプトを用意する
はじめにCloudflareのAPIを用いた削除用のスクリプトを用意します。
トークンなどの発行方法は

https://qiita.com/yousan/items/a62336f903a2ab512976

が参考になると思います。

作成するシェルスクリプトは以下のようなものです。

```sh:purge.sh
curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/purge_cache" \
-H "X-Auth-Email: ${EMAIL}" \
-H "X-Auth-Key: ${API_KEY}" \
-H "Content-Type: application/json" \
--data '{"purge_everything":true}'

```
今回は全てのキャッシュを削除する設定にしています。
特定のファイルのキャッシュのみ削除する場合は

https://qiita.com/yousan/items/a62336f903a2ab512976#%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%81%AE%E5%89%8A%E9%99%A4

を参照してスクリプトを変更してみてください。


## herokuデプロイ時に作成したスクリプトを実行する
herokuではrelease phaseという機能を用いることで、デプロイ時に実行するコマンドを指定することができます。これを用いて作成したスクリプトをデプロイ時に実行するようにします。

https://devcenter.heroku.com/ja/articles/release-phase

release時に実行するコマンドはレポジトリのrootディレクトリに`Procfile`を配置し、そのProcfileを用いることで設定することができます。

```Procfile
release: bash purge.sh
```

これによって、herokuデプロイ時に自動でCloudflareのキャッシュをpurgeすることができるようになります。
UNION ALL

# UNION ALLとは
クエリの結果を一緒にするために使う。

# 具体例
## データ
こういうデータがあったとする。

```bash
+----+------+------+------+
| id | x    | y    | z    |
+----+------+------+------+
|  1 |    1 |    2 |    3 |
|  2 |    5 |    5 |    2 |
|  3 |    4 |    7 |    1 |
|  4 |    3 |    3 |    8 |
+----+------+------+------+
```

## SQL発行
idと（x,y,z）カラムをtablesテーブルからSELECTする。

```sql
SELECT id, x AS value FROM tables
UNION ALL
SELECT id, y AS value FROM tables
UNION ALL
SELECT id, z AS value FROM tables
```

## クエリ結果
３つのSELECTの結果がくっついてることがわかる。

```bash
+----+------+
| id | col  |
+----+------+
|  1 |    1 |
|  2 |    5 |
|  3 |    4 |
|  4 |    3 |
|  1 |    2 |
|  2 |    5 |
|  3 |    7 |
|  4 |    3 |
|  1 |    3 |
|  2 |    2 |
|  3 |    1 |
|  4 |    8 |
+----+------+
```

# 周辺
## UNIONとUNION ALLの違い
### 挙動
UNIONは重複しているものが削除されます。
以下、UNIONで発行した結果ですが、（id, col）の組み合わせで重複しているものが排除されています。

```bash
+----+------+
| id | col  |
+----+------+
|  1 |    1 |
|  2 |    5 |
|  3 |    4 |
|  4 |    3 |
|  1 |    2 |
|  3 |    7 |
|  1 |    3 |
|  2 |    2 |
|  3 |    1 |
|  4 |    8 |
+----+------+
```


### パフォーマンス

ユニークである挙動を持っているため、UNIONの方が重いらしいです。

# 注意点
上の例だと、x,y,zはいずれも整数型であり揃ってますね:+1:
同じテーブルの似たようなカラムなので条件は満たしていそうです。
なお、型に関しては暗黙的に変換できるものなら大丈夫だそう。
備忘録 Goでginを使う時に、cssやjsのファイルが読み込めない問題の解決

# 書いた理由
go言語でginを使っていたら、htmlからjsが読み込めない問題が発生したので、忘れないようにメモっておきます。また、ginを使わない場合でも同様の操作が必要らしいです。
cssの読み込みも同様にやるので、省略します。

## ディレクトリについて

[github](https://github.com/suzakutakumi/gin-staticJS)に今回のコードはおいてあります。
`correct.go`が正常に動作するプログラムで、`incorrect.go`が正常に動作しないプログラムです。

```
./
├── correct.go
├── incorrect.go
└── src
    ├── index.html
    └── js
        └── main.js
```

## htmlとjs

ボタンを押すと、alertで`Pushed!!`と出るだけの簡単なプログラムです。

```html:index.html
<html>
  <head>
    <title>gin-js</title>
    <script defer="defer" src="./js/main.js" ></script>
  </head>
  <body>
      <button id="btn">Push!!</button>
  </body>
</html>

```

```javascript:main.js
document.getElementById("btn").onclick=function(){
    alert("Pushed!!")
}
```

## 失敗するプログラム

`/`に接続すると、`index.html`が表示されるいたって簡単なプログラムです。

```go:incorrect.go
package main

import "github.com/gin-gonic/gin"

func main() {
	router := gin.Default()
	router.LoadHTMLGlob("src/*.html")
	router.GET("/", func(ctx *gin.Context) {
		ctx.HTML(200, "index.html", gin.H{})
	})
	router.Run()
}

```

実行すると`/js/main.js`にGETリクエストをして、`404`が返ってきています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467463/520bb136-d11e-2661-606d-780cf2349ba1.png)

## 成功するプログラム

```go:correct.go
package main

import "github.com/gin-gonic/gin"

func main() {
	router := gin.Default()
	router.Static("/js", "src/js/") // ここを追加するだけ!
	// router.Static("HTMLで読み込むURL","読み込むファイルがあるディレクトリの場所")
	router.LoadHTMLGlob("src/*.html")
	router.GET("/", func(ctx *gin.Context) {
		ctx.HTML(200, "index.html", gin.H{})
	})
	router.Run()
}
```

実行すると`/js/main.js`にGETリクエストをして、`200`が返ってきて成功しています!
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467463/9448120d-4169-e691-9a2c-0f3104b50e9f.png)

静的なファイルにはこのメソッドを使用するらしいです。(詳しくは自分で調べて...)
`router.Static("HTMLで読み込むURL","読み込むファイルがあるディレクトリの場所")`

## 最後に

調べても全然出てこなく、30分ぐらいかかったので備忘録&周知のために記事を書きました。
誰かの役に立ったら幸いです。

[今回のリポジトリ](https://github.com/suzakutakumi/gin-staticJS)
【初心者でもわかる】マウス操作だけで動きをつけたり見た目が変わるHTML、CSSたち

#どうも7noteです。JavaScriptを使わなくてもマウス操作だけで見た目に動きをつけたり変化ができるHTML・CSSについて。

HTMLやCSSの中には、マウス操作によって見た目を変える方法がいくつかあります。

JavaScriptを使ってCSSを変更したり、クラスを付与して変化をつけなくても、HTML、CSSだけでこれだけできるんだっていうのを共有できたらと思います。


## マウス操作で変化するHTML・cssたち。

### 「マウスホバー(:hover)」

```style.css
a:hover {
  text-decoration: none;
}
```

![sample01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/c5fa6d50-9c7c-8c84-1838-aca13a3c21e0.gif)

---

### 「フォーカス(:focus)」

```style.css
input[type="text"]:focus {
  background: #fcc;
}
```

![sample02.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/3f30e29a-62d8-b52e-a132-c9a7287d3a47.gif)

---

### 「チェック(:checked)」

```style.css
input[type="checkbox"] {
  display: none;
}

input[type="checkbox"] + span {
  position: relative;
}

input[type="checkbox"] + span::before {
  content: '□';
}

input[type="checkbox"]:checked + span::after {
  content: '✓';
  color: #f00;
  position: absolute;
  left: 0;
  bottom: -2px;
}
```

![sample03.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/b6c8e241-2c6e-5b9e-6605-cd29267728d0.gif)


---

### 「details &  summary」

```index.html
<details>
  <summary>みだし</summary>
  内容内容<br>内容内容
</details>
```

![sample04.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/6e1c6c25-97b9-2392-4a84-5804d2d0ffb8.gif)

---

### 「#idでスクロール」

```index.html
<div><a href="#hogehoge">ほげほげへ移動</a></div>
<div id="fugefuge">ふがふが</div>
<div id="hogehoge">ほげほげ</div>
```

![sample05.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/f1caef9a-5113-18fb-c758-c3dbb2b0b9a3.gif)


## まとめ

JavaScriptを使わなくても、簡易的な動きをつけるだけならHTML・CSSだけでも十分可能です。

とくに:checkedを使ったチェックボックスの方法は自由度が高いので、覚えておくと使えるタイミングがあるかなと思います。
他にもあるような気がするので、思いつき次第追記していきます。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
Vimでタブをスペースに変換

vimを使用する際にタブ↔︎スペースの変換が一度にできるコマンドがあったのでメモ

### タブ→スペース
```
:set expandtab
:retab 4(スペースの数)
```


### スペース→タブ

```
:set noexpandtab
:retab! 4(スペースの数)
```
WSLからwindowsのファイルをみるのに便利・ディレクトリに別名【zsh】

# お悩み

windows側のファイルを触りたいことがあるけど、`/mnt/c/Users/USERNAME`にいちいち移動するのめんどくさい！

例えば、windowsでダウンロードしたファイルをwsl側のhomeに移動したいとか。

# 解決
以下の設定で、ディレクトリに別名をつけることができます。`~別名`でアクセスできる。

```zsh:.zshrc
hash -d w=/mnt/c/Users/USERNAME
```

```shell
$ cp ~w/Downloads/hoge.txt ~/workdir
```

サイコ～
そう、zshならね。

# 参考文献
本記事には何らの新規性もなくすべて以下の記事から引用です（すみません&感謝！！）
WSLを使うときに特に役に立つな！　と思ったのでタイトルを変えて再掲ということです。

[よく使うディレクトリに別名をつける](https://qiita.com/usamik26/items/18591c9f870fcdd0d003)

WSLerの皆様に刺されば幸いです。
flutter road #1 初期アプリの概観

youtubeに解説動画をアップロードしています。

https://youtu.be/cA8TNO8EfaY

初期アプリをおおまかに説明します。


```dart:main.dart
// flutterの材料の輸入
import 'package:flutter/material.dart';

// MyAppのアプリを起動
void main() {
  runApp(MyApp());
}

// MyAppの説明
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // ここを変えるとアプリの色が変わる（green➡red, blueとか、知ってる色を試してみて）
        primarySwatch: Colors.green,
      ),
      // 上のタイトル　''で囲まれたところが表示される
      home: MyHomePage(title: 'こんにちは'),
    );
  }
}

// MyHomePageの説明
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

// _MyHomePageStateの説明
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // アプリ上部のバー（色がついているところ）
      appBar: AppBar(
        // widget.titleというのは、上のclass MyAppの中に書いてあることを読み込んでいる
        title: Text(widget.title),
      ),
      // AppBar以外のアプリの中身
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

```


追加で、色がついていてわかりやすいのでスクショを貼っておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1335172/be41c7c2-a824-789c-ee21-33cebb8a1790.png)

最初なので、スクショにある primarySwatch: Colors.green, の部分とhome: MyHomePage(title: 'こんにちは'),の部分を少し変えてみてください。エミュレーターかスマホの端末をUSBでつないで　Ctrl＋S（保存）を押すと見た目が変わると思います。

今後は新しい機能を追加したり、Widgetを解説する記事も書こうと思います。
Hasuraでの「Error: field "XXX" not found in type: 'XXX'」エラー

Hasuraにおける「Error: field "XXX" not found in type: 'XXX'」というエラーについて
開発する中でHasura APIに対してリクエストを投げる際に何度か出てきたので
被疑箇所をメモとして残しておきます。
データフェッチにはApolloを使用しています。

# エラー発生状況
以下のようなqueryを実行しました。

```js
gql`
  query GetRecentPost {
    posts(limit: 10, order_by: { id: asc }) {
      id
      image
      gender
      content
      created_at
      user {
        id
        display_id
        image
        name
      }
      comments_aggregate {
        aggregate {
          count(columns: id)
        }
      }
      likes_aggregate {
        aggregate {
          count(columns: id)
        }
      }
    }
  }
`
```

GraphQLに関しても使い始めて日が浅い為、query内容に冗長なところが
あるかもしれませんが何卒ご了承ください。

ユーザの最近の投稿10件を取得し、それを投稿したユーザと
その投稿についているコメントといいねの件数を取得するものです。

このqueryを投げたところ以下のエラーが出ました。
`Error: field "comments_aggregate" not found in type: 'posts'`
postsフィールドの中にcomments_aggregateが存在していないようです。

# 解決方法
Hasuraで定義したテーブルに対するPermissionの設定が原因でした。
今回のエラー文にある`comments_aggregate`は
`posts`テーブルに紐づく`comments`テーブルの件数を集計するqueryで
テーブルを作成した時点でHasura側が勝手に用意してくれるものです。

しかしこの集計queryにはデフォルトでPermissionがadmin以外disableになっていました。
以下は`posts`テーブルと`users`テーブルの中間テーブルで投稿へのコメントを表す
`post_comments`テーブルのPermissionsタブの中身です。
(Hasura Console→DATA→テーブル の中にあります)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682983/a3ac4468-3e4c-297f-73f1-f372be705dbd.png)

こちらの`Aggregation queries permissions`の Allow role [role] to make aggregation queries
というチェックボックスにチェックを入れることでエラーが解消されました。
（ユースケースによって適切なRoleに対して設定してください）
(likesのテーブルに関しても同様に設定しました。)


# さいごに
Hasuraにおいてこのようなエラーが出た場合、今回の内容でなくとも
自分の場合は適切な権限がRequestのRoleに付与されていなかったというケースがほとんどでした。
同じようなエラーが出た方で、ここら辺の確認が漏れている場合は
確認してみると良いのでは無いでしょうか。
0からはじめるChrome拡張開発1

私は、仕事でExcelVBAとか使うぐらいでしたが、Chromeも使うことが多いので
Chrome側で仕事を便利にできるようなものを作ろうと拡張機能に手を出し始めているところ
自分の勉強がてら記事作成していこうかと思います。


必要なもの
-
・Google Chrome
・Visual Studio Code(メモ帳でも可）

最小構成を作る。
-
適当なフォルダを作成して、フォルダ内に以下のファイル名でファイルを作成する。

```
manifest.json

{
    "manifest_version": 2,
    "name": "拡張機能サンプル",
    "version": "0.0.1",
    "description": "最小構成"
}
```

拡張機能のインストール
-
1. Google Chromeのアドレスバーに、「chrome://extensions」と入力する。
（オプションから「その他のツール」＞「拡張機能」でも良い)
![2021-05-12 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46615/6c0b42fa-9395-7a4b-4c70-b23069b43f88.png)

2. デベロッパーモードのスイッチをON。
![2021-05-12 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46615/ae5f5bfc-6ff5-4788-9410-f13a289d0687.png)

3. 作成したフォルダごと画面に投げ込む。

4. エラーが出なければ、インストール完了。

おわりに
-
全く何もしない拡張機能ではあるが、最初の一歩はここからがいいと思います。
Javascriptに慣れていない人・Chrome上でのデバッグに慣れていない人が
Web上にあるチュートリアルっぽいやつをやると意外とひっかかることもあり（自分がそうでした）
ちゃんと動くやつを少しずつ変えていくと、詰まったところがわかりやすいと思います。

次は、Web上によくあるハローワールド的なものに行こうかなと思います。

続きはこちらで書いています→https://www.new-normal-skill.com/
【Vim】文字を置換したいときにはsedのような形式にコマンドする。


内部Tipに書いていたどこっちに書いていなかったのでメモ

sedコマンドを使わずに、そのまま使う

`s/[置換したい文字]/[置換する文字]`

参考
https://vim.blue/vim-replace-all-string/
【Python】logging の設定ファイル

# はじめに

python を使うおじさんですが、未だにlogging の使い方がこなれていない。
おじさんは

1. モジュールとそれを呼び出すモジュールとで、両方に logger を設定して使いたい
1. 出力の設定はまとめておきたい

をしたいのだが、できていません。今回、設定をファイルから読み込むことで、少し進展しそうです。ので、メモ。


# Configuration file を読む

設定ファイルは、logging.config.dictConfig() で読むことができます。


## 動作例

同じディレクトリに設定ファイルを置いてあります。

```
.
├── logging.yaml
└── main.py
```

### 設定ファイル

まず、設定ファイルの方です。最初は、最後の行にある ```disable_existing_loggers: False``` が無くて動きませんでした。大事です。

```YAML:logging.yaml
version: 1
formatters:
  simple_fmt:
    format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
  console:
    class: logging.StreamHandler
    level: INFO
    formatter: simple_fmt
    stream: ext://sys.stdout
  console_AAA:
    class: logging.StreamHandler
    level: DEBUG
    formatter: simple_fmt
    stream: ext://sys.stdout
loggers:
  AAA:
    level: DEBUG
    handlers: [console_AAA]
    propagate: no
root:
  level: DEBUG
  handlers: [console]
disable_existing_loggers: False
```

当然ながら、yamlファイルがきちんと書かれちないとload するときにエラーが出ます。class AAA では debug level で出力するようにしています。dictConfig() に渡される辞書については、下記に書かれています。version, formatters, handlers などのキーが必要です。

https://docs.python.org/ja/3/library/logging.config.html#dictionary-schema-details

### 動作例

以下のプログラムを動かしてみます。

```python:main.py
from logging import getLogger,config
import yaml

logger = getLogger(__name__)

class AAA(object):
    def __init__(self):
        self.logger = getLogger(self.__class__.__name__)
        self.logger.debug("class name is {}".format(self.__class__.__name__))
    def do_something(self):
        self.logger.info("doing something")

def main():
    aaa = AAA()
    aaa.do_something()

    logger.debug('debug message')
    logger.info('info message')
    logger.warning('warn message')
    logger.error('error message')
    logger.critical('critical message')

if __name__ == "__main__":
    config.dictConfig( yaml.load(open("logging1.yaml").read(), Loader=yaml.SafeLoader) )
    main()
```

動かすと、class AAA にある logger では debug levelで出力されますが、main() なかでは info レベルです。

```
$ python main_yaml.py
2021-05-11 21:41:16,663 - AAA - DEBUG - class name is AAA
2021-05-11 21:41:16,663 - AAA - INFO - doing something
2021-05-11 21:41:16,664 - __main__ - INFO - info message
2021-05-11 21:41:16,664 - __main__ - WARNING - warn message
2021-05-11 21:41:16,664 - __main__ - ERROR - error message
2021-05-11 21:41:16,664 - __main__ - CRITICAL - critical message
```

### まとめ

とりあえず動いた。もう少し調べてもよいかなと思うのは、

- Formatter の使いこなし。。。
- 設定ファイルの書き方。Loggerのドキュメントに書かれていますが、json や独自形式？の .conf でも読むことができるようです。
https://docs.python.org/ja/3/howto/logging.html
- 別ファイルにあるlogger を出力する（本当はこれを確認したい）

(2021/05/11)
【Rails】ユーザー管理機能をDeviseを使って実装する方法

１: Gemのインストール

``````ruby:Gemfile
# 最下部に追記
gem 'devise'
```
 
```terminal:ﾀｰﾐﾅﾙ
% bundle install

# 再起動
control + C
rails s
```
２: deviseの設定ファイルを作成

```terminal:ﾀｰﾐﾅﾙ
% rails g devise:install
```

３: userモデルを生成

```terminal:ﾀｰﾐﾅﾙ
% rails g devise user
```
4: マイグレーションの実行

```
#db/migrate/20XXXXXXXXX_devise_create_users.rb　に記述

# マイグレーションを実行
% rails db:migrate

# usersテーブルを確認

# ﾀｰﾐﾅﾙにて
再起動
control + C
rails s

# localhost:3000　で確認
```

5: deviseのビューを作成

```terminal:ﾀｰﾐﾅﾙ
rails g devise:views

#　ログイン画面・サインアップ画面を編集
```

以上がdeviseを使ってユーザー管理機能を実装する方法でした！
Windows10 Pro の Windows PowerShell コンソールでdockerコンテナ操作時にBackspaceキーを押すと発生する音を消す

### 実現したいこと

Windows10 Pro の Windows PowerShell コンソールで　dockerコンテナ操作時にBackspaceキーを押すと私にとって不快な音が発生する。(発生する音が心地よい方にはあまり関係ない)
不快な音を発生させないようにしたい。

![01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49795/9ce2b0d3-0523-e194-0494-c13e6ac879d3.png)

これは、Windows Terminalでも発生する。

![02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49795/36e494d5-9529-474b-da75-4a81354029a5.png)


### 一番簡単な解決方法：パターン1

* 解決方法がたくさんあるが、簡単な方法はこれだった。

1. VSCode(Visual Stdio Code)をインストール
1. VSCodeを起動する
1. VSCodeのターミナルを開く
    * ショートカットキーで [Ctrl] + [Shift] + [@] でも開ける
1. VScodeのターミナルで操作する

![03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49795/ac9c20a8-898c-8f87-22eb-13bafe5aacde.png)

### 一番簡単な解決方法：パターン2

* スピーカーをOFFにする。
* 言われるまでもなく、あまり良い解決方法ではない。

### 情報源

* 思い付きでVScodeで試したところ、解決に至った。

### 注意

* ただしExtentionや、設定には注意
キーボードが出現するタイミングでTextFieldをずらすコードの書き方[Xcode/Storyboard]

Xcode/Storyboardで、キーボード出現時にTextFieldが隠れないようにずらす方法をアウトプットします。

![Unknown.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864623/841814dc-cc6a-e7b4-09cb-668bb0a492a5.gif)

#環境
・Mac Book Pro(macOS:BigSur)
・Xcode(ver:12.5)

#コード

```ruby:ViewController.swift
  class ViewController: UIViewController {
    
    @IBOutlet weak var textField: UITextField!
    @IBOutlet weak var button: UIButton!
    
    var screenSize = UIScreen.main.bounds.size
    
    override func viewDidLoad() {
        
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_ :)), name:UIResponder.keyboardWillShowNotification, object: nil)
        
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    @objc func keyboardWillShow(_ notification:NSNotification){
        
        let keyboardHeight = ((notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as Any)as AnyObject).cgRectValue?.height
        
        textField.frame.origin.y = screenSize.height - keyboardHeight! - textField.frame.size.height
        
        button.frame.origin.y = screenSize.height - keyboardHeight! - button.frame.size.height
    }
    
    @objc func keyboardWillHide(_ notification:NSNotification){
        
        textField.frame.origin.y = screenSize.height - textField.frame.size.height
        
        button.frame.origin.y = screenSize.height - button.frame.size.height
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        textField.resignFirstResponder()
    }
}
```

#解説
「var screenSize = UIScreen.main.bounds.size」は、画面の大きさを指しています。
「 NotificationCenter.default.addObserver」を使って、キーボードが出てくるタイミングや隠れるタイミングを監視します。
「keyboardWillShowNotification」は、キーボード出現時、
「keyboardWillHideNotification」は、キーボードが隠れる場合を監視するときに使います。
上記のタイミングが訪れたときに、selectorで設定したメソッドが呼ばれます。
上記のコードの場合だと、「keyboardWillShow」・「keyboardWillHide」になります。
キーボードが出てくるときに、TextFieldを上にあげる処理が必要になります。
それが、「keyboardWillShow」の中身の処理になります。
今回の場合だと、TextFieldとButtonのy座標を画面の高さからキーボードと各パーツの高さを引きます。
逆にキーボードが下に下がるときに、元に戻す処理が必要になります。
それが、「keyboardWillHide」の中身の処理になります。
画面の高さから各パーツの高さを引くことで下の位置に下がります。

以上となります。
自己紹介

# 学歴・職歴
私立大学理工学部　中途退学（成績不振のため）
鉄道系専門学校　卒業（首席）
その後、鉄道会社の駅務に携わるも接客が精神的につらくなり体調不良で退職
現在はある会社のシステム部門でVBAを用いたシステム開発・改修に従事

# 趣味
・旅行
・勉強（最近はプログラミングも）
・ゲーム
・YouTube

自分って意外と勉強好きなんだなぁって最近改めて実感しました。

# 取得してきた資格
・TOEIC 615
・総合旅行業務取扱管理者資格（←頑張った！）
他多数

# スキル
・VBA(実務)
・HTML
・CSS
・JavaScript
・Ruby

# 最後に
まだまだ未熟者ですがよろしくお願いします
React-Nativeの開発環境を整える


初心者がreact-nativeでandroidアプリを作っていく過程を綴っていきます。
アプリの開発にあたって@YutamaKotaroさんのQiitaの記事を参考にさせていただきました。
https://qiita.com/YutamaKotaro/items/dd7846c6db15e2307daa


###1-1. node
nodeが必要らしいのでインストールされているか確認。

```
$ node -v
v13.13.0
```
すでにインストールされていました:smile:

###1-2. watchman
ファイル変更監視ツールです、インストールすれば便利になるらしい...:frowning:
とりあえずbrewでインストールします。

```
$ brew install watchman
```

###1-3. react-native-cli
React Nativeでの開発を手軽にする開発ツールらしいです...:frowning:
npmでインストールします。

```
$ npm install -g react-native-cli
```

###1-4. プロジェクトを作成
ひとまず開発の準備はできているっぽいので、プロジェクトを作成していきます。

```
$ react-native init sample
```

これでプロジェクトは完成しました:relieved:

##2. ターミナルからAndroidのエミュレータを実行
次にターミナルからAndroidのエミュレータを実行できるようにします。

###2-1. Android Studioのインストール
Android Studioの公式サイトでインストールします。
https://developer.android.com/studio/?hl=ja 

###2-2. Android Studioでエミュレータを使えるように設定します
このサイトが参考になりました。
https://techacademy.jp/magazine/2396

次にPATHを通すために.bash_profileに以下を追加します。

```:.bash_profile
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
```

これでターミナルからエミュレータが起動できるようになったはずです:relieved:
早速ターミナルから実行します。

```
$ react-native run-android
```

<img width="327" alt="スクリーンショット 2020-05-23 14.38.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333161/de996211-bdb4-90a6-f131-63a2e1a93b6d.png">

実行できました:joy:
【FileMaker】SendGrid経由でメールを送る 添付ファイル編

さて、SendGridでメールを送る[準備編](https://qiita.com/tyuma/items/42b415fb9c515ff1b0d8)、[テキストメール編](https://qiita.com/tyuma/items/778b94db943b0e3ba713)を経て、今回はファイルをメールに添付して送る話です。
FileMakerのバージョン等は、[準備編](https://qiita.com/tyuma/items/42b415fb9c515ff1b0d8)の記事を参考にしてください。

# テーブル設計
今回もテスト用ですがテーブルにオブジェクトフィールドを設定しました。
通常の運用だと、ここに請求書のpdfや管理している画像などが入る感じでしょうか？
計算フィールドで[Base64EncodeRFC](https://help.claris.com/ja/pro-help/content/base64encoderfc.html)を使ってオブジェクトをテキストにしていますが、データサイズが増えてしまうのでメールに添付するだけでしたらスクリプトなどで処理中に変換するだけでいいと思います。
Base64EncodeRFCで指定する4648は、エンコードしたデータに改行コードを付けない、という意味です。
改行コードありの指定をしてしまうと、ある一定の間隔(RFC番号ごとに決まっている間隔)で改行コードが入ってしまい、復元できなくなってしまいますので、注意してください。
![スクリーンショット 2021-05-11 20.35.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/3a1992c4-1df3-6611-5e2c-974373dceb71.png)

# SendGrid APIの確認
[SendGrid API](https://sendgrid.com/docs/api-reference/)では、attachmentsというキーを配列で指定します。
contentとfilenameが必須項目です。
contentは、Base64EncodeRFCでエンコードしたテキストを設定します。
filenameは[GetContainerAttribute](https://help.claris.com/ja/pro-help/content/getcontainerattribute.html)で取得できます。
![スクリーンショット 2021-05-11 20.43.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/5c580522-47d7-d1e7-2def-b0f6bff6d000.png)

# スクリプトの確認
基本的なスクリプトは、[テキストメール編](https://qiita.com/tyuma/items/778b94db943b0e3ba713)を参考にしてください。
今回追加したのは、attachmentsキーの部分になります。
当然ですが、attachmentsキーは配列なので複数のファイルを設定できます。
![スクリーンショット 2021-05-11 20.47.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/871b9364-33a3-8303-7b37-5906e6c9bab4.png)

# 実行する
では、今回も自分宛に送信してみます。
今回は、infoseek,gmail,macMailアプリでテストしてみました。

## infoseek
成功です。
![スクリーンショット 2021-05-11 20.58.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/cc19930c-8e05-75f5-7c04-f561e9e7193d.png)

## gmail
こちらも成功です。
「sendgrid.net経由」というのも表示されています。
![スクリーンショット 2021-05-11 20.58.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/101f8878-ab9a-e72f-1ed0-5302c19367b0.png)

## macMailアプリ
だがしかし、こちらはちょっと問題がありました。
添付ファイル名の日本語（2バイト文字)が文字化けしてしましました。
![スクリーンショット 2021-05-11 20.59.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/463157b5-bf8b-d055-8b09-03134eced636.png)
まだ解決していませんが、とりあえず添付ファイルを送信できて、受信したメールから添付ファイルをダウンロード→開くということもできたので、今回はこれで終わりにします。
解決策がわかったらまた記事にします。
Rでロジスティック回帰をやってみた(2)

SASでもやってみた。

ちなみにSASのプログラムではこうなる

```SAS
proc logistic data=qiita.logi2 descending;
model admit=rankx;
run;
```

SASの結果はRと全く同じになった。


```R
　　　　　　　　　　　　　　　最尤推定値の分析
パラメータ	自由度	推定値	標準誤差	Waldカイ 2 乗値	Pr > ChiSq
Intercept	1	-1.3083	0.1782	53.9014	<.0001
rankx	　　1	　　0.9459　0.2264	17.4587	<.0001
オッズ比の推定
効果	点推定	　95% Wa
　　　　　　　　　　　信頼限界
rankx	2.575	1.652	4.013
```
【Unity】UnityEditorのティアリングを解消する

<iframe width="560" height="315" src="https://www.youtube.com/embed/lavqz5EqDEY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

UnityEditorで再生すると、上のように映像が乱れます。
ティアリングという垂直同期がズレる現象です。

ビルドする場合は、ProjectSettings > Quality で VsyncCount を **Every V Blank**にするとティアリングが解消されますが、UnityEditorには有効ではありません。
こういうものかと諦めていたんですが、調べてみるとちゃんと設定がありました。

# ティアリングを解消する

GameViewのResolution設定に **Vsync(Game view only)** の項目があります。
**Vsync(Game view only)**  をオンにするとティアリングがなくなります。
![スクリーンショット 2021-05-11 20.10.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535406/a1457192-337f-d773-f3d2-1e6285dc636c.png)

お前、そこにおったんかー！
探しとったでー

# 参考
https://forum.unity.com/threads/screen-tearing-and-jittering-issue-in-game-mode-view-unity-2018-1.531659/

https://issuetracker.unity3d.com/issues/macos-vsync-in-quality-settings-has-no-effect-and-screen-tearing-is-visible-when-in-game-view
rails (apiモード)+ Docker + mysql 環境構築（メモ）

#はじめに
学習したことのメモとして書いていきます。

#ディレクトリ構造
```
api/
　├ Gemfile
　├ Gemfile.lock
　├ Dockerfile
　├ docker-compose.yml 
　├ entrypoint.sh　
```

#Dockerfile dockercompose.yml Gemfile entrypoint.sh

```Dockerfile:Dockerfile
FROM ruby:2.7.4
RUN apt-get update

#最新版のyarnをインストールできるように設定
FROM ruby:2.7.4
RUN apt-get update

RUN set -x && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
  echo 'deb http://dl.yarnpkg.com/debian/ stable main' > /etc/apt/sources.list.d/yarn.list

RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && \
  apt-get install nodejs

RUN apt-get install -y \
  build-essential \
  libpq-dev \
  yarn
RUN mkdir /api
WORKDIR /api
COPY Gemfile  /api/
COPY Gemfile.lock /api/

RUN bundle install


COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]

```

```yml:docker-compose.yml
version: '3'
services:
  api:
    build:
      context: ./api/
      dockerfile: Dockerfile
    volumes:
      - './api:/api'
    ports:
      - '8000:3000'
    tty: true
    stdin_open: true
    depends_on:
      - db
    links:
      - db
  db:
    image: mysql:5.7
    volumes:
      - ./db-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - '3306:3306'

```
dbのvolume:　について詳しくは[こちらのブログ](https://nishinatoshiharu.com/docker-volume-tutorial/)。
volumeの場所については[こちら](https://note.com/w0o0ps/n/n9bc1bcd9fa59)

```entrypoint.sh:entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /api/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

```

```Gemfile:Gemfile
source 'https://rubygems.org'
gem 'rails', '~>6'
```
#rails ファイルの作成


次にコマンドを実行します

```
docker-compose run --rm --api rails new . --api --force --database=mysql --skip-bundle --skip-test 
```
**--skip-bundle** :  Dockerfileでbundle install するのでbundleをスキップ

**--force** : rails new　で作られるファイルがすでに存在する場合上書き

**--skip-test** : rspecを使うのでスキップ

Gemfile が更新されたので下記を実行

```
docker-compose build
```



#database.ymlの編集


またdatabase.ymlのデフォルトの部分を以下のように編集する

```database.yml:datbase.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: db
```

次に

```
docker-compose exec api rails db:create

docker-compose exec api rails db:migrate
```



これでdocker-compose up を行った後、指定したポート(今回は8000)でURL(localhost:8000)を入力すればよく見るrails の画面が現れる。
【JavaScript】スタートボタンを作成し、1秒毎に文字の色が変わる画面を作成せよ。停止ボタンも作成し、押下すると色の変化を止める処理を作成せよ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/26b8a0dd-3b5d-b581-ff87-4953a3cc00b3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/e30f1edf-87d0-dd6b-3439-174bf6ccaa12.png)



```javascript
<!DOCTYPE html>
<html lang="ja">
<head>
   <meta charset="UTF-8">
   <title>要素の作成・追加</title>
   <script>
   // 変数を定義
   var interval_id;
   var start_flag = false;  // スタート処理中はtrue
//--------------------------------------------------------
   function start_flash_text() {
     // 停止しているときのみ、スタート処理を開始(二重クリック防止)
     if (start_flag === false) {
       // 1秒ごとにflash_textを実行
       interval_id = setInterval(flash_text, 1000);
       start_flag = true;
     }
   }
//--------------------------------------------------------
   function flash_text() {
     var flash = document.getElementById('flash');
     // p要素の文字色を赤か青に変更
     if (flash.style.color === 'red') {
       flash.style.color = 'blue';
     } else {
       flash.style.color = 'red';
     }
   }
//--------------------------------------------------------
   function stop_flash_text() {
     // setIntervalによる繰り返し動作を停止
     clearInterval(interval_id);
     start_flag = false;
   }
//--------------------------------------------------------

   window.onload = function() {
     var start = document.getElementById('start');
     start.addEventListener('click', start_flash_text, false);
     
     var stop = document.getElementById('stop');
     stop.addEventListener('click', stop_flash_text, false);
   }
   </script>
</head>
<body>
   <p id="flash">flash text</p>
   <button id="start">start</button>
   <button id="stop">stop</button>
</body>
</html>
```