OmniAICreator/Qiita-1.07M huggingface dataset:
Rails6 + PostgresのDocker開発環境を構築

いろんな記事をみてコピペしてみたのですが、どれもうまくいきませんでした。
私がうまくいった方法を記録しておきます。

## ファイルの準備
```zsh
$ touch Dockerfile docker-compose.yml Gemfile Gemfile.lock
```
```Dockerfile
FROM ruby:2.7

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

RUN apt-get update -qq && apt-get install -y nodejs postgresql-client yarn

RUN mkdir /app_name
ENV APP_ROOT /app_name
WORKDIR $APP_ROOT

ADD ./Gemfile $APP_ROOT/Gemfile
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock

RUN bundle install
ADD . $APP_ROOT
```
```docker-compose.yml
version: "3"
services:
  db:
    image: postgres
    volumes:
      - psgl_data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: password
    ports:
      - 5433:5432
  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    tty: true
    stdin_open: true
    depends_on:
      - db
    ports:
      - "3000:3000"
    volumes:
      - .:/app_name
volumes:
  psgl_data:
```
```rb:Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 6'
```
`Gemfile.lock`は空のままでOK

## 構築
```zsh
$ docker-compose run web rails new . --force --no-deps --database=postgresql
$ docker-compose build
```
ビルドの間に、`config/database.yml`を編集

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

development:
  <<: *default
  database: app_name_development

test:
  <<: *default
  database: app_name_test
```
ビルドが終わったら以下のコマンドを叩く

```zsh
$ docker-compose up
$ docker-compose exec web rails db:create
```

http://localhost:3000 にアクセスして、**Yay! You’re on Rails!**を確認

## 【おまけ】VSCode Remote Containerで開発
私は普段以下のような環境で作業をしています。ローカルにRubyやRailsを入れる必要無し！
[VSCode Remote Containerが良い](https://qiita.com/d0ne1s/items/d2649801c6f804019db7)
CERN ROOT における Makeのエラー

#導入

ここでは、CERNが配布して知るROOTを使ったMakefileを作成した際に躓いたメモを書く。

#環境

- Ubuntu 18.04.4 LTS
- ROOT 6.20/04
- gcc 7.5.0
- GNU Make 4.1

#問題点

いままで別のバージョンのLinuxなどで使ってきた以下のMakefileが使えなくなってしまった。
いままで使っていたMakefilは以下のとおりである。

```Makefile:Makefile_old
TARGET = macro

SRCS = $(TARGET).cc
OBJS = $(TARGET).o

ROOTCFLAGS = $(shell root-config --cflags)
ROOTLIBS   = $(shell root-config --libs)
ROOTGLIBS = $(shell root-config --glibs)

CXXFLAGS   = $(ROOTCFLAGS) -Wall -fPIC
CXXLIBS    = $(ROOTLIBS)
CC = g++ 

$(TARGET): $(OBJS)
        $(CC) $(CXXLIBS) $(OBJS) -o $@

# suffix rule
.cc.o:
        $(CC) $(CXXFLAGS) -c $<

# clean
clean:
        rm -f $(TARGET) $(OBJS)
```

基本的にはこれで使えたはずなのだが、本環境に移行した際に次のようなエラーが発生し、makeできなくなってしまった。

```
macro.o: 関数 `__static_initialization_and_destruction_0(int, int)' 内:
macro.cpp:(.text+0xcca): `TVersionCheck::TVersionCheck(int)' に対する定義されていない参照です
collect2: error: ld returned 1 exit status
Makefile:31: recipe for target 'macro' failed
make: *** [parmteqm2gpt] Error 1
```

ROOT forumを見てみると $ROOTSYS/lib が正しく通っていないことが原因なようだが、確認してみたところPATHは正しく通っていることがわかった。正確な話は後日気が向いたら追記していきたい。

該当するROOT forumのリンクは以下のものである。
https://root-forum.cern.ch/t/undefined-reference-to-tversioncheck-tversioncheck-int/21123/12

#解決策

さて、上記問題点の原因を探るためにいろいろと探ってみたら、次のようなことがわかった。

１）　libへのパスは通っている
２）　ターミナル上からのコンパイル

```
g++ `root-config --libs --cflags` macro.cpp -o macro 
```
は通らない。

３）オブジェクト生成を経由する

```
g++ $(root-config --cflags) -c macro.cpp
g++ $(root-config --libs) macro.o -o macro 
```
は通らない。

４）　ターミナル上からのコンパイルでlibの引用を分割した

```
g++ $(root-config --libs) $(root-config --cflags) macro.cpp -o macro 
```

は通る（なんで!?）

そこで以下のようにMakefileを書き換えてみた。

```Makefile:Makefile_new
TARGET = macro

SRCS = $(TARGET).cpp
OBJS = $(TARGET).o

ROOTCFLAGS = $(shell root-config --cflags)
ROOTLIBS   = $(shell root-config --libs)
ROOTGLIBS = $(shell root-config --glibs)

CXXFLAGS   = $(ROOTCFLAGS) -Wall -fPIC
CXXLIBS    = $(ROOTLIBS)
CC = g++ 

$(TARGET):
        $(CC) $(SRCS) $(CXXLIBS) $(CXXFLAGS) -o $@

# # suffix rule
# .cc.o:
#       $(CC) $(CXXFLAGS) -c $<

# clean
clean:
        rm -f $(TARGET) $(OBJS)
```

なにをやったかというと、ただソースファイルから直接実行ファイルを生成しただけである。
こうすると、エラーを吐き出さずに問題なくmakeできた。

#まとめ

自分の環境だと、従来のコンパイルの方法でうまくいかないことがわかった。この問題は、libの引数を分割し、一括で実行ファイルを生成する方法だとうまく行くことがわかった。しかし、原因はよくわかっていない。

＊用語に関して間違った使い方をしているかもしれません。ぜひご指摘をおねがいいたします。また、上記エラーの原因について初歩的なミスが考えられるので、もしご存じの方がいらっしゃったら教えていただけるとうれしいです。
【初心者】branchっていくつも作っていいの？（メモ、備忘録）

リモートリポジトリや、ローカルリポジトリにブランチというコピーのようなものを作って、
そこで作業してプルリクしたり、マージしたりすることで共同作業することは分かった。


# 開発に関係するリポジトリとブランチの全体像が見えねぇ！
解決してくれたサイト様
[Gitを最大限に活用できる「Git flow」で、効率よく開発を進めよう！](https://liginc.co.jp/248864)


# 状況を整理しよう
何かを開発して、サービスを提供する以上は大別して２つの環境に分けられる…
>①サービスを提供する/している/する予定のサーバー環境
②開発用やテストなどで使用するローカル環境

①をとっても、②をとっても１つの環境で開発が完了するということは無いであろう。
（逆説的に環境１つで完了するのであれば、今回の”全体像”は気にしなくて良いレベルに重要性が低くなる）

いくつもの環境から開発やテストをするときに、関係するリポジトリの数は多くなる。
その多くなったリポジトリと、それぞれのリポジトリ内に存在するブランチはどうなっているのか？

例えば…
>①サービスを提供する「本家サーバー」
②3人1組の開発チーム、2人1組の保守チーム

①と②で合計して６つの環境があったとする。
そうすると、それぞれの環境でローカルリポジトリと、リモートリポジトリが存在する。

>「本家サーバ」のローカルリポジトリ
「本家サーバ」のリモートリポジトリ
開発チームAさんのローカルリポジトリ
開発チームAさんのリモートリポジトリ
開発チームBさんのローカルリポジトリ
開発チームBさんのリモートリポジトリ
…

この時点で「うわっ、管理めんどくせぇ」となるうえに、
それぞれで無秩序にブランチを作成して作業をしていたのでは
**どのブランチがどういった用途で使われているかという個人のルールを
全員（もしくはリーダー）が把握するという無駄な中間管理業務が発生してしまう。**

”中間管理”という表現で済めばいいけど本番環境でトラブったらやばくね？
ヒューマンエラーの予感しかしねぇ！
マージするとかちょー怖い。

# 解決しよう
解決策：みんなで統一できて効率の良いルールを使おうぜ

⇒そうだ、Git flowを使おう！


# 完
「どんな具合にブランチを切ったら良いか」は
「Git flowを解説してくれよぅ」と同義なため、頑張ってGit flowを勉強して下さい。
（*残念！筆者も勉強中なのだ！*）

To 先人の方々
理解が間違ってたらコメントください。
DrupalノードIDリセット

#NODEのIDをリセットするSQL
```
ALTER TABLE `node` AUTO_INCREMENT=1;
ALTER TABLE `node_revision` AUTO_INCREMENT=1;
ALTER TABLE `node_field_data` AUTO_INCREMENT=1;
ALTER TABLE `node_field_revision` AUTO_INCREMENT=1;

ALTER TABLE `file_managed` AUTO_INCREMENT=1;
ALTER TABLE `file_usage` AUTO_INCREMENT=1;

```
Google colab: ResNet with one-neuron hidden layers is a Universal Approximator

[ResNet with one-neuron hidden layers is a Universal Approximator](https://arxiv.org/abs/1806.10909)の2章にある実験の再現に[Colab](https://github.com/festa78/colab_experiments/blob/master/one_neuron_resnet.ipynb)にてトライ。　　

これはFully Connected NNと簡易的なResNetの分類学習を比較し、ResNetのみが正しく学習可能なデータ例を示す。　　
この例を通して、ResNetのIdentity mappingとの組み合わせがあることで、ResNetのみがuniversal approximationが実現可能になる事を説明しようとしている。

再現実験ではいいところまでいったものの、たまにしか再現できず断念。恐らく何か間違っている？
【Linux】exportについて

ログアウトするたびexportしないといけない
https://docs.python.org/ja/3/library/codecs.html


「export」は、環境変数やシェル変数を設定するコマンドです。
export 変数名=値 （シェル変数を定義して同時にエクスポートする）
https://www.atmarkit.co.jp/ait/articles/1801/12/news015.html
Kubuntu18.04インストール後の環境を整える

##何の話か
Kubuntuを導入する際に個人的に必ず行う最低限の設定やツールなど環境整備の事例についてです。
普段のエディタはviです。

##homeの日本語ディレクトリを英語化
日本語を選んでインストールしたあとディレクトリだけは英語化
ubuntuの場合は普通に`LANG=C xdg-user-dirs-gtk-update`で良いがkubuntuの場合は

```
LANG=C xdg-user-dirs-update --force
```

##sshサーバ

```
sudo apt install -y openssh-server
```

公開鍵`id_rsa.pub`を`~/.ssh`配下に置く


##net-tools
手がコマンドを覚えているのでこれがないと暮らせない

```
sudo apt install net-tools
```

##vim
標準でも入っているがtiny版なのでpluginもいろいろはいっているHuge版をインストール

```
sudo apt install vim
```

###Plugin管理はVundleで
参照：[Vundle Quick Start](https://github.com/VundleVim/Vundle.Vim#quick-start)

```
git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim
```

`~/.vimrc`に以下を記述
これも[Vundle Quick Start](https://github.com/VundleVim/Vundle.Vim#quick-start)どおりにまず.vimrcに記述

```~/.vimrc
set nocompatible              " be iMproved, required
filetype off                  " required

" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
" alternatively, pass a path where Vundle should install plugins
"call vundle#begin('~/some/path/here')

" let Vundle manage Vundle, required
Plugin 'VundleVim/Vundle.vim'

" ここ以下に導入したいpluginを書いていくgithubのAuthor/Github repoの形式
Plugin 'airblade/vim-gitgutter'
Plugin 'vim-airline/vim-airline'
Plugin 'vim-airline/vim-airline-themes'
Plugin 'scrooloose/nerdtree'
```

その後、viを立ち上げて

```
:PluginInstall
```
を実行する
Vundleの他のコマンド

```
:PluginList       - lists configured plugins
:PluginInstall    - installs plugins; append `!` to update or  :PluginUpdate
:PluginSearch foo - searches for foo; append `!` to refresh local cache
:PluginClean      - confirms removal of unused plugins; append `!` to auto-approve removal
```

###Escの代わりにjjでコマンドモードに移行する設定
これ必須ですね

```~/.vimrc
inoremap <silent> jj <ESC>
```

##jq
最近はこれも必要

```
sudo apt install jq
```


##参考：忘れがちなaptコマンド
環境整備の話ではないですが参考まで。
`apt update/upgrade/install`はひたすら打つのだけど以下はあまり使わないので忘れがち。

|  コマンド | 動作 |
|:--|:--|
| sudo apt remove (パッケージ名) | パッケージ削除 |
| sudo apt remove --purge (パッケージ名) | パッケージ完全削除 |
| sudo apt show (パッケージ名) | パッケージ詳細情報表示 |
| sudo apt list (パッケージ名) | パッケージ検索(完全一致) |
| sudo apt search (パッケージ名) | パッケージ検索(部分一致) |
| sudo dpkg -l | インストール済パッケージ一覧表示 |

補足：インストールログは `/var/log/apt/history.log`や`history.log.1.gz`などにあり。

`grep Commandline history.log`
`zcat history.log.1.gz |grep Commandline`
などで検索すると見やすい。
Laravel new コマンド PHP Fatal error:  Uncaught Error: Call to undefined method

Laravelインストーラを使ってインストールした時にエラーが起きた場合の対処法です。

## 問題

```shell-session
$ laravel new project-name
Crafting application...
PHP Fatal error:  Uncaught Error: Call to undefined method Symfony\Component\Process\Process::fromShellCommandline() in /Users/ucan/.composer/vendor/laravel/installer/src/NewCommand.php:84
Stack trace:
#0 /Users/ucan/.composer/vendor/symfony/console/Command/Command.php(251): Laravel\Installer\Console\NewCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#1 /Users/ucan/.composer/vendor/symfony/console/Application.php(886): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#2 /Users/ucan/.composer/vendor/symfony/console/Application.php(262): Symfony\Component\Console\Application->doRunCommand(Object(Laravel\Installer\Console\NewCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#3 /Users/ucan/.composer/vendor/symfony/console/Application.php(145): Symfony\Component\Console\Application->doRun in /Users/ucan/.composer/vendor/laravel/installer/src/NewCommand.php on line 84

Fatal error: Uncaught Error: Call to undefined method Symfony\Component\Process\Process::fromShellCommandline() in /Users/ucan/.composer/vendor/laravel/installer/src/NewCommand.php:84
Stack trace:
#0 /Users/ucan/.composer/vendor/symfony/console/Command/Command.php(251): Laravel\Installer\Console\NewCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#1 /Users/ucan/.composer/vendor/symfony/console/Application.php(886): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#2 /Users/ucan/.composer/vendor/symfony/console/Application.php(262): Symfony\Component\Console\Application->doRunCommand(Object(Laravel\Installer\Console\NewCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#3 /Users/ucan/.composer/vendor/symfony/console/Application.php(145): Symfony\Component\Console\Application->doRun in /Users/ucan/.composer/vendor/laravel/installer/src/NewCommand.php on line 84
```

Laravelインストーラが古いので更新しましょう...😅

## 対策

```shell-session
$ composer global update
```

ディレクトリは作成されてるので削除してやり直しましょう。

```shell-session
$ rm -rf project-name
$ laravel new project-name
$ php artisan -V
Laravel Framework 7.10.3
```

バージョン表示できたらokです。

## 参考

- https://laracasts.com/discuss/channels/laravel/laravel-new-app-not-working-after-upgrading-laravel-installer
【GCP】Cloud speech-to-text apiを触ってみた

#参考URL
https://qiita.com/knyrc/items/7aab521edfc9bfb06625
(参考URLの解説的なサイト:https://qrunch.net/@OrionB312/entries/4o6rlrHxW39xSC5n)


#流れ
・プロジェクトを作成or既存のプロジェクトを選択
・APIを有効化
・認証情報を設定
　今回はサービスアカウントキーを使用

```
export GOOGLE_APPLICATION_CREDENTIALS=/home/***/***.json
```

・コマンドシェルを起動
・以下のコードを記載したファイルを作成

```
# !/usr/bin/env python
# coding: utf-8
import argparse
import io
import sys
import codecs
import datetime
import locale

def transcribe_gcs(gcs_uri):
    from google.cloud import speech
    from google.cloud.speech import enums
    from google.cloud.speech import types
    client = speech.SpeechClient()

    audio = types.RecognitionAudio(uri=gcs_uri)
    config = types.RecognitionConfig(
        sample_rate_hertz=16000,
        encoding=enums.RecognitionConfig.AudioEncoding.FLAC,
        language_code='ja-JP')

    operation = client.long_running_recognize(config, audio)

    print('Waiting for operation to complete...')
    operationResult = operation.result()

    d = datetime.datetime.today()
    today = d.strftime("%Y%m%d-%H%M%S")
    fout = codecs.open('output{}.txt'.format(today), 'a', 'utf-8')

    for result in operationResult.results:
      for alternative in result.alternatives:
          fout.write(u'{}\n'.format(alternative.transcript))
    fout.close()

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument(
        'path', help='GCS path for audio file to be recognized')
    args = parser.parse_args()
    transcribe_gcs(args.path)
```

・音声ファイルを作成
　例として、スマホアプリの「サウンド＆ボイスレコーダー - ASR」なら簡単に作成可能。
　　Flacファイルにして、16000HZ、モノラルで録音する。
・Storageに作成した音声ファイルを格納する。
・「Python　ファイル名　音声ファイルのURI」でコマンドを実行
・同階層にファイルができる
・ファイルの中身を確認して完了

#詳細な手順の記載
1.プロジェクトを作成する。
※ここでは解説いたしません。
2.作成したプロジェクトにて、speech-to-text api の有効化をする
3.コンソール画面上部検索窓に「speech-to-text api 」を入力し、「Cloud　speech-to-text api」をクリック　
4.APIを有効にするをクリック
5.APImangerの認証情報にある認証情報を作成をクリック
6.サービスアカウントキーをクリック
7.サービスアカウントキーが作成されたことを確認し、作成されたサービスアカウントキーをダウンロードする
8.メニューからstorageをクリック
9.任意のストレージを選択し、音声ファイルをアップロードする
10.音声ファイルを作成する
　例として、スマホアプリの「サウンド＆ボイスレコーダー - ASR」なら簡単に作成可能。
　　Flacファイルにして、16000HZ、モノラルで録音する。
11.Cloud Shell を開く
12.pathを通す。
export GOOGLE_APPLICATION_CREDENTIALS=/home/ユーザ名/***.json
13.Cloud Shell の右上にあるアップロードからspeech_to_text_test.pyファイルをアップロードする
14.「Python　ファイル名　音声ファイルのURI」でコマンドを実行
15.同階層に実行した日時をファイル名としたファイルができる
16.ファイルの中身を確認すると翻訳した内容が出力される



#エラー
・エラー集
https://qiita.com/hanlio/items/875b91e0d4931a57e86b

####1
ImportError: cannot import name 'speech_v1' from 'google.cloud' (unknown location)

https://qiita.com/arumiti/items/835e87c35dcbb69d8ca2
ここを参考に。

```
python3　→　import sys　→　print(sys.path)
```

の順にコマンドを打つ。

pythonのインストール先がどこかが表示される。

このとき、python3ではなく、python2.7に保存されていた。
なので、python2.7で実行すれば正常に実行される。

####2
https://docs.python.org/ja/3/library/codecs.html
codecsの部分をutf-8に直した


#参考情報
Flacはハイレゾ音源らしい
https://support.digion.com/curiostyle/2017/07/24/hires-free/

#今後やりたい
https://iti.hatenablog.jp/entry/2017/05/09/112051
https://qiita.com/saihara-k/items/86ba457523daa02c1869

https://blog.apar.jp/web/9893/
Text-to-Speech API だった
Node-REDでraw bodyが取りたい！

# はじめに

http requestを受け取る際にNode-REDは気が利く奴なので
整形したbody情報を渡してくれます。😇
また、raw bodyの情報は見えません。
メモリを食わないように気を使ってくれています。😍
でも、たまにraw bodyを取得したい。。

## raw bodyを取得する。

多分、以下でraw bodyを取れます。（取れてるはず..)

```
encodeURIComponent(JSON.stringify(msg.payload))
```
RFC3986に忠実に変換する場合encodeURIComponentを以下に変更

```
function fixedEncodeURIComponent (str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
```

RFC1738

```
function rawurlencode (str) {
  return encodeURIComponent(str)
    .replace(/!/g, '%21')
    .replace(/'/g, '%27')
    .replace(/\(/g, '%28')
    .replace(/\)/g, '%29')
    .replace(/\*/g, '%2A')
}

let requestBody = rawurlencode(msg.payload);
```
## 最後に

間違ってたら教えて下さい🙇
Github Actions で Rails の CI をやりたい

# なにこれ？
Github Actions で Ruby on Rails の CI をやりたい、という話をする。ただ、ちょっとマニアックな路線でいこうと思う。

# コード
今回のコードは [Github のレポジトリ](https://github.com/seahal/qiita) にもあります。

### アジェンダ
Github Actions は `.github/workflows/` にあるコードを読んで実行してくれるみたいなので、プロジェクトのルートディレクトリ傘下に前記の階層を作り、その後 `rails_test.yaml` でも作成して CI のコードを書けば、docker-compose up したらローカル環境と同じ条件で rails test がうごく、この記事を書き始めるまでは、そう思っていたのです。

### 何が悪かったのか
コンテナのホスト側とコンテナ側の user id の不一致のせいで、`mkdir` とかが実行されず、テストが実行できなかった。

### 解決した方法
`docker-compose` で起動したときに uid と gid をコンテナとホストで一致させてやると、この問題は解決できそうだったので、下記のようにした。

```dockerfile
# docker-compose.yaml
services:
  application-server:
    user: "${USER_ID}:${GROUP_ID}"
```

そんでもって、こうすると Github Actions の CI で動いてくれるみたいだ

```bash
$ USER_ID=$(id -u) GROUP_ID=$(id -g) docker-compose build
$ USER_ID=$(id -u) GROUP_ID=$(id -g) docker-compose run -T application-server yarn install --check-file
$ USER_ID=$(id -u) GROUP_ID=$(id -g) docker-compose run -T application-server bundle exec rails db:migrate:reset
$ USER_ID=$(id -u) GROUP_ID=$(id -g) docker-compose run -T application-server bundle exec rails test
```

# おわりに
CI 関連、地味に時間が取られるのが辛い...
【鉄則】サーバレスLINEbotの実運用法が確立した【論文調】

# 背景
LINE bot を周知戦略としてビジネスに使うことが増えている．しかし，チーム開発でどうLINE botを開発し運用すべきかという議論はあまり行われていない．ここでは，LINE botのバックエンドにHTTP APIをトリガーとしたLambdaを用いたモダン開発運用のエコシステムを提言する．

# 概要
![linebotoverview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234751/3527aff4-a365-7d30-abd7-6f2afe7d36f5.png)

LINEbotのチーム開発運用の鉄則としてこれらを提言し，具体的な手法について詳細に説明する．

1. 開発botと本番botに分ける
2. APIとLambdaでステージ管理を行い，それぞれのbotに紐付ける
3. Lambdaのコードはdocker環境にてローカルで開発する(以下のメリットがある)
    - gitHub管理下に置け，チーム開発に適する
    - Lambdaのコードをいつでもローカル環境からデプロイできる
    
以後分かりやすく説明するために記事をこちらに移動した↓
[続きはこちら](https://sho-d-blog.com/tech/518/)
ViewCreator クエリ設定コード、データ参照コード 変更方法

ViewCreatorではクエリ設定の主キーにあたるクエリ設定コードやデータ参照のデータ参照コードの変更が出来ません。IM-FormaDesignerと同じです。
IM-FormaDesignerのアプリケーションID 変更方法と同じようにエクスポートファイルの修正によってID変更が可能です。

[IM-FormaDesigner アプリケーションID 変更方法](https://qiita.com/doriburu/items/d85c258b9dd75f2d8f0d)


ViewCreatorはエクスポートファイルがXMLですので、Formaより手順は少なく簡単です。

### 1. 変更対象をエクスポートする
### 2. エクスポートファイル中のクエリ設定コードやデータ参照コードを修正する
### 3. 変更したファイルをインポートする


おそらくIM-Workflowも同様の方法でID変更が可能だとは思うのですが、こちらは必要に駆られたことがないため未検証です。
JS http https 分岐　<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">を付与

https:時に

```<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">```

を付与するコードを簡易的に作成したかった。

```js

    var url = location.protocol

    if(url == 'https:') {
        $('head').append('<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">');
    }
```
Hugoを使ってみた（Quick-Startをなぞる）

## この記事は何
[自分のWebサイトを持ちたい！！とずっと思っていたので作ってみた](https://qiita.com/tom_ogashi/items/5ad9ea0b670b750b5a6b)の番外編です。
Webサイトを構築するにあたり、**静的サイトジェネレーター**という単語を多く見かけたので、実際にどんなもんなのか触ってみました。

## 前提

OSは`Windows 10 Home`です。
また、パッケージ管理には`Chocolatey`を使用しています。

## Hugoのインストール

基本的に、[Hugo公式ドキュメントのQuick-Start](https://gohugo.io/getting-started/quick-start/)を追っていきます。
まずは、PowerShellを立ち上げてください。
その後、以下のコマンドを打ち込んでください。

```
> cinst hugo
```

私の環境では、インストールに6分ほど掛かりました。

インストールが完了したら、以下のコマンドを打ち込んで、問題なくインストールができていることを確認してください。

```
> hugo version
Hugo Static Site Generator v0.70.0-7F47B99E windows/amd64 BuildDate: 2020-05-06T11:17:50Z
```

## サイトの構築

次に、実際にサイトの構築を行います。
任意のディレクトリに移動し、以下コマンドで作業環境の構築を行います。
（私は`C:\Users\ユーザ名\workspace`配下に構築しました。）

```
> mkdir Hugo | cd
```

その後、以下コマンドを打ち込んでください。

```
> hugo new site quickstart
```

すると、`Hugo\quickstart`配下にこんな感じで色々展開されていると思います。

```
│  config.toml
│
├─archetypes
│      default.md
│
├─content
├─data
├─layouts
├─static
└─themes
```

## テーマの追加

Hugoには多くの[テーマ](https://themes.gohugo.io/)が用意されています。この中から好きなものを一つ選んで、以下コマンドで適用していきます。

私は、公式ドキュメントの通りに[Ananke theme](https://themes.gohugo.io/gohugo-theme-ananke/)を使用してみます。

```
> cd quickstart
> git init
> git submodule add https://github.com/budparr/gohugo-theme-ananke.git themes/ananke
```

その後、`config.toml`に使用するテーマの記載を追記します。

```
> Add-Content -Value 'theme = "ananke"' -Path config.toml -Encoding UTF8 -NoNewline
```

## 記事の追加

以下のコマンドで新しい記事を追加することができます。

```
> hugo new posts/my-first-post.md
```

これで、my-first-postというマークダウンファイルが保存されました。
中身はこんな感じになっています。

```markdown
---
title: "My First Post"
date: 2019-03-26T08:47:11+01:00
draft: true
---

```

タイトルとか日付を勝手に補完してくれていい感じです。

せっかくなので何か書いておきましょう。

```markdown
---
title: "My First Post"
date: 2019-03-26T08:47:11+01:00
draft: true
---

# 最初の雄たけび
ウオーーーーーーーーーー！！！
アイ アム ヒューーーーーゴ！！！！！！
```

嬉しいので叫んでおきました。いかがでしょうか。

## 実際に動かして見てみる

これで、デザインの適用、記事の追加が出来ました。
実際にサーバーを立ち上げて、どんな感じになったか見てみましょう。

以下のコマンドを打ち込んでください。

```
> hugo server -D
```

すると、どこどこにサーバを立ち上げたよ～みたいに教えてくれると思います。（私は`http://localhost:1313/`でした。）

ブラウザを立ち上げて、指定されたURLを打ち込むと・・・

![image-20200507150327250.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500366/4fe22f9c-311c-2bc2-96df-acfb7f39bc53.png)


#### で、できたーーーーーーーーー！！！！

#### ウオーーーーーーーーーー！！！

#### アイ アム ヒューーーーーゴ！！！！！！



## カスタマイズ

サーバーを`Ctrl + c`で落としましょう。
そしたら、`config.toml`をお好みのテキストエディタで開き、ブログ名とかを変えてみましょう。

```toml
baseURL = "https://example.org/"
languageCode = "en-us"
title = "Qiiita"
theme = "ananke"
```

上記変更を保存後、再び`hugo server -D`をすると・・・

![image-20200507152325125.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500366/13404938-36f6-1992-4003-efd3f5189646.png)

**Qiiitaが爆誕しました。本当におめでとうございます。**

## ビルドしよう

```powershell
> hugo -D
```

これだけです。

これだけで、`.\public\`以下にhtmlファイルやらが出力されています。

お疲れさまでした。

## 感想
あまりにサクサク進んでいくので気持ちが良かったです。
Webサイト構築に使用する技術として、**Gatsby**と**Hugo**で迷っているところなので、両者とももう少し触ってみたいと思います。
tableViewのdidSelectRowAtでセル内のテキストを取得する

まずtableView(tableView, cellForRowAt: indexPath)でindexPathを元にcellを作成します。
あとはcell -> textLabel -> textと辿っていくだけです。

```Swift
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let cell: UITableViewCell = self.tableView(tableView, cellForRowAt: indexPath)
        print((cell.textLabel?.text)!)
    }
```
AWS ALB＋Lambdaでサーバーレスなウェブサービスを実装してみる #1

#前提
-投稿者はAWSを本格的に学び始めて日が浅い（一月余り）
-環境ありきの要件なので必ずしも効率的とは限らない
-RDB Proxyを使ってみる

#環境
![ServerlessService.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612635/c1ac04e4-5699-edcd-926b-b7049a396ea4.png)

上の図のような構成を検証する形で構築していきたいと思います。

題名ではウェブサービスと言ってしまっていますが、ブラウザからアクセスしてウェブページを表示させるところまでで完成形としたいと思います。

#ALB+Lambda
まずはALBからLambdaを呼び出すところをやってみる。

##ALB
ALBの作成から始めます。
AWSマネジメントコンソールのEC2から"ロードバランシング">"ロードバランサー"を選択する。
"ロードバランサーの作成"を選択し、ターゲットの種類をLambda関数にして"後で関数を追加する"を選択してロードバランサーを作成します。


##Lambda
以下は、AWS公式ドキュメントを参考にしたLambda関数"HelloWorldFunction"を確認のため表示する文字だけ変えたものです。

```
def lambda_handler(event, context):
	response = {
		"statusCode": 200,
		"statusDescription": "200 OK",
		"isBase64Encoded": False,
		"headers": {
			"Content-Type": "text/html; charset=utf-8"
	}
	}

	response['body'] = """<html>
	<head>
	<title>テストですよ!</title>
	<style>
	html, body {
	margin: 0; padding: 0;
	font-family: arial; font-weight: 100; font-size: 1em;
	text-align: center;
	}
	</style>
	</head>
	<body>
	<p>ラムダよりもBeansがすき</p>
	</body>
	</html>"""
	return response
```

ALBのDNS名の前に"https://"を付けてアクセスすると次の画像のようになりました。
![結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612635/875b3905-9b61-e184-56e7-b91d8850acd8.png)

これでALB+Lambdaで静的ページを表示できるようになります。
　実際に任意のドメインでクセスしようと思うとAWS Certificate ManagerとかRoute 53とかを使用する必要があります。
「序数242が見つかりません」を解決する。

###"序数242が見つかりません"
AnacondaでNumpyをインポートしようとすると出てくるこのメッセージ。何回か右往左往したので自分なりの解決法を備忘録として置いときます。

1　Windows/system32以下にあるmkl*.dllのファイルを削除orリネーム。
(*はうんたらと読み換えてください。)

2　同じくWindows/system32にある libiomp5md.dllというファイルを削除orリネーム

ググってみるとどうやらAnacondaはsystemの方のmkl*.dllファイル(数値演算用ライブラリ)を先に読み込んでしまうらしく、それを消すことでAnacondaの方のファイルを読み込めるようです。

今のところ問題は特に出ていません。同じ問題で悩んでいらっしゃる方の助けになれば幸いです。
Prometheus + Grafana連携でCPU使用率を表示したい

# TL;DR

- [ここ](https://qiita.com/egghikari/items/452ea39fd638d195c105)にあるように、Prometheus + Grafanaで機器監視を行うことができる。追加でDashboardにCPU使用率を表示したいという要件があり、追加してみた

# 手順

要点のみ記載します。重要なのは条件式となります。

## Panelの追加

画面上部のAdd Panelをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/4f68a263-40ac-d4b9-612b-7cfd4cad5105.png)

## Metricsの指定

1. MetricsでDataSourceにPromethesを選択し、条件式として以下を指定
    
    ```
    100 - (avg by (instance) (irate(wmi_cpu_time_total{mode="idle", instance=~"$server.*"}[5m])) * 100)
    ```

1. Legend formatに`not idle`を指定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/29171742-dd5d-4921-97a4-c9b2ca7872e7.png)

## Axesの指定

1. Left YのUnitに`percent(1-100)`を指定

1. Left YのY-Minに`0`、Y-Maxに`100`を指定

# 設定結果例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/73870775-db3a-eea1-27a5-fbe6a4a3e44e.png)

# リソース

https://qiita.com/egghikari/items/452ea39fd638d195c105

http://otndnld.oracle.co.jp/document/products/oem/10203/doc_cd/server/B28457-02/host.htm
※表3-4 「CPU使用率（CPU Usage）」メトリック
GithubのRepository組み替え

## 状況

 - もともと HOGE と言うレポジトリがあった。
 - HOGEを大幅に作り替えたバージョン HOGE V2を作るにあたり、 新たな HOGE2レポジトリを作りそこで作業を行なった。
 - しばらくして、HOGE2 と言うレポジトリ名が気に入らなくなった。HOGEを代表ブランド名としてバージョンに関係なく使いたかった。

## やりたい事

 - HOGE2 レポジトリを HOGE レポジトリに移し、既存HOGEレポジトリ は 旧バージョンレポジトリとして別のリポジトリ(HOGE-v1) に移したい。
 

## やった事

**1. 既存HOGEレポジトリの移行**

下記のレポジトリduplicationに従いHOGEレポジトリをHOGE-v1レポジトリにコピー。HOGE-v1レポジトリはgithubから事前に作成しておく。
https://help.github.com/en/github/creating-cloning-and-archiving-repositories/duplicating-a-repository
**2. HOGE2レポジトリからHOGEリポジトリへの移行**

下記のレポジトリduplicationに従いHOGE2レポジトリをHOGEレポジトリにコピー。
この時、**特にHOGEレポジトリの内容をクリーンにしておく必要はない**。ファイル、コミット履歴等も含め全てが上書きされる。
https://help.github.com/en/github/creating-cloning-and-archiving-repositories/duplicating-a-repository

**3. HOGE2レポジトリを削除(githubコンソールから)**
【rails】コメント機能を実装する

###はじめに
僕の質問サイトに回答機能とは別にコメント機能を追加したのでメモとして残しておきます。
初心者なので間違っていたらコメントで指摘していただけると幸いです。

##前提
rails6
ruby2.7.0

questionモデル（投稿モデル）
Userモデル（deviseのもの)
はつくられている前提です。

###コメントモデルを作る

```shell:
$ rails g model comment comment:text comment_id:integer commenter_id:integer
$ rails db:migrate
```
カラム名通りcommentはコメントそのもの、comment_idはどの投稿に対してのコメントか、commenter_idは誰がコメントをしたかを保存します。

```ruby:user.rb
has_many :comments, foreign_key: :commenter_id
```

```ruby:questions.rb
has_many :comments
```

```ruby:comment.rb
  belongs_to :user
  belongs_to :questions, optional: true
```

###コントローラー作成

```shell:
$ rails g controller comments
```

```ruby:comments_controller.rb
class CommentsController < ApplicationController

  def create
    @comment = Comment.new(comment_params)

    respond_to do |format|
      if @comment.save
        format.html { redirect_to "/questions/#{@comment.comment_id}" }
      else
        format.html { render :new }
      end
    end
  end

  private

    def comment_params
      params.require(:comment).permit(:comment, :comment_id, :commenter_id)
    end
end
```

###ルーティング

```ruby:
resources :comments, only: [:create]
```

###views

今回はエラーメッセージなどは表示しないようにしています。

```erb:comments/_form.html.erb

  <%= form_with model: comment do |f| %>
    <%= f.text_area :comment %>
    <%= f.hidden_field :comment_id, { value:@question.id } %>
    <%= f.hidden_field :commenter_id, { value:current_user.id } %>
    <%= f.submit 'コメントをする' %>
  <% end %>

```

```ruby:questions_controller.rb

def show
    @question = Question.find(params[:id])
    @comment = Comment.new
    @comments = Comment.where(comment_id: @question.id)
end
```

あとは表示したい場所(show.html.erb)などに

```erb:show.html.erb

<% @comments.each do |f| %> #コメント表示
    <p><%= f.comment %></p>
    <p><%= f.user.name %></p>
<% end %>

<%= render "comments/form", comment: @comment %> #フォーム
```

と書いてください。


##終わりに
お疲れさまでした😃。結構仕組み自体は簡単ですが一からやるとなるとやはりエラーなどが見えてしまいました。
あとはエラー表示、削除、編集機能を実装してみるといいかもしれません。

宣伝
あと、最近ぼくが公開した[資格試験の質問サイト　QUA](https://www.quaquestions.com/)もお願いします。利用者がいません（泣）。
Rails テストについて  5 （コントローラー編）

#はじめに
テストに拒否反応があるので、まずは整理したいと思います。
整理していくにつれ、拒否反応がなくなってきたかも・・・

少しづつ記事を書いていきます。
[Rails テストについて  1](https://qiita.com/raigakun/items/b88af7e80e64abfedcca)
[Rails テストについて  2](https://qiita.com/raigakun/items/d0d253f6338ce9d89fe5)
[Rails テストについて  3]
(https://qiita.com/raigakun/items/4439cf6615c155b7b489)
[Rails テストについて  4]
(https://qiita.com/raigakun/items/e3e4a979541c321f3ec7)
もうすでにご存知の方、省略の仕方等ご存知でしたら、ご助言願います。


## コントローラーテストで確認したいこと
- アクション内で定義するインスタンス変数の値が期待したものになるかを確認する
- アクションが呼ばれたあと、期待したビューが表示されるかを確認する


## コントローラーテストのコードの書き方
- コントローラー内のメソッドで、あるアクションが呼ばれた際の挙動をチェック
- 1つのアクションにつき、先ほどの確認したいことの2つを確認する。

1.　アクション内で定義するインスタンス変数の値が期待したものになるかを確認する
2.　アクションが呼ばれたあと、期待したビューが表示されるかを確認する

**ひとつのアクションに対して2つ以上のexample(it '' do ~ end)が必要となる。**

```spec/controllers/◯◯_controller_spec.rb
describe ◯◯Controller do
  describe 'HTTPメソッド名 #アクション名' do
    it "インスタンス変数は期待した値？" do
　　"擬似的にリクエストを行ったことにするコードを書く"
      "エクスペクテーションを書く"
    end

    it "期待するビューに遷移できる？" do
      "擬似的にリクエストを行ったことにするコードを書く"
      "エクスペクテーションを書く"
    end
  end

```

## コントローラーテストのコードの書き方に関する注意

- 各アクションはそれぞれリクエストされる際のhttpメソッドが違う
 - よって、それぞれ少しずつテストの書き方が異なる。

以下、Railsに定められている7つのアクションのうちhttpメソッドが**get**であるアクションに関してのテストコードの書き方となります。
他アクションに関しては、随時追記していきます。


## コントローラーテストの準備

#### Gemfileに追記

```Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails'
  gem 'factory_bot_rails'
  gem 'rails-controller-testing'  ← 追記
end
```

そして、**bundle install**　！！


#### Specファイルを作成（コントローラー用）

①　specディレクトリ以下にcontrollersディレクトリを作成する。
②　①内に◯◯_controller_spec.rbを作成する。

- 今回は、groups_controller.rbのテストを行います。
- ということで、groups_controller_spec.rbを作成しました。
- 緑色になっているところです。

<img width="1280" alt="qiitatest_controller1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576541/72d03f7c-314d-84eb-d9b0-0f6d2fc9c90a.png">



## 基本コードの記入

作成した◯◯_controller_spec.rbに以下コードを記入する。

```◯◯_controller_spec.rb
require 'rails_helper'

describe ◯◯Controller do

end
```
groupsの場合

```groups_controller_spec.rb
require 'rails_helper'

describe GroupsController do

end
```



## テスト実行できるか確認

```
ターミナル

% bundle exec rspec spec
```

**上記コマンドでも問題ないが、特定したテストファイルのみ実行することができる。**

```
ターミナル

% bundle exec rspec spec/controllers/◯◯_controller_spec.rb

```


<img width="465" alt="qiitatestcon2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576541/4fa2f3bc-9ad1-f78b-022c-e66bd4f0d665.png">



と出力されれば準備おkです！　今回はここまで！



###テスト編、続きます!
######(httpメソッドがgetで呼ばれるアクションのコントローラーテストに入っていきます！)


#さいごに
日々勉強中ですので、随時更新します。
皆様の復習にご活用頂けますと幸いです。
【GCP】Cloud langage apiを検証してみた

#参考URL
https://to-kei.net/programming/python/google-natural-language-api/

#流れ
・プロジェクトを作成or既存のプロジェクトを選択
・APIを有効化
・認証情報を設定
　今回はAPIKeyを設定
・コマンドシェルを起動
・以下のコードを記載したファイルを作成

```Python:langage_test.py

# !/usr/bin/env python
# coding: utf-8
import requests 
 
#APIキーを入力
key = "YourAPIkey"
 
#感情分析したいテキスト
text = "こんにちは、今日もいい天気ですね。明日も晴れるといいなあ。でも最近晴れてるのに寒いですよね。"
 
#APIのURL
url = 'https://language.googleapis.com/v1/documents:analyzeSentiment?key=' + key
 
#基本情報の設定 JAをENにすれば英語のテキストを解析可能
header = {'Content-Type': 'application/json'}
body = {
    "document": {
        "type": "PLAIN_TEXT",
        "language": "JA",
        "content": text
    },
    "encodingType": "UTF8"
}
 
#json形式で結果を受け取る。
response = requests.post(url, headers=header, json=body).json()
 
#分析の結果をコンソール画面で見やすく表示
print("総合magnitude:",response["documentSentiment"]["magnitude"])
print("総合score:",response["documentSentiment"]["score"])
for i in response["sentences"]:
    print(i["text"]["content"],"magnitude:",i["sentiment"]["magnitude"],", score:",i["sentiment"]["score"])

```

・ファイルを起動
・結果が返ってくる

#ポイント
・GCEで検証しようとしたが、PHPをうまく反映できなかったので、参考URLの内容にした。

#詳細な手順の記載
1.プロジェクトを作成する。
※ここでは解説いたしません。
2.作成したプロジェクトにて、langage api の有効化をする
3.コンソール画面上部検索窓に「langage api 」を入力し、「Cloud　langage api」をクリック　
4.APIを有効にするをクリック
5.APImangerの認証情報にある認証情報を作成をクリック
6.APIキーをクリック
7.APIキーが作成されたことを確認し、作成されたAPIキーをコピーする
8.langage_test.pyファイルをローカルにコピーする
9.langage_test.pyファイルを開き、key = にコピーしたAPIキーを記載する
10.langage_test.pyファイルを上書きする
11.Cloud Shell を開く
12.Cloud Shell の右上にあるアップロードからlangage_test.pyファイルをアップロードする
13.以下のコマンドを実行し、ファイルを起動する
python langage_test.py
14.返ってきた値を確認する


#エラー
####１
  File "test.py", line 3
SyntaxError: Non-ASCII character '\xe3' in file test.py on line 3, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

https://techacademy.jp/magazine/22345
ここをみたら日本語がダメってことらしいので、日本語が記載されている部分をコメント含めて全部消したら、正常にいけた。

#今後やってみたいサイト
https://codelabs.developers.google.com/codelabs/cloud-nl-intro-ja/index.html?index=..%2F..next17-tok#8

https://cloud.google.com/natural-language/docs/quickstarts?hl=ja

https://www.qwiklabs.com/focuses/582?locale=ja&parent=catalog

https://www.casleyconsulting.co.jp/blog/engineer/252/
ブロックストレージとオブジェクトストレージの違いについて

#概要
AWSのS3のようなオブジェクトストレージについて、従来のブロックストレージとの違いについて理解できていなかったため調べました。

#ブロックストレージとは
従来から使用されてきたもの。HDD等のストレージをブロック単位で分割し、データを格納する。（1ブロック4KBのディスクに10KBのデータを書き込む場合は3ブロック使用するイメージ）

####AWSのサービス
#####「EBS」
　→「100GB」のEBSを作成した場合は、100GB分(のブロック)の料金

#オブジェクトストレージとは
クラウドにおいてよく利用される。
ディレクトリのような階層構造はなく、ストレージプールというオブジェクトの入れ物のみが作成され、メタデータ（作成日や作成者、データの種類、保存期間やコピー回数など）によって管理される。
ブロック単位ではなくファイル単位で保存するので、ピンポイントで取り出しが可能。
拡張性に優れていて、HTTPSでオブジェクトにアクセス可能。


####AWSのサービス
#####「S3」
　→保存容量が無制限。実際に保管したオブジェクト（データ）の分だけ料金が発生。


#両者の用途
####◎ブロックストレージ
　・頻繁に読み書きをおこなうデータベース
####◎オブジェクトストレージ
　・データが常に増加するシステム
　　（例：twitterの画像投稿…大量の画像投稿に耐える拡張性。クライアントからはHTTPSで直接アクセスしてもらう。）

#まとめ
・ブロックストレージとオブジェクトストレージでは、データを保存する際の単位に違いがある。

・拡張性が求められるクラウドサービス等においては、オブジェクトストレージを使用

・頻繁に読み書きを行うデータベース等においては、ブロックストレージを使用

#参考ページ
以下のページを参考にまとめさせていただきました。
https://xn--o9j8h1c9hb5756dt0ua226amc1a.com/?p=1822/
https://www.fujitsu.com/jp/products/computing/storage/lib-f/tech/beginner/object-storage/
外部からDjango REST FrameworkのAPIを叩いた時にNot Foundが出る時の解決法

# 問題

Nuxt.jsからDjango REST Framework（以下DRF）のAPIを叩いて特定の情報を表示させようとした時にDjango側のログにNot Foundが出ました。

まずはDjango側の不具合かと思い、一旦DRFのコンソールで確認しましたが、データは存在し、かつ閲覧できる状態です。
単純な問題ですが、うっかりミスをしていたので念のため記事として残しておきます。

# 解決法

以上の前提条件からNot Foundが起こっている場合、十中八九エントリーポイントの設定を間違えています。

そもそもの前提の話ですが、Djangoのルーティングではurls.pyに記述されているもの以外のurlが打ち込まれた場合は404のエラーハンドリングをしていない場合は無条件でNot Foundになります。なので、Nuxt.js側で呼び出すエントリーポイントの記述を間違っている可能性が高いです。

例えば、

```JavaScript
async asyncData ({ $axios, params }) {
    try {
      const user = await $axios.$get('user')
      return { user }
    } catch (e) {
      return { user: [] }
    }
```

といったような形でデータを取得しようとしていた場合、Django側のプロジェクトのurls.pyで

```Python:urls.py
urlspatterns = [
      path('api/',include('sample.urls')),
]
```

と記述し、

```Python:sample/urls.py
urlspatterns = [
      path('user/',UserListView.as_view()),
]
```

といったような形式の書き方しなければなりません。
なぜならば、DRFの書き方と同じように`api/user`といったアドレスからGETしないと`user`のデータを取得することはできないからです。
なのでDjango側でのルーティングに合わせた書き方をNuxt.js側でもしてあげなければならないんですね。

簡単なことですが、フロントエンドとバックエンドを分離させて外部からAPIサーバーを叩く場合は意外と見落としがちかなと思います。
少なくとも今回の自分はちょっとだけハマりました。
この件で前よりもルーティングの理解が深まったので良かったです。

この記事が誰かの助けになると幸いです。
PythonでABC160-Eを解く

### はじめに
緑diffを解けるようになりたいので、解けそうな緑diffを解きます。

### [Red and Green Apples](https://atcoder.jp/contests/abc160/tasks/abc160_e)

赤のリンゴは最大でも$X$個、緑のリンゴは最大でも$Y$個しか食べないので、$p,q$を降順で並べたときの前から$X,Y$個しか食べません。無色のリンゴは両方の色にできるので$p[:X],q[:Y],r$を連結して降順で並べます。その連結したリストの前から$X+Y$までの合計が答えになります。
また、Pythonのlistに対するsortは$O(N log N)$なので耐えます。

```python
x, y, a, b, c = map(int,input().split())
p = list(map(int,input().split()))
q = list(map(int,input().split()))
r = list(map(int,input().split()))

p.sort(reverse=True)
q.sort(reverse=True)
p = p[:x]
q = q[:y]
apple = p + q + r
apple.sort(reverse=True)
ans = sum(apple[:x+y])
print(ans)
```

### まとめ
緑になりたい。ではまた。
これまで記事にしたAI実装の近況まとめ@202004

以前に書いた記事の情報が古くなっているので下記についてここ最近の状況をまとめます。

## [AI初心者がOpenPoseのモバイル実装に取り組んだ話](https://qiita.com/otmb/items/b924b5f600db1ce11037)

軽量な姿勢推定についての需要があるとのことでIntelの方から論文が出ており、その実装がOpenCVの再トレーニング可能なモデルとして公開しています。
また、モバイル用途にしては珍しく精度について記載があります。
[Real-time 2D Multi-Person Pose Estimation on CPU: Lightweight OpenPose](https://github.com/opencv/openvino_training_extensions/tree/develop/pytorch_toolkit/human_pose_estimation)

参考までに精度はAP40行かない程度です。
また、初期のOpenPoseですがAP61.8
2018年公開の論文(v1.5)ではAP64.2
となっています。

試しにCoreMLに変換を試したところ一応動作しましたので[サンプルコード](https://gist.github.com/mbotsu/8c712093884cb64f9477881cb182dbc2)を公開しています。
[issue](https://github.com/Daniil-Osokin/lightweight-human-pose-estimation.pytorch/issues/69)にも一応報告しました。

あとは、[C++](https://github.com/opencv/open_model_zoo/tree/master/demos/human_pose_estimation_demo)の実装もありますので高速に動かせると思います。

## [PoseNetをマルチプラットフォームで実装してみた](https://qiita.com/otmb/items/561a62d3413295cc744e)

iOSではApple公式のPoseNetが公開となりました。
  [Detecting Human Body Poses in an Image](https://developer.apple.com/documentation/coreml/detecting_human_body_poses_in_an_image)
本家が出てくるとお試しで書いた私のコードはお役御免ですね＾＾：

### 追記(2020/05/22)

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Apple公式のPoseNetのモデル <a href="https://t.co/86X4RVDnIX">https://t.co/86X4RVDnIX</a> のライセンスに &quot;Please see <a href="https://t.co/6iCAU2c2lu">https://t.co/6iCAU2c2lu</a> for license information for the converter&quot; とあるんだけど、これってAppleが自前でなく <a href="https://twitter.com/mb_otsu?ref_src=twsrc%5Etfw">@mb_otsu</a> さんのコンバータ使ってモデル作ったってこと？<br><br>参考: <a href="https://t.co/pdVXOQY0uk">https://t.co/pdVXOQY0uk</a></p>&mdash; koher (@koher) <a href="https://twitter.com/koher/status/1263700248053993473?ref_src=twsrc%5Etfw">May 22, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

本当に書いてあった。びっくりした。
きっと使える部分を参考にしたのでしょうね。
<img width="767" alt="LICENCE" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35973/0c8f187b-7331-fcee-50f8-16c7b303d005.png">



## [手認識が実用レベルに到達した件](https://qiita.com/otmb/items/3e43be59de87e9e5a146)

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ハンドジェスチャーを試しに実装したので記事を書きました。<a href="https://t.co/2tTExx2ig4">https://t.co/2tTExx2ig4</a><a href="https://twitter.com/hashtag/MediaPipe?src=hash&amp;ref_src=twsrc%5Etfw">#MediaPipe</a><a href="https://twitter.com/hashtag/TensorFlow?src=hash&amp;ref_src=twsrc%5Etfw">#TensorFlow</a> <a href="https://twitter.com/hashtag/HandTracking?src=hash&amp;ref_src=twsrc%5Etfw">#HandTracking</a> <a href="https://t.co/DdbayV5cIn">pic.twitter.com/DdbayV5cIn</a></p>&mdash; o2 (@mb_otsu) <a href="https://twitter.com/mb_otsu/status/1207658291074985985?ref_src=twsrc%5Etfw">December 19, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


HandTrackingですが、MediaPipeがベータ版ということで扱いが良くなかったのですがTendorFlow.jsで公開となったそうです。
今から試す方は[handpose](https://github.com/tensorflow/tfjs-models/tree/master/handpose)を利用するのが良さそうです。

以上。近況についてのまとめになります。
お役に立てば幸いです。
ふりかえりのアクティビティ紹介：学習マトリックス

# この記事について

ふりかえりの手法を1つずつ紹介していきます。
ふりかえりをより楽しくしていくためにお使いください。

# 出典

この内容は [ふりかえり読本 学び編～経験を力に変えるふりかえり～](https://hurikaeri.booth.pm/items/1317813) 6章(6.2) で紹介しています。

# 出典（原典）
Esther Derby・Diana Larsen・角 征典（訳）（2007）．アジャイルレトロスペクティブズ 強いチームを育てる「ふりかえり」の手引き．オーム社。
こちらを参考に、ファシリテーションテクニック等を汎化したものが本記事となります。

# 実施例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221788/a78f4ab9-97ae-d4db-9a72-0ab23aee9041.png)

# 目的・ねらい

「よかったこと、続けたいこと」「変えたいこと」「新しいアイデア・気付き」「感謝」の4つの質問をすることでカイゼンを促します。このアクティビティで特徴的なのは「感謝」です。感謝を伝え合うことによって、チームの関係性の向上が図れます。

# 所要時間

20分～30分

# ステップ

「よかったこと、続けたいこと」「変えたいこと」「新しいアイデア・気付き」「感謝」の4つの軸で、意見を記入します。

まずは「よかったこと、続けたいこと」「新しいアイデア・気付き」「感謝」の3つに対して意見を出し、チーム内で共有します。最後に「変えたいこと」を考えていきます。意見を付箋に書いて共有、を繰り返しながら、マトリクスを埋めていきます。

意見が多い場合は、全員のアイデアをそれぞれ読み上げることはせず、眺めるだけで共有の効果は得られます。ただし、感謝だけは読み上げて共有したほうが、チームビルディングの効果は高まります。

# 事前準備・道具

フリップチャート・ホワイトボードを4つのセクションに区切っておきます。また、4色の付箋を用意しておくと、それぞれのセクションが記載しやすくなります。

# ファシリテーションのポイント

意見を出す順番には気を配りましょう。最初に「変えたいもの」を出そうと考えると、ほかのポジティブな意見が出にくくなってしまいます。

「変えたいもの」に関しては、問題点を挙げるだけでなく、前向きに変えたいことを挙げるようにすると、実験に富んだアイデアを集められます。ふりかえりがより前向きでポジティブなものになっていくでしょう。

このアクティビティは、アクションを具体的に決めるための活動は含まれません。別途アクションを決めるためのアクティビティを組み合わせましょう。

# バリエーション

単純に4軸を考えるのではなく、事前に時系列に出来事や感情を収集しておき、そのデータを4つの軸に分類してみる、という手法でも活用できます。チームの好みに合わせてカスタマイズしてみてください。

# 他の手法を知るには

[Qiita - ふりかえりを拡張する「ふりかえりチートシート」](https://qiita.com/viva_tweet_x/items/b06f56ce83038fc2bb8f) で様々な手法を紹介しています。
コロナに負けるな！Typescript&Nuxt.js を使って今風なデザインのポートフォリオを作成した話

##背景
ゴールデンウィークにも関わらずコロナで外出する事が出来ず、家にいる時間が勿体ないので、スキルアップも兼ねてポートフォリオを作成しました。

このポートフォリオは、**Nuxt.js & Typescript を利用して作成しており、最近のフロントエンドの技術を出来るだけ利用して制作するように心がけました。**


##完成したポートフォリオ
![portfolio_mockup.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23815/44242531-8190-b04a-9e73-c0e7abc1ac3c.jpeg)



https://profile.isystk.com/



##制作にかかった時間
- デザイン構想策定・・・2日
- HTMLコーディング・・・2日
- Nuxt.js アプリ化・・・2日


##デザイン構想策定
良いWebサイトを作るためには、良いWebサイトが何かを知る必要があります。自分が良いサイトだと思っていても世の中の人が見たらそれは普通のサイトだと感じるかもしれません。
自分の感性を確認するために**世の中で良いサイトと言われているWebサイトを調査しました。**

####Webデザインを参考にしたサイト
| サイト名         |    URL   |
|:---------------|:------------------|
| io3000.com     |      https://io3000.com/   |
| イケサイ        |      https://www.ikesai.com/    |



#####次に、自分のポートフォリオに組み込みたい内容や機能を整理していきます。

- 自己紹介
- プログラミングのスキルセット
- ブログや過去に制作した作品の紹介
- Twitterのタイムラインとフォロワー数
- FacebookやGithubなどのコンタクト情報

#####また、アプリに組み込みたいこだわりやアニメーションなどの細かな機能もここで決めました。
- レスポンシブデザイン
- ドロワーメニュー
- チャート表示
- アニメーション表示
- モックアップ画像
- SNS連携
- メインビジュアルに動画を表示したい

**ある程度やりたい事（素材）が頭の中で固まってきたら構成を紙に書いてみると良いと思います。**

サイトの構成が決まったらWF（ワイヤーフレーム）を作成していきます。
私はエンジニアで、Webデザインの知識は少ないですがYouTubeやUdemyなどを利用してWFを作成する為の簡単なPhotoshopの操作方法は予め学びました。

作成したPSDファイル↓
https://demo.isystk.com/design/psd/portfolio.psd

##HTMLコーディング
WFが完成したらHTMLファイルをコーディングしていきます。
最近のWebサイトは、スマホからのアクセスが70%を超えておりPCサイトからのアクセスが減少しています。
その為、**Webデザインはスマホファースト（スマホからのアクセスを優先したデザイン）となるようにして、PCからアクセルされた場合でも違和感なく表示出来るようレスポンシブデザインとなるようにしました。**

HTMLコーディングの段階で、CSS3やjavascript を利用したアニメーション処理も組み込んでいきます。

###アニメーション機能
- ドロワーメニュー

スマホ表示の場合に右上にメニューボタンを表示します。タップするとスライドでメニューが表示され、ハンバーガーメニューのボタンがバッチボタンに切り替わるアニメーションです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23815/f1e3add6-ba49-b184-174f-163e5f9e8ae7.gif" width="200px">


- フェードインアニメーション

画面をスクロールしてコンテンツがウィンドウ範囲内に含まれた際にフェードインさせて表示するアニメーションです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23815/2761ef6e-a3f3-30d9-8af3-8351dbe45b52.gif" width="200px">


- チャート表示

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23815/4d697557-5fe0-e510-54ab-0e1680b9e27c.gif" width="400px">



- 数字をシャッフルしてから表示する

Twitterのフォロワー数を初期表示の際にシャッフルさせるアニメーションです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23815/5bb39fcc-d923-fe02-ab10-b84737794e12.gif" width="200px">


- ページトップに戻るアニメーション

一定位置までスクロールすると右下に「ページトップに戻る」為のボタンを表示させて、クリックするとページトップまでスクロールさせるアニメーションです。

##Nuxt.js & Typescript でアプリ化

HTMLをそのまま公開しても良かったのですが、フロントエンドエンジニアとして働いていることもあり、折角なので最近流行りのNuxt.js & Typescript を利用してアプリ化しました。

#####Nuxt.js で対応した機能
- 表示内容をjsonファイルから読み込んで表示
- vue-charts
- PWA対応
- GA設定


##苦労した点
HTMLコーディングの際にjQueryを利用してアニメーションを作成していたのですが、Nuxt.jsにする際に、脱jQueryで書き直す必要が出てしまったのでHTMLコーディングの時点でjQueryを使わないようにした方が良かったなぁと思います（笑）

##ソースコード
https://blog.isystk.com/web_production/portfolio/829/
PHP bindValue と bindParam

2020/5/7
-

PDOStatement::bindParam — 指定された変数名にパラメータをバインドする
PDOStatement::bindValue — 値をパラメータにバインドする

```php
$stm = $pdo->prepare("select * from users where user = :user");
$user = "jack";
//
$stm->bindParam(":user",$user);
//エラー
//$stm->bindParam(":user","jack");

$stm->bindValue(":user",$user);

$stm->bindValue(":user","jack");
```
---

2020/5/8
-
bindValue と　「？」

```php
<?php
/* バインドされた PHP 変数によってプリペアドステートメントを実行する */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < ? AND colour = ?');
$sth->bindValue(1, $calories, PDO::PARAM_INT);
$sth->bindValue(2, $colour, PDO::PARAM_STR);
$sth->execute();
?>
```
---
Vue.js + Jerseyデスクトップアプリ

先日、簡易的なデスクトップアプリの実装例として[vue-nest-desktop-app](https://github.com/unhurried/vue-nest-desktop-app)（[Vue.js + NestJSでデスクトップアプリを実装する](https://qiita.com/unhurried/items/01dbb48a5ea872a22778)）を紹介したが、バックエンドの開発はNode.jsよりもJava（Spring Boot + Jersey）の方が慣れているので、バックエンドをJavaで置き換えた[vue-jersey-desktop-app](https://github.com/unhurried/vue-jersey-desktop-app)を作成した。

以下では開発のポイントを簡単にまとめている。

#### アプリケーション構成

![システム構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186068/73403486-c948-3e8d-39b4-1e6170e02e29.png)

* バックエンドはSpring Bootで開発している。埋め込みTomcatを組み込んだ実行可能jarファイル（いわゆるfat jar）にビルドして配布し、ローカルで起動したアプリケーションサーバーにブラウザからアクセスして利用する構成としている。
* フロントエンドはVue.jsで実装し、ビルドしたHTML、CSS、JavaScriptをバックエンドのWebサーバー機能（spring-boot-starter-web）で静的ファイルとして配信する。
* 主な機能はバックエンドでRestful API（spring-boot-starter-jersey）として提供し、フロントエンドからのAPI呼び出しで利用する形としている。

#### Spring Bootのデスクトップアプリ化

Spring Bootをデスクトップアプリ化するために以下の工夫を入れている。

* ログをSwingで実装したウィンドウに表示し、ウィンドウを閉じたときにアプリケーションが停止するようにする。（jarを実行したときにアプリケーションがバックグラウンドで起動するだけでは、起動中かどうかの判別や、プリケーションの停止がしにくいため。）
  * 参考：[ConsoleFrame.java](https://github.com/unhurried/vue-jersey-desktop-app/blob/v0.0.1/backend/src/main/java/vjda/gui/ConsoleFrame.java)
* アプリケーションサーバーはローカルマシンの空きポートを探して起動し、起動後にシステム（デフォルト）ブラウザでフロントエンドのトップ画面を自動で開く処理を入れている。
  * 参考：[Browser.java](https://github.com/unhurried/vue-jersey-desktop-app/blob/v0.0.1/backend/src/main/java/vjda/gui/Browser.java)

#### 外部のRestful APIの呼び出し

ローカルで動作するWebサーバーでホストされたフロントエンドにブラウザでアクセスするため、他のオリジンとなる外部のWeb APIにフロントエンドから直接アクセスすることができない。そのため、バックエンド側でAPIのプロキシ機能（開発用のクローズドなAPIにもアクセスできるようにSSHポートフォワーディングにも対応）じを実装している。

参考：[ApiProxy.java](https://github.com/unhurried/vue-jersey-desktop-app/blob/v0.0.1/backend/src/main/java/vjda/proxy/ApiProxy.java)
サーバー上に簡単に git でバックアップを取る方法

# サーバー上に git でバックアップする簡単な方法

## 状況設定

- サーバー (データを保管する容量がある場所)
    -  ユーザー名 : yamada
    -  ドメイン : univ.ac.jp
- クライエント (自分の作業パソコン)
   
の２つのマシンがあり，どちらにも git がインストールされているとする．
クライエントのソフトウェアや書類などのバックアップをサーバー側にしたいとする．

[rsync] (https://www.atmarkit.co.jp/ait/articles/1702/02/news031.html) を，--link-dest というオプション付きで使うことで，単純にコピーするだけではなくて，差分やバージョン管理が可能である．[rsyncの--link-destでの差分バックアップ](https://jyn.jp/bash-rsync-link-dest/)など参照ください．git が使い慣れている人は，次に示す 4つのステップで実現できるので紹介します．


## サーバー-クライエントのgit環境の構築例

４つのステップのうち，２つはサーバー側の２つのコマンドです．
まずは，サーバー側に移動して，サーバーに git がインストールされているか確認して，されてなければまずは [git をインストール](https://git-scm.com/book/ja/v2/使い始める-Gitのインストール)しましょう．

まずは，一つ目のステップになります．サーバー側にいることに注意してください．

1) XX.git というディレクトリを作成する．

``` bash:
$ mkdir -p ~/yourdir-in-server/hene.git
$ cd ~/yourdir-in-server/hene.git
```

ここでは，適当な名前(hene)を使っていて，hene.git というディレクトリを生成し，cd でその場所に移動します．名前は自分の好きな名前で構いません．


2) git init の実行

``` bash:
$ git init --bare --shared=true
Initialized empty shared Git repository in /...../hene.git/
```

これで git レポジトリとしての初期化が行われます．


次に，クライエント側，つまり自分が作業しているパソコンでの作業になります．
ここでも git がインストールされてなければまずはインストールしましょう．

3) git init を実行します．

自分がgit化したいファイルのある一番上のディレクトリに移動します．
その場所に移動したら，

``` bash:
$ git init 
Initialized empty Git repository in /.../.git/
```

を実行します．

4) git remote の実行

``` bash:
$ git remote add origin yamada@univ.ac.jp:~/yourdir-in-server/hene.git
```

を実行する．これが最低限の設定になります．

git pull は，[カレントブランチの設定](https://gotohayato.com/content/455/)が必要なので，

``` bash:
$ git branch --set-upstream-to=origin/master master
```

と一回だけ打っておきましょう．


## 実行例

では，クライエント側で動作確認をしてみましょう．
まずは，git の リモートの設定が自分の意図したものかを確認しましょう．

``` bash:
$ git remote -v
origin	yamada@univ.ac.jp:~/yourdir-in-server/hene.git (fetch)
origin	yamada@univ.ac.jp:~/yourdir-in-server/hene.git (push)
``` 

次に，git push の確認です．

``` bash:
$ git add .
$ git commit -m "test" 
$ git push origin master
numerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 10.58 KiB | 5.29 MiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To ssh://univ.tmu.ac.jp/.../hene.git
 * [new branch]      master -> master
``` 

これで，git push が成功することを確認しましょう．
そのほか，git pull, git log など，基本的な操作を確認して問題なければ大丈夫です．
Cloud FunctionとPCローカルからGoogle Home にしゃべらせるアーキテクチャを考えてみる。

# 当初案
![通知アーキテクチャ-当初イメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87538/97756be3-8a1e-8f74-3a76-3336b6a3fa65.png)

* Cloud FunctionsがしゃべらせるAPI
* Cloud Taskから、Queueを取得するLocalプロセス
* Localプロセスは、Queueからテキストを受信して、Text-To-SpeechにてMP3ファイル化し、配信する

## 流れ
1. 何らかのLocalプロセスもしくはCloudプロセスからしゃべらせるAPIへメッセージを送信
2. Cloud Taskへメッセージを載せたQueueをプッシュ
3. 自作のローカルプロセスが定点で取得
4. 取得したメッセージをMP3化
5. MP3を一度だけ返すサーバを起動して、GoogleHomeへChromecast通知
6. Google Homeがしゃべる


# 第二案
![通知アーキテクチャ-調査後第二案.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87538/ecc76ef7-ffdf-bd93-af84-8d78ae633b35.png)

* Cloud FunctionsがしゃべらせるAPI
* Cloud PubSubは、しゃべらせるメッセージをWebSocketで公開・配信するプロセス
* Localプロセスは、PubSubを購読して、テキスト受信後、Text-To-SpeechにてMP3ファイル化し、配信する

## 流れ
1. 何らかのLocalプロセスもしくはCloudプロセスからしゃべらせるAPIへメッセージを送信
2. Cloud PubSubがサブスクライバーへ配信
3. ローカルのサブスクライバープロセスが取得したメッセージをMP3化
4. MP3を一度だけ返すサーバを起動して、GoogleHomeへChromecast通知
5. Google Homeがしゃべる

# 作った
問題なく構築できた。