OmniAICreator/Qiita-1.07M huggingface dataset:
C言語における構造体の宣言の仕方を理解しよう。

##構造体を使用するメリット
- 文字列を含め、全要素を一括代入ができる。
- 再帰的に使用して、リスト構造を作れる。

*リスト構造については最後の参考URLにわかりやすい解説があります。

##構造体の型を宣言する
structの後に構造体名を付けて宣言

```c
struct 構造体名{
};
```


- Example

```c
struct student {
	int year;	/* 学年 */
	int number;	/* 出席番号 */
	char name[64];	/* 名前 */
	double stature;	/* 身長 */
	double weight;	/* 体重 */
};
```
##新しい型として構造体の型を宣言する
C言語では、新しい型を宣言するtypedef(タイプデフ)が用意されています。

```c
typedef 新しい型の形 新しい型名
```

```c
struct student_tag {
	int year; /* 学年 */
	int number; /* 出席番号 */
	char name[64]; /* 名前 */
	double stature; /* 身長 */
	double weight; /* 体重 */
};
/*
構造体student_tag型のstudent型を宣言
宣言以降、studentを型名として使用することができる。
*/
typedef struct student_tag student;
```
###上記のtypedefを使用した宣言の省略した書き方
```c
typedef struct student_tag {
	int year; /* 学年 */
	int number; /* 出席番号 */
	char name[64]; /* 名前 */
	double stature; /* 身長 */
	double weight; /* 体重 */
} student;
```

###さらに省略した書き方

```c
typedef struct {
	int year;	/* 学年 */
	int number;	/* 出席番号 */
	char name[64];	/* 名前 */
	double stature;	/* 身長 */
	double weight;	/* 体重 */
} student;
```

##再帰的に構造体を利用する際の書き方
ポインタを使用する場合は、今まで説明した省略形が使えません。定義されていない型が、型の中に出てきてしまうため、コンパイル時にエラーが発生します。

なので、先に型を宣言する方法を使います。

```c
typedef struct list LIST;
struct list{
  unsigned int number;
  char name[256];
  LIST *next;
} ;
```

もしくは見にくいかもしませんが、より再帰をイメージしやすいように書くと下記のようになります。

```c
typedef struct List List;
struct list{
  unsigned int number;
  char name[256];
  List *next;
} ;
```
Listの構造体を持つList型を宣言してから、Listの構造体を宣言しています。

C言語では、型の中身である構造体が決まっていなくても、宣言できてしまうのです。

なぜかと言えば、宣言しているのは、__Listという言葉を型を示す言葉として使用しますよ！__ということであって、領域を確保しているわけではないからです。





##使用する関数の中で宣言
関数の中で宣言することで使えるようになります。

###typedefで型名として宣言しない場合
```c
int main(void)
{
	struct student data;
	return 0;
}
```

###typedefで型名として宣言する場合
```c
int main(void)
{
	student data;
	return 0;
}
```

#####参考URL
異なる型の変数をまとめる - 苦しんで覚えるC言語
https://9cguide.appspot.com/16-01.html

リスト構造をC言語プログラムの実例を用いて解説 | だえうホームページ
https://daeudaeu.com/programming/c-language/list-structure/
Golang製のSlackAPI(nlopes氏の)がレポジトリ引っ越したらしい(´・ω・｀)



ちょうどSlackBotの開発をしていたところ気がついたのでメモ。



## 旧レポジトリ( 2020年2月27日時点 )

```
レポジトリURL: https://github.com/nlopes/slack
```

## 新レポジトリ( 2020年2月27日時点 )

```
レポジトリURL: https://github.com/slack-go/slack
```

## README( nlopes/slack )

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195292/8219701b-187f-be3f-9842-4b7ffee11517.png)

上記は2020年2月27日時点の `nlopes/slack` のREADMEですが以下の

>but no guarantees are made on how up to date it will be

からとりあえずこれから入るアップデートが必要な機能とかは保証されないうんぬんでちゃんと新レポジトリから取った方が良さそうですね！

また、旧に `nlopes/slack` 使えなくなったらとりあえず新レポジトリから引っ張ってくれば良さそうですね :)
WEBフォント、Font Awesomeを外してみた


日本語webフォント「Noto Sans JP（google font）」と「Font Awesome」を利用してページ作成。PageSpeed Insightsで測定。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590318/0bbd939e-b198-7389-9d29-50ad583e84c9.png)

リクエスト数、フォントが画像を超えている。。。

取り急ぎNoto Sans JPとFont Awesomeを外してみる
合わせてsassのコンパイルをcompressedにしてみる

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590318/8e6cba75-e1a5-3a60-3039-1ff04c08fc40.png)

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590318/8af653f9-8543-87cf-245a-fcddc29cde45.png)

「92」いただきました！

第三者項目も同時に減りました。
Pythonを用いてCSVファイルを読み込んでみた

### 実行環境
・Mac OS X

PythonからCSVファイルを閲覧しようと思い、実際にやってみました。

まず、Python公式ドキュメントのCSVモジュールの使用例のコードをそのまま利用してみました。

```python:read.py
import csv

with open('hoge.csv', newline='') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)
```

早速、ターミナルで実行してみましょう。

```
$ python3 read.py
```


すると、次のようなエラーが出てしまいました。

```ターミナル
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8e in position 1: invalid start byte
```

何やら文字エンコードに問題があるようです。そこで、次のようにエンコードをcp932に指定してみました。

```python:read.py
import csv

with open('hoge.csv', newline='', encoding='cp932') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)
```

こうしてエラーは解決し、無事にPythonスクリプトからcsvファイルを開くことができました。
appsync subscriptionで引数使うときmutationの戻り値に含めないと動かない

Appsyncでsubscription使ったときにハマったので共有します。

例えば下記のsubscription定義があるとします。

```
type Subscription {
	subscribeToNewMessage(conversationId: ID!): Message
		@aws_subscribe(mutations: ["createMessage"])
}
```
"createMessage" Mutationが実行された、かつ、conversationIdがある値のときにsubscribeしたいって定義です。

これがNuxt.jsで作ったクライアントから上手く動かなかったのですが、クライアントから実行するMutationの書き方に問題がありました。

動かなかったときのMutationは次です。

```
const createMessage = /* GraphQL */ `
  mutation createMessage(
    $id: ID!
    $content: String
    $conversationId: ID!
    $s3Key: String
  ) {
    createMessage(
      content: $content
      conversationId: $conversationId
      id: $id
      s3Key: $s3Key
    ) {
      id
      content
      sender
    }
  }
`;
```

次に動いたときのMutationはコレです。

```
const createMessage = /* GraphQL */ `
  mutation createMessage(
    $id: ID!
    $content: String
    $conversationId: ID!
    $s3Key: String
  ) {
    createMessage(
      content: $content
      conversationId: $conversationId
      id: $id
      s3Key: $s3Key
    ) {
      id
      conversationId     ←ここ
      content
      sender
    }
  }
`;
```

subscriptionの引数に定義したconversationIdを戻り値に指定したら動きました。

どうやら、mutationの引数ではなく、戻り値を見て発火しているみたいです。
viエディタ　改行削除　J

コマンドモードで J(大文字)を入力する

例:
あいうえお
かきくけこ

1.[ESC]キーを押して、コマンドモードにする
2.あいうえお　の行にカーソルを移動する(横の位置はどこでも良い)
3.J(大文字)を入力する [Shift] + [J]
4.あいうえおかきくけこ　となる
【MySQL】自動起動の意外な落とし穴

##はじめに
```
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
```
ログインする際のエラーを解決するためにサーバーを一旦停止したかった時のことです。
自動起動設定をしたことをすっかり忘れていて、時間がかかったのでまとめておきます。

##そもそもの自動設定は、どうやってた？
brewのhomebrew-servicesを使っていた。

公式サイトはこちら。
https://github.com/Homebrew/homebrew-services

###使い方
MySQLを自動起動にする。

```
$ brew services start mysql

==> Successfully started `mysql` (label: homebrew.mxcl.mysql)
```

これだけ。

自動起動を止めたい時は、

```
$ brew services stop mysql

Stopping `mysql`... (might take a while)
==> Successfully stopped `mysql` (label: homebrew.mxcl.mysql)
```

一覧を取得したい。

```
$ brew services list

Name       Status  User   Plist
mysql      started ------ /Users/------/Library/LaunchAgents/homebrew.mxcl.mysql.plist
postgresql started ------ /Users/------/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
```

##自動起動がオンになっていると、停止コマンドは成功するが確認すると止まってない。。。
```terminal
% mysql.server stop
Shutting down MySQL
. SUCCESS!

% mysql.server status
 SUCCESS! MySQL running (21754)
```
パッと見「サクセス！！！」って完全に停止できてると信じていたけれど、騙されました。
いざコマンドで確認したところ、普通に動いてて、意味がわからなかった。。。
そして、自動起動について書かれてる記事をみた時に、ハッと思い出して、、、
今に至ります（笑）

##おわりに
便利なものをインストールして、効率を上げるのはいいことだけど、しっかり把握しておかないと今回のようなことになってしまうので注意します。
【ROS2】python形式のlaunchでbagファイルを再生する方法

<!-- # 【ROS2】python形式のlaunchでbagファイルを再生する方法 -->

# はじめに

ROS2のlaunch.pyでbagファイルを再生する方法について記述します．

# テスト環境

- Ubuntu 18.04
- ROS Eloquent

# bagの再生の方法

```py
import launch

def generate_launch_description():
    return launch.LaunchDescription([
        launch.actions.ExecuteProcess(
            cmd=['ros2', 'bag', 'play', 'your_bag_dir'],
            output='screen'
        )
    ])
```

# 関連記事

- [【ROS2】python形式のlaunchでremapとparameterを記述する方法](https://qiita.com/RenFukatsu/items/a1e08ea3db2a82a53f12)
【解説付き】PythonでFizz Buzz (paizaランク C 相当)を解く

# 初めに
paizaのレベルアップ問題集を解いていたのですが、模範解答がなかったので解説付きで自分で作ってみました。
言語はPython3です。

# 問題
Paizaのスキルチェック見本問題 Fizz Buzz (paizaランク C 相当)
https://paiza.jp/works/mondai/skillcheck_sample/fizz-buzz?language_uid=python3
paizaは登録が無料ですぐにできるので、とりあえず登録してみることをおススメします。


>### 下記の問題をプログラミングしてみよう！
>> 整数 N が入力として与えられます。

>>1からNまでの整数を1から順に表示してください。

>>ただし、表示しようとしている数値が、

>>・3の倍数かつ5の倍数のときには、"Fizz Buzz"
>>・3の倍数のときには、"Fizz"
>>・5の倍数のときには、"Buzz"

>>を数値の代わりに表示してください。

>###入力される値
>>入力は以下のフォーマットで与えられます。

>>N

>>N は1以上N以下の整数です。


>>入力値最終行の末尾に改行が１つ入ります。
>>文字列は標準入力から渡されます。

>###期待する出力
>>最後は改行し、余計な文字、空行を含んではいけません。

>###条件
>>すべてのテストケースにおいて、以下の条件をみたします。

>>・1 ≦ N ≦ 100
>>・N は整数

>####入力例1
>>5

>####出力例1
>>1
>>2
>>Fizz
>>4
>>Buzz

>####入力例2
>>20

>####出力例2
>>1
>>2
>>Fizz
>>4
>>Buzz
>>Fizz
>>7
>>8
>>Fizz
>>Buzz
>>11
>>Fizz
>>13
>>14
>>Fizz Buzz
>>16
>>17
>>Fizz
>>19
>>Buzz

# 解説
###入力値を受け取る
入力値は0-100の整数値です。
input関数を用いて入力値を受け取った後、int関数を用いて、str型からint型に**型変換**しておきます。

```python:fizz-buzz_1.py
n = int(input())
```

### 数値を順に表示する
次に、代わりに表示しなければいけない数値を探します。今回は、1からnまでの整数のを順番に探していけばよいので、**range関数**を用います。
この時注意しなければならないのが、range関数の**範囲の指定**の仕方です。

range関数で引数を二つ入力した場合は、第一引数は~~begin~~ start、第二引数は~~end~~ stopとなります。
この時、~~end~~ stop引数は、その数自身を含まず、一つ前の整数を出力するように指定します。

つまり、`range(1, 5)`とした場合の出力は、1,2,3,4となり、**5は含まれません。**
1,2,3,4,5 と出力したい場合は、`range(1, 5+1)`と指定する必要があります。

```python:range_sample.py
print(list(range(1,5)))    # [1,2,3,4]
print(list(range(1,6)))    # [1,2,3,4,5]
```
今回の場合、1からnまでの整数値が欲しいので、range関数には **1, n+1** と引数を渡します。
for文と組み合わせるとこのようになります。

```python:fizz-buzz_2.py
n = int(input())
for i in range(1, n+1):
    print(i)
    
"""
n = 5の時、
1
2
3
4
5
"""
```

### FizzBuzzを見つける
次に、fizzBuzzに変換しなければならない数値を判定します。
そのために　% (余りを求める代数演算子)を使用します。

もし、n を 3で割った余りがゼロであれば、nは 3の倍数です。
もし、n を 5で割った余りがゼロであれば、nは 5の倍数です。
もし、n を15で割った余りがゼロであれば、nは 3の倍数であり、かつ5の倍数です。

3の倍数であり、かつ5の倍数ということは、**15の倍数**であるということです。

今回はif-elif文を用いて判定します。

この時、**判定する順番**は注意が必要です。
~~n が3、または5の倍数であるかどうかの判定を、
15の倍数であるかどうかの判定よりも先に書いてしまうとうまくいきません。~~
>nが3、または5の倍数であるかどうかの判定を、
>15の倍数であるかどうかの判定よりも先に書く場合には少し工夫が要ります。
>@shiracamus様が指摘された方法があり、下のコメント欄で確認してみてください。
>今回は判定する順番により解決したいと思います。


```python:if_sample.py
# ダメなコード
n = 15
if n%3 == 0:
    print("nは3の倍数です。")
elif n%5 == 0:
    print("nは5の倍数です。")
elif n%15 == 0:
    print("nは3の倍数かつ5の倍数です。")
else:
    print("nは3の倍数でも5の倍数でもありません。")
    
# nは3の倍数です。
```
もしnが15の倍数であった場合、15の倍数ではなくて、3、または5の倍数と判定されてしまいます。
上から順番に処理されていくことを意識しておきましょう。

したがって、まず最初に、15の倍数であるかどうかを判定します。
その後に、5の倍数であるか、3の倍数であるかを判定するとうまくいきます。

```python:fizz-buzz_3.py
n = 15
if n%15 == 0:
    print("nは3の倍数かつ5の倍数です。")
elif n%5 == 0:
    print("nは5の倍数です。")
elif n%3 == 0:
    print("nは3の倍数です。")
else:
    print("nは3の倍数でも5の倍数でもありません。")
    
# nは3の倍数かつ5の倍数です。
```


一般的に、if-elif文を書くときは狭い条件の方から先に書くとうまくいくことが多いようです。



# 解答コード
```python:fizz-buzz.py
n = int(input())
for i in range(1, n+1):
    if i%15==0:
        print("Fizz Buzz")
    elif i%5==0:
        print("Buzz")
    elif i%3==0:
        print("Fizz")
    else:
        print(i)
```

# 参考
https://qiita.com/KoyanagiHitoshi/items/3286fbc65d56dd67737c

# 最後に
過去の自分が引っかかったところを詳しく説明したつもりです。
まわりくどくて分かりにくいところもあったかもしれませんが、
なにか気になる点があれば気軽にコメントしてくださいね。
追加するカラムの位置を指定する

#追加するカラムの位置を指定する
よく業務で使用する割に毎回調べているから備忘録として・・・

追加するカラムの位置を指定することもできます。
位置の指定には、「AFTER」と「FIRST」を使います。

使い所としては、新しく追加したカラムがPKとして運営するときに使用。
A5M2でTableを確認する際にPKは左側にまとめたい。
	
ALTER TABLE テーブル名 ADD 新規カラム名 型情報 AFTER 既存カラム名;
ALTER TABLE テーブル名 ADD 新規カラム名 型情報 FIRST;

```SQL:example
ALTER TABLE m_achievement ADD language_test varchar(255) NOT NULL COMMENT '表示言語' AFTER achievement_code;
```

メモメモ・・・・
今すぐ出来るおっさんエンジニアに贈る疲れ目対策

# 結論
**あくまで個人の体感ですw**

1. モニタを一番暗くする
2. 色数を少なくする
3. たまに遠くの壁に貼ってる文字を見る
4. 1時間に10分は無理やりにでも休憩する
5. まばたきを意識して増やす

# モニタを一番暗くする
* モニタもしくはノートパソコンの明るさを一番暗くします
 * 最初は違和感しかありません
 * 慣れてきます
 * 慣れない場合はコントラストを少し上げましょう
 * それでも慣れない場合は我慢ですw

# 色数を少なくする
* ターミナルで派手な色にしてる場合は、できるだけ色数を少なくします
* 合わせて暖色系の色合いにしてあげると自分の体感ですが疲れ目がマシな気がします
* vimのcolorschemeとかターミナルの色とか喜び勇んでいろんな色が使われてるものを利用しがちですが、そこは我慢して白黒ぐらいな勢いのほうが目は疲れにくいです

# たまに遠くの壁に貼ってる文字を見る
* カレンダーとかエレベーター停止のお知らせとか法定停電のお知らせとかをぼーっと見る
* 遠くをみることで目のピント機能を司る筋肉の緊張がほぐれます
 * ずっと同じ姿勢してるといろいろ痛くなってくるのと同じ

# 1時間に10分は無理やりにでも休憩する
* たばこ吸う人は休憩しやすいですが、吸わないひとははばかられるかもしれませんね
* でも休憩を無理矢理にでもしましょう
* コーディングのってたり煮詰まってたりすると休憩したくない気持ちはわかりますが、お茶でもいれて休憩しましょう

# まばたきを意識して増やす
* 仕事してるとオフィスは乾燥してる上にまばたきを一切してないことに気がつきます
* そりゃ目が乾きますよね・・・意識してまばたきしましょう
* 集中しすぎるとまばたきも水飲むのも忘れてカタカタキーボードを叩いてしましますが、目には良くない

# まとめ
* 疲れ目対策な専用モニタとか売ってますけど会社だとねえ・・・
* ブルーライトは個人的にはそこまで効果があるのかわからなかった、メガネとかソフトで対策できるけども。
* つまるところ、やはり同じ姿勢態勢を続けるというのは体には負担になると。
* 適度に休憩しましょうね、みなさん。
COTOHA アクセストークンの取得 (Ruby)

[COTOHA API Portal](https://api.ce-cotoha.com/contents/index.html) の使用例です。

```rb:access_token.rb
#! /usr/bin/ruby
# -*- encoding: utf-8 -*-
#
#	access_token.rb
#
#					Feb/27/2020
#
# ---------------------------------------------------------------------
require 'faraday'
require 'json'
require 'dotenv'
#
# ---------------------------------------------------------------------
STDERR.puts	"*** 開始 ***"
#
Dotenv.load
#
data = {
    "grantType": "client_credentials",
    "clientId": ENV["CLIENT_ID"],
    "clientSecret": ENV["CLIENT_SECRET"]
    }
#
str_json = JSON.generate(data)
#
url = ENV['ACCESS_TOKEN_PUBLISH_URL']

headers={
    "Content-Type": "application/json"
    }
#
con = Faraday.new 
res = con.post do |req|
	req.url url
	req.headers['Content-Type'] = 'application/json'
	req.body = str_json
end

puts	res.status
puts	res.body
puts	"-----------" 

dict_aa=JSON.parse(res.body)
puts	dict_aa['access_token']
#
STDERR.puts	"*** 終了 ***"
# ---------------------------------------------------------------------
```

実行結果

```text
$ ./access_token.rb 
*** 開始 ***
201

          {
            "access_token": "oleleUiGwUIVjbvH*******", 
            "token_type": "bearer",
            "expires_in": "86399" ,
            "scope": "" ,    
            "issued_at": "1582767850104"           
           }
        
-----------
oleleUiGwUIVjbvHLonJD2OA3I8q
*** 終了 ***
```

使ったバージョン

```text
$ ruby --version
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]
```
pandasでグループごとに行単位で比率を算出

# 環境
* Python 3.8
* pandas 1.0.1


# 内容
pandasで、グループごとに行単位で比率を出したいです。
特に難しくはないのですが、コードの書き方に悩んでしまったので備忘録としてQiitaに記事を残します。


```python
import pandas

df = pandas.DataFrame({
    "name": ["Alice", "Bob","Carol", "Dave","Eve"],
    "class": ["A", "A","A", "B", "B"],
    "sex": ["F", "M","F", "M","F"],
    "worktime": [1, 2,3, 4,5],
})
print(df)

#     name class sex  worktime
# 0  Alice     A   F         1
# 1    Bob     A   M         2
# 2  Carol     A   F         3
# 3   Dave     B   M         4
# 4    Eve     B   F         5



# "sex"ごとにworktimeの比率を算出
df["ratio_per_sex"] = df.groupby(["sex"])["worktime"].apply(lambda e: e / e.sum())
print(df.sort_values("sex"))

#     name class sex  worktime  ratio_per_sex
# 0  Alice     A   F         1       0.111111
# 2  Carol     A   F         3       0.333333
# 4    Eve     B   F         5       0.555556
# 1    Bob     A   M         2       0.333333
# 3   Dave     B   M         4       0.666667


```

# 参考サイト
https://stackoverflow.com/questions/23377108/pandas-percentage-of-total-with-groupby
https://teratail.com/questions/229246
メモ: Flash

## OCX

* `C:\WINDOWS\system32\Macromed\Flash\flash.ocx`

xp

![スクリーンショット_2020-02-27_09-51-27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/06de0068-b583-7178-0929-fd47125c610d.png)

10

![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/6e94171d-a48f-e523-5722-9435600e049c.png)


## 埋め込み方

* [HTMLタグ/埋め込みタグ/embed未対応ブラウザでの表示 - TAG index](https://www.tagindex.com/html_tag/other/noembed.html)

## サンプル

(noembedタグはIE6の時点で機能しなかった・・・)

```html
<object width="550" height="400">
   <param name="movie" value="somefilename.swf">
   <embed src="somefilename.swf" width="550" height="400">
   </embed>

   <noembed> フラッシュを見るにはプラグインが必要です。</noembed>
</object>
```
Next.js のプロジェクトにGTMを組み込む方法

意外と情報がなかったので後世のために記す。

[react-gtm-module](https://github.com/alinemorelli/react-gtm#readme) というライブラリにお世話になった。
使わない場合は `_document.js` に dangerouslySetInnerHTML したりでもいける。はず。

## Next.js での設定

まず `npm install react-gtm-module --save` か `yarn add react-gtm-module` する。

そして `_app.tsx` に次のコードを埋め込む

```tsx
import TagManager from 'react-gtm-module';

class MyApp extends App {
  componentDidMount() {
    // gtmId に自分のGTMアカウントのID入れてください
    TagManager.initialize({ gtmId: 'GTM-XXXXXX' });
  }

  render() {
    。。。
  }
}
```

これでタグは配信されるようになる。

が、これだけだとクライアントサイドルーティングのPVが計測できない(History APIで更新しているだけなのでタグが発火されないから)。Next.jsを使っていると基本的にユーザの元に届いた時点でSPAとして振舞うようになると思うのでそれに対策する必要がある。

## GTM上でページ遷移時のPVを取るためのトリガーを作る

「履歴の変更」というトリガーを仕込んであげるといい。
https://support.google.com/tagmanager/answer/7679322?hl=ja

<img width="679" alt="スクリーンショット 2020-02-27 10.18.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150569/338ab5d9-2ddf-bad8-e989-8ab0bd33481a.png">

これで公開して GTM のプレビューで見ると `History` というイベントが計測されていることを確認できる。

![スクリーンショット 2020-02-27 10.19.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150569/371976c4-de02-2608-286b-ed9193b3a9e6.png)
JavaScriptでIdentifier '<変数名>' has already been declared が発生する

## 現象
シンプルなHTML+JavaScriptの構成にて以下のエラーが発生。
`Uncaught SyntaxError: Identifier '<変数名>' has already been declared`

エラー内容的には、「変数がすでに宣言されているよ！」らしいが、2重で宣言してしまっているような個所は見当たらない。

しかもこのエラーは常に先頭行にある変数に対してのみ発生していて、
先頭行の変数を削除すると、その次にある変数で同じエラーが発生する。

## 原因
HTMLでJavaScriptファイルを2回読み込んでしまっていた。

```HAML
<!-- 省略 -->
        </div>
      </div>
      <script src="script.js"></script><!-- 1回目 -->
    </div>
  </div>
  <div class="text"></div>
</body>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script type="text/javascript" src="script.js"></script><!-- 2回目 -->
</html>
```

盲点。気づくまで30分くらいかかった。
これ、やったことある人いるよね。
【小ネタ】引数のコンマ区切りを卒業し、関数呼び出しの可読性を高めよう

別にphpに限った話ではないけど。
`eval`関数の使える言語なら大抵似たようなことができると思う。
`eval`が使えなくても文字列演算をすれば代用可能。

# 1.執筆の動機

例えばPostgreSQLでは、文字列から部分文字列を取り出す関数として、
`substring('string' from 2 for 3);`
みたいのがある。このコードでは1オリジン2文字目から3文字だけ取り出すから、
結果は`'tri'`となる。

引数がコンマ`,`ではなく、`from`とか`for`で区切られている。
そのおかげで、
`substring('string', 2, 3);`
のようなコードと比べ、可読性が向上しているとは言えないだろうか。

是非このような仕組みをほかの言語でも可能にしたいと思ったのが、本稿執筆のきっかけ。

# 2.実現方法
結論から言うと、引数全体を一つの文字列とし、それを連想配列に変換しちゃえばいい。

例: 'st r_ing'の2文字目から5文字取り出したい場合

まず、次のような関数で文字列を連想配列に変換する。

```php:php
function arg2assoc(string $str)
{
    $str = str_replace("__", "_", preg_replace("/([^_]|\A)_([^_]|\z)/", "$1 $2", rtrim(preg_replace("/[ \t\r\n]*([^ \t\r\n]+)[ \t\r\n]*([^ \t\r\n]*)[ \t\r\n]*/", "'$1'=>$2,", $str), ",")));
    return eval("return [$str];");
}
```

以上のようにarg2assoc関数を書いたら、
`var_dump(arg2assoc("str 'st_r__ing' from 2 for 5"));`
を実行すると次のようになる。

```
array(3) {
  ["str"]=>
  string(8) "st r_ing"
  ["from"]=>
  int(2)
  ["for"]=>
  int(5)
}
```

後は、この連想配列を関数内部で利用すればよい。
例えば
`substring('st r_ing', 2, 5);`を
`substr("'st_r__ing' from 2 for 5");`
のように書けるようにしたい場合は、次のようにすればよい。

```php:php

function substr(string $argstr)
{
    $assoc = arg2assoc("str ".$argstr);
    return substring($assoc['str'], $assoc['from'], $assoc['for']);
}

```




# 3.仕様説明

`arg2assoc`関数をもう少し丁寧に書くと次のようになる。

```php:php
function arg2assoc(string $str)
{
    //"str 'st_r__ing' from 2 for 5"
    //(ホワイトスペースを引数に含める場合、「_」で置き換える)
    //(「_」を含めたい場合は「__」と2個連続で。)

    $str = preg_replace("/[ \t\r\n]*([^ \t\r\n]+)[ \t\r\n]*([^ \t\r\n]*)[ \t\r\n]*/", "'$1'=>$2,", $str);
    //"'str'=>'st_r__ing','from'=>2,'for'=>5,"

    $str = rtrim($str, ",");
    //"'str'=>'st_r__ing','from'=>2,'for'=>5"
    
    $str = preg_replace("/([^_]|\A)_([^_]|\z)/", "$1 $2", $str);
    $str = str_replace("__", "_", $str);
    //"'str'=>'st r_ing','from'=>2,'for'=>5"

    return eval("return [$str];");
}

```


`'st r_ing'`を`'st_r__ing'`に置き換えて渡すことの必要性について説明する。
正規表現では原理的にカッコ言語を受理できないため、
**例え引用符でくくってあったとしても、配列の区切りの空白と、文字列としての空白の区別をつけることができない**のである。
そこで、文字列としての空白は`_`で置き換えて渡す仕様とした。
また、この仕様により、空白の置き換えとしての`_`と、文字列としての`_`の区別がつかない問題が新たに発生した。
そこで文字列としての`_`は、自身を2連続した`__`で表現することとした。
StreamingAssetsでTextureをロードする方法

#はじめに

意外と、これだけのシンプルな内容の記事がなかったので端的に書いてみました。
#対象
・unityのC#がわかる
・Resouces使いたくない
・コルーチンがわかる
・Actionがかわる
・WWW使いたくない

#本題

```    

using UnityEngine.Networking;

------------------

        private Texture textureTest;
        protected string path;

        public void Start() {
//StreamingAssets内のTestフォルダのAというjpeg画像のパス指定
　　　　　　SetPath(Test/A.jpg);
           StartCoroutine (DownloadTexture (r => textureTest = r));
        }

//StreamingAssetsフォルダー内のパスの指定
        public void SetPath (string url) {
            path = url;
        }

        public IEnumerator DownloadTexture (Action<Texture> callback) {
//StreamingAssetsまでのパスと内側のパスをつなげる
            var url = System.IO.Path.Combine (Application.streamingAssetsPath, path);
            url = "file://" + url;

            using (UnityWebRequest www = UnityWebRequestTexture.GetTexture (url)) {
                yield return www.SendWebRequest ();
                if (www.isNetworkError || www.isHttpError) {
                    Debug.Log (www.error);
                    yield break;
                }
                var myTexture = ((DownloadHandlerTexture) www.downloadHandler).texture;
//コルーチンは返り値を持てないので、Actionで返す
                callback (myTexture);
            };
        }

```
#解説

```
SetPath(Test/A.jpg);
```
この引数の部分を自分のフォルダーに変更してください。

#最後に
StreamingAssetsはなんぞや
どういう利点が？
等は他に良記事が多数なのでググってみてください。
minikubeの後始末（不要なクラスタの設定を削除する）

### ■kubernetsのお試しなどでローカル環境に残っているminikubeクラスタの設定削除する

dockerでk8sクラスタが立てれるようになっていたのでローカルはそちらに移行。
不要な設定が見えているのでkubectxしたときに気になるため削除したい

# contextの設定削除

- contexts設定確認

```
# kubectl config get-contexts
CURRENT   NAME                                                                      CLUSTER                                                                   AUTHINFO                                                                  NAMESPACE
minikube                                                                  minikube                                                                  minikube                                                                  dashboard
```

- contextの設定削除

```
#kubectl config delete-context minikube
deleted context minikube from /Users/hoge/.kube/config
```

# clusterの削除

- clustersの設定確認

```
# kubectl config get-clusters
minikube
```
- clusterの削除

```
# kubectl config delete-cluster minikube
deleted cluster minikube from /Users/hoge/.kube/config
```
これでスッキリ
aiohttpを無理やりmockする

無理やり行きます。

test_aiohttp_mock.py::

```
import asyncio
from unittest import mock

import aiohttp
import pytest


async def send_request():
    async with aiohttp.ClientSession() as session:
        resp = await session.get('http://127.0.0.1:8234')
        resp.raise_for_status()

# mock
class DummyResponse(mock.MagicMock):
    def __await__(self):
        tmp = yield
        return self
    

class DummyClientSession:
    def __init__(self, resp: DummyResponse):
        self.resp = resp
    
    def __await__(self):
        tmp = yield
        return self

    def __aenter__(self):
        return self

    async def __aexit__(self, *args, **kwargs):
        await self.close()


    async def close(self, *args, **kwargs):
        pass

    async def get(self, *args, **kwargs):
        return self.resp


# testing
@pytest.mark.asyncio
async def test_simple():
    dummy_resp = DummyResponse()
    async with DummyClientSession(dummy_resp) as client:
        resp = await client.get()
        resp.raise_for_status()
        assert dummy_resp.raise_for_status.called


@pytest.mark.asyncio
async def test_aiohttp():
    with mock.patch("aiohttp.ClientSession") as ClientSession:
        dummy_resp = DummyResponse()
        ClientSession.return_value = DummyClientSession(dummy_resp)
        await send_request()
        assert dummy_resp.raise_for_status.called

```

実行

```
pytest test_aiohttp_mock.py
```


出力::

```
============================= test session starts ==============================
platform darwin -- Python 3.8.0, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /srv/sximada/blogs/python-async
plugins: asyncio-0.10.0
collected 2 items                                                              

test_aiohttp_mock.py ..                                                  [100%]

=============================== warnings summary ===============================
/Users/sximada/.virtualenvs/py38/lib/python3.8/site-packages/aiohttp/helpers.py:107
  /Users/sximada/.virtualenvs/py38/lib/python3.8/site-packages/aiohttp/helpers.py:107: DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead
    def noop(*args, **kwargs):  # type: ignore

-- Docs: https://docs.pytest.org/en/latest/warnings.html
========================= 2 passed, 1 warning in 0.20s =========================

```
【Rails】Slackへの通知をActionMailerのようなerbテンプレートを使う形で実装する

以下のGemを利用してSlackで通知を実装する際ActionMailerのようにerbを使ってviewを分けられないかと検討した。

https://github.com/stevenosloan/slack-notifier


```app/views/admin_slack_notifier/receive_message_from_user.text.erb
【<%= @subject %>】

■□–––––––––––––––––––––□■
▼送信者情報
<%= @message.user.name %>

▼送信内容
<%= @message.content %>

■□–––––––––––––––––––––□■

```

```app/libs/slack_notifier.rb
module SlackNotifier
  CONFIG = YAML.load_file(Rails.root.join('config', 'slack.yml'))[Rails.env]

  class << self
    def post(to, text, options = {})
      options = options.symbolize_keys
      dry_run = options.key?(:dry_run) ? options[:dry_run] : CONFIG['dry_run']
      post_options = format_options(to, text, options)
      notifier = Slack::Notifier.new CONFIG['webhook_url']
      notifier.post post_options unless dry_run
    end

    private

    # rubocop:disable Metrics/AbcSize
    def format_options(to, text, options)
      post_options = {
        'channel' => (options[:channel].presence || CONFIG[to.to_s]['channel']),
        'icon_emoji' => (options[:icon_emoji].presence || CONFIG[to.to_s]['icon_emoji']),
        'username' => (options[:username].presence || CONFIG[to.to_s]['username']),
        'text' => text
      }
      post_options[:title] = options[:title] if options.key?(:title)
      post_options
    end
    # rubocop:enable Metrics/AbcSize
  end
end


```

```app/libs/admin_slack_notifier.rb
module AdminSlackNotifier

  class << self

    def receive_message_from_user(message)
      @message = message
      @subject = 'ユーザーより新しいメッセージが送信されました'
      post_with_template 'admin_channel', __method__, binding
    end

    private

    def post_with_template(to, view_name, binding)
      erb = Rails.root.join('app', 'views', name.underscore, "#{view_name}.text.erb").read
      text = ERB.new(erb).result(binding)
      SlackNotifier.post to, text
    end
  end
end

```

```config/slack.yml
development: &default
  dry_run: true
  username: &username Admin
  webhook_url: WEBHOOK_URL
  admin_channel:
    channel: admin_channel
    icon_emoji: ":crystal_ball:"
    username: *username
staging:
  <<: *default
  dry_run: false
production:
  <<: *default
  dry_run: false
test:
  <<: *default

```
以下のような形でAction名と同様のviewを習得してSlackの通知を送信することができる。

```sample.rb
    AdminSlackNotifier.receive_message_from_user(message)
```
S3にあるテキストファイルをサクッと編集するには

S3にあるテキストファイルを編集したいとき、都度ダウンロードして編集してアップロードするのは手間だし、ローカルにコピーがあるとローカルとS3上とでどっちが最新だったかわからなくなるときがあるし、S3を無理やりマウントする方法もありそうだけどそこまでしたくない場合です。

以下のワンライナーでできます。これでviが立ち上がります。

```console
$ aws s3 cp s3://S3_BUCKET/S3_KEY - | vipe | aws s3 cp - S3_BUCKET/S3_KEY
```

vipeというコマンドを使っています。S3とのファイルやりとりはawscliを使っています。

S3のパスを2回書くのがダサい場合は、次のようにもできます。

```console
$ S3_PATH=s3://S3_BUCKET/S3_KEY bash -c "aws s3 cp \$S3_PATH - | vipe | aws s3 cp - \$S3_PATH"
```

vipeコマンドはパイプの中にエディタを入れて、パイプを流れるデータをその場でエディタで編集できるものです。標準入力からデータをすべて読み込んだらそのデータを編集するエディタを起動し、エディタが終了したら編集結果を標準出力に流します。エディタはvimなどの環境変数 `EDITOR` で定義されたものが使用されるようです。

以下のように使用すると、command1が標準出力を出し切ったらエディタが立ち上がり、command1の出力内容を編集できる画面になり、エディタを終了すると編集結果がcommand2の標準入力として取り込まれます。

```console
$ command1 | vipe | command2
```

vipeコマンドは`moreutils`というパッケージでインストールできます。

```console
$ sudo apt install moreutils
```

CentOSでもたぶん`moreutils`という名前でインストールできるんじゃないかと思います。

既存のファイルを編集するつもりでS3のパスを間違えた場合に、間違えたパスに新規ファイルを生成してしまうことに注意です。
ネストしたものに削除機能導入

# gorupの中のmessageに削除機能導入
ネストの中のmessageに削除機能導入するさい躓いたので備忘録として書きます。

```routes.rb
  resources :groups, only: [:new, :create, :edit, :update, :show] do
    resources :messages, only: [:index, :create, :destroy]
  end
```

```messages_controller.rb
  before_action :set_group
...
  def destroy
    message = Message.find(params[:id])
    message.destroy
    redirect_to group_messages_path(@groups)
  end
...
  def set_group
    @groups = Group.find(params[:group_id])
  end
```

rails routes
[![Image from Gyazo](https://i.gyazo.com/37fb360f1f80fea067c5af0481de39c9.png)](https://gyazo.com/37fb360f1f80fea067c5af0481de39c9)



#問題点
躓いた箇所は下記のlink_to後ろの記述
このままではどのグループのどのメッセージなのか指定できてない

```messages/index.html.erb
      <%= link_to "/messages/#{message.id}", method: :delete do%>

```

下記のようにメッセージの前にどのグループかを指定することで解決

```messages/index.html.erb
      <%= link_to "/groups/#{@groups.id}/messages/#{message.id}", method: :delete do%>

```

rails routesをした時にURI Patternを見ておく！！！
続々・WebGLについて

この記事は先日投稿した[こちらの記事](https://qiita.com/alicial/items/ccff5d2459d888a5eabf)の続きとなります。

# はじめに
今回は前回までで表示したポリゴン単体を回転させたいと思います。

# 回転させるために必要なモノ
3Dオブジェクトを回転させるためには**行列**が必要になります。
なぜ行列が必要なのかは[こちらのサイト](https://wgld.org/d/webgl/w005.html)などを参考にしてもらうと何となく分かると思います。
なにはともあれ行列が必要なわけです。

### 行列
とはいえ行列が必要といわれてもどのように作ればいいのかわかりません。
ですので今回は[glMatrix](http://glmatrix.net/)という行列生成ライブラリを利用しました。(あくまでも行列生成ライブラリなので生WebGL描画という当初の目的は継続中です。(断言))

# れっつ回転
glMatrixを使用して回転させる方法について、今回は[こちらの記事](http://nmi.jp/archives/582)を参考にさせて頂きました。
### 頂点シェーダの変更
glmatrixを追加した上で頂点シェーダの変更をします。
今回の追加したコードに関してはコメントで簡易的に説明をしてあります。

```hindex.tml
<script id="vs" type="x-shader/x-vertex">

// 平行起動回転行列
uniform mat4 modelviewMatrix; 
// 錐台変換行列
uniform mat4 projectionMatrix; 
// 頂点座標
attribute vec3 position;
// 頂点の法線ベクトル 
attribute vec3 normal;
// 法線ベクトルと平行移動回転行列との積
varying vec3 e_normal; 
attribute vec4 color;
varying lowp vec4 vColor;
void main ()
{
	// 頂点座標をクリッピング座標系に変換
	gl_Position = projectionMatrix * modelviewMatrix * vec4(position, 1.0);
	// 法線ベクトルを世界座標系に変換
	e_normal = vec3(modelviewMatrix * vec4(normal, 0.0));
	vColor = color;
}

</script>
```

- varying
    - 頂点シェーダからフラグメントシェーダに送るデータ

### フラグメントシェーダの変更
```index.html
<script id="fs" type="x-shader/x-fragment">

// 法線ベクトルと平行移動回転行列との積
precision mediump float;
varying vec3 e_normal;
varying lowp vec4 vColor;
void main ()
{
	// 法線ベクトルを正規化
	vec3 n = normalize(e_normal);
	// 法線ベクトルと光ベクトルとの内積で光量を決定
	float l = abs(dot(n, normalize(vec3(-1, 1, 1))));
	gl_FragColor = vColor;
}

</script>
```

# 描画時に回転させる
```script.js
var frame = 0;
function render()
{
	frame++;
	// 錐台行列の生成
	var proj_mat = mat4.create();
	mat4.frustum(proj_mat, -1, 1, -1, 1, 3, 10);
	// 移動回転行列の生成
	var mv_mat = mat4.create();
	mat4.translate(mv_mat, mv_mat, [0, 0, -6]);
	mat4.rotate(mv_mat, mv_mat, frame * 0.01, [0, 1, 0]); 
	// uniformでShaderに送信
	gl.uniformMatrix4fv(gl.getUniformLocation(program, "projectionMatrix"), false, proj_mat);
	gl.uniformMatrix4fv(gl.getUniformLocation(program, "modelviewMatrix"), false, mv_mat);
	
	// ======== Start 5.背景描画 ========

              ...

	// ======== End 8.描画する ========

        // 一定時間ごと処理をループ
	setTimeout(render, 16);
}
```

### 追記
3d感が薄かったためZ軸をズラしました。

```script.js
// Z軸を0から0.5に変更
var position = [
	0, 0.5, 0.5,
	-0.5, -0.5, 0.5,
	0.5 ,-0.5, 0.5
];
```

# くるくる
![Polygon.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275170/d211c1a5-52ef-a83a-d68f-f2895d5679be.gif)


# おわりに
やっと動いてるものを描画することができました。
ポリゴン1枚を描画して回転させるだけですが、ここまで行うのにそこそこのコード量が必要でした。
生WebGLでの描画、回転などが行えましたので、次回はなにかライブラリを使用してさくっと3Dオブジェクトを表示させたいと思います。

## つづき
→[完・WebGLについて](https://qiita.com/alicial/items/cba1d3b07a83af631386)
Pythonのロギング

# 概要

PythonでロギングするLoggerクラス。

# Loggerクラス

```Logger.py
from logging import Formatter, handlers, StreamHandler, getLogger, DEBUG

class Logger:

    _unique_instance = None

    def __init__(self, name=__name__):
        self.logger = getLogger(name)
        self.logger.setLevel(DEBUG)
        formatter = Formatter("[%(asctime)s] [%(process)d] [%(name)s] [%(levelname)s] %(message)s")

        # stdout
        handler = StreamHandler()
        handler.setLevel(DEBUG)
        handler.setFormatter(formatter)
        self.logger.addHandler(handler)

        # file
        handler = handlers.RotatingFileHandler(filename = 'backup.log',
                                               maxBytes = 1048576,
                                               backupCount = 3)
        handler.setLevel(DEBUG)
        handler.setFormatter(formatter)
        self.logger.addHandler(handler)

    @classmethod
    def get_instance(cls):
        if not cls._unique_instance:
            cls._unique_instance = cls()

        return cls._unique_instance

    def debug(self, msg):
        self.logger.debug(msg)

    def info(self, msg):
        self.logger.info(msg)

    def warn(self, msg):
        self.logger.warning(msg)

    def error(self, msg):
        self.logger.error(msg)

    def critical(self, msg):
        self.logger.critical(msg)

```

# 使用例

- インスタンスの作成/呼び出しはget_instance()を使う。
- ロギングの出力は各メソッドを呼び出す。

```UseLogger.py

from Logger import Logger

# 〜(中略)〜
logger = Logger.get_instance()

logger.error("some error message")
logger.debug("some debug message")

```

 # 備考

- Singletonになっているので、複数のモジュール内でインスタンスを使う場合も、get_instance()からインスタンスを取得すれば、インスタンスは1つしか作成されない。
PythonでSQLite3を扱うための具体的なサンプルコード

SQLite3はPythonに最初から入っていることや、ファイルとしてDBを保存できることなどからPythonで最も簡単に扱えるデータベースと言えます。

そこでここでは、Pythonを用いたSQLite3のデータの書き込み/読み出しのサンプルコードをメモしておきます。

# 基本
~~~python
import sqlite3

# 接続DBファイルの指定
conn = sqlite3.connect('example.sqlite3')
conn.row_factory = sqlite3.Row 
c = conn.cursor()

# SQL文の実行
sql="create table persons(name, age, job)"
c.execute(sql)

# 変更の保存
conn.commit()

# DBから切断
conn.close()
~~~
SQL文を実行した後、その変更を反映するためには「conn.commit()」を実行する必要があります。

#テーブル操作
##テーブルの作成
~~~python
sql="create table persons(name, age, job)"
c.execute(sql)
~~~
ここでは例としてname・age・jobの３つのカラムを持つ「persons」テーブルを作成しています。

##テーブルにカラムを追加
~~~python
sql="alter table persons add column address"
c.execute(sql)
~~~
「persons」テーブルに「address」のカラムを追加

##テーブルを削除
~~~python
sql="drop table persons"
c.execute(sql)
~~~
「persons」テーブルを削除する処理

##テーブル名の変更
~~~python
sql="alter table persons rename to workers"
c.execute(sql)
~~~
「persons」テーブルを「workers」に名称変更

#データの操作
##データの追加（INSERT）
~~~python
sql="insert into persons values ('Ann', '20','apprentice')"
c.execute(sql)
~~~

##データの変更（UPDATE）
~~~python
sql="update persons set age=21 where name='Ann'"
c.execute(sql)
~~~
このコードでは「persons」テーブル内の「name='Ann'」のAgeを21に変更しています。

##データの削除（DELETE）
~~~python
sql="delete from persons where age<20"
c.execute(sql)
~~~
このコードでは「persons」テーブル内のageが20以下のデータが削除されます。

#データの取り出し
##基本
~~~python
sql="select * from persons"
c.execute(sql)
~~~
全部取り出す場合はこのコードで事足ります。
データサイズが小さい場合はDBから全部取得した後にPython側のPandasなどで処理したほうが分かりやすいかもしれません。

##取り出したデータをリストに展開
~~~python
import sqlite3

# DBに接続
conn = sqlite3.connect('example.sqlite3')
conn.row_factory = sqlite3.Row #dict型を指定
c = conn.cursor()

# DBの中身を取得
c.execute('select * from persons')
results = c.fetchall()

# 展開用に空リストを作成
persons_list=[]

# リストに展開する処理
for r in results:
    persons_list.append(r)

# DBから切断
conn.close()

# 表示
display(persons_list)
~~~
「persons_list」に行データを格納しています。取り出すときは

~~~python
persons_list[0]['name']
## ann
~~~
この様にすると取り出せます。

##一部取り出し(カラム名指定)
~~~python
sql="select name from persons"
c.execute(sql)
~~~
name列だけ取り出すコード

##一部取り出し(条件指定)
~~~python
sql="select * from persons where age>20"
c.execute(sql)
~~~
ageが21以上の行を抽出

##データの取り出し順を指定
~~~python
#昇順で取り出し
sql="select * from persons order by age asc"
c.execute(sql)

#降順で取り出し
sql="select * from persons order by age desc"
c.execute(sql)
~~~

# PandasでSQLを読み込み
~~~python
import sqlite3
import pandas as pd

conn = sqlite3.connect("sample01.sql")
conn.row_factory = sqlite3.Row 
c = conn.cursor()
        
sql="select * from persons"
df = pd.read_sql_query(sql, conn)
        
c.close()
conn.close()
~~~

#PandasでSQLを保存
~~~python
import sqlite3
import pandas as pd

conn = sqlite3.connect("sample01.sql")
conn.row_factory = sqlite3.Row 
c = conn.cursor()
        
df.to_sql('data_name', conn, if_exists='replace')
        
c.close()
conn.close()
~~~

#参考ページ
[\[Python3\]\[SQLite3\]レコードを辞書型\(dict型\)で取得する簡単な方法 \- Qiita](https://qiita.com/wiwi7373/items/7d47decf85a77454074d)
[SQLite入門](https://www.dbonline.jp/sqlite/)
[PythonからSQLite3で初めてのデータベース！ \- Qiita](https://qiita.com/DNA1980/items/1fbcb95e8ee5771d6b2b)
Ruby on Rails チュートリアル学習記録 第3章

第2章については特に書く内容がなかったため学習記録は付けませんでした
# 3.1
`heroku create`を実行すると`bash: heroku: command not found`というエラーメッセージ。
https://qiita.com/RyuGotoo/items/7d44f7aa51f7c90ad0b7
↑こちらの記事参考に
`nvm install node`
`npm install -g heroku-cli`
を実行後、あらためて`heroku create`を実行すると上手くいった。
# 3.2
特になし
# 3.3
特になし
# 3.4
特になし
# 3.5
特になし
# 3.6
特になし
SEOは人ではないアルゴリズムでもない

最近はよく人にフォーカスすることが言われる。道具でも同じ。使う人にとって優れているものは自然とリピートされていく。それが口コミで広がるのがバイラル効果。ただし、激しい競争の中では「良いもの、ユーザーの意見を聞いたが成果がでない」ということも。

SEOはアルゴリズム。最近のGoogle検索は以前とはまた変わってきた。数年前までなら「良い記事、ユーザー目線で受け入れられる記事なら上位をとれる」という時期があった。それは流行にすぎないのか、ユーザーファースト「コンテンツイズキング」であった時代の過去のこと。

Googleアップデートはコンテンツよりもドメイン重視の時代がやってきている。それは一過性なのか、それとも今後の主流なのかはっきりしなかった。つまり、「人にとって受け入れられるものを作ること」がサイト運営者に求められることだったが、最近の2020年ごろではブランド力が物を言うわけだ。<a href="https://alphard-discount.com/kyutei-nyokan-jang-geum-no-chikai-netabare-arasuji/" >あらすじチャングムのネタバレ</a>のようなサイトはダメ。有力ドメインは高い評価を受ける。人ではなく、アルゴリズム。

商品だったら、無名メーカーよりも高級ブランドが優れているということ。ユーザーから受け入れられる優れた内容よりも、「どこの」というもとのところが問われている。無名ブランドが努力しても厳しいのがSEOになってきた。
rails g model/migrationの違い

# rails g model...

```ruby:main.rb
rails g model モデル名 カラム名:データ型...
rails g model Graph date:date weight:float user:references
```
Graphがモデル名

モデル名とテーブルとデータができる

#rails g migration...

```ruby:main.rb
rails g migration add_user_id_to_posts
```
postsテーブルにuser_idカラムを加える

**rails g model**
**rails g migration**
はいずれも
**rails db:migrate**　を実行する必要あり

#rails db:migrate
```ruby:main.rb
rails db:migrate
```

これがないとデータベースに反映されません
CircleCiでis not empty and not a git repository　エラー

# 概要
CircleCiのチェックアウトで下記エラーがでてしまう

```
Directory (/go/src) you are trying to checkout to is not empty and not a git repository
```


``` .circleci/config.yml
version: 2
jobs:
〜〜〜〜〜略〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
   steps:
      - checkout
〜〜〜〜〜略〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
```

# 結論
メッセージの通りなのですが、
コンテナの`working_directory`が空でないため、githubからcheckout出来ないため、
`working_directory`を配下を空にするか、他のからのディレクトリを指定するとエラーは解消となります。

# 参考：解決例

参考までに今回自分の解決した例を載せておきます。

```
    working_directory: /go/src
　　　　↓
    working_directory: /go/src/github.com/{{ORG_NAME}}/{{REPO_NAME}}
```

circleciの設定で{{ORG_NAME}}と{{REPO_NAME}}を見かけますが、
最初見たとき、何をどこで設定すればいいんだよ！！ってなって悩んでしまったのですが、
circleci側で自動的に設定が行われており問題なく、動きます。
UNVTの目的と手段と、手段の手段について

# 目標は地図の多様性、手段は努力の結集、手段の手段はオープンソース
継続的改善というのは、オープンソースコミュニティを持続可能な形で維持することで実装できる、というのが国連ベクトルタイルツールキット主任のポジションです。

努力を集約するということは手段であり、オープンソースというのは手段の手段である。目標は地図の多様性すなわち目的合致性を擁護することである、ということになります。

# See also
継続的改善について、次の文書を読んで考えました。
https://sara-sabr.github.io/ITStrategy/mandate.html
vim初心者　チートノート

vimのコマンドでこれで、NormalMode、InsetMode、VisualModeすべてで方向キーとBackSpaceキーを封印したら通常の削除すらままならなくなったので、よく使うキーのみ自分なりにまとめておこうと思います。

#基本の移動

| コマンド | 意味 |
|:--|:--|
| h | 左へひとつ |
| j | 下へひとつ |
| k | 上へひとつ |
| l | 右へひとつ |

#行移動

| コマンド | 意味 |
|:--|:--|
| w | 次の単語の先頭へ |
| e | 単語の最後へ |
| b | 前の単語の先頭へ |
| 0 | 行頭へ |
| $ | 行末へ |
| ( | 前の余白まで |
| ) | 次の余白まで|
| { | 前の余白まで |
| } | 次の余白まで |
| gg | ファイルの先頭へ |
| G | ファイルの最終へ |

#削除
vim縛りをした際一番困ったコマンドを記述しておきます。


| コマンド| 意味 |
|:--|:--|
| x | カーソル下の一文字を削除 |
| D | 行内のカーソル以降を削除 |
| dd | 行を削除 |



#インサートモードへの移行


| コマンド | 意味 |
|:--|:--|
| o | 前の行を空けてインサートモードに移行 |
| i | 後ろに向けて移動してインサートモードに移行 |
| a | 前に向けて空インサートモードに移行 |
| I | 行の先頭に移動してインサートモードに移行 |
| A | 行末に移動してインサートモードに移行 |

#インサートモードへの解除


| コマンド | 意味 |
|:--|:--|
| control c |　インサートモード解除 |
| esc | インサートモード解除 |

#マーク機能
コピー（ヤンク）する際は必須！
とりあえず現在使用しているコマンドを書いておきます。

| コマンド | 意味 |
|:--|:--|
| ms | マーク開始 |
| y's | マーク終了&コピー |
| d's | マーク終了&切り取り |

#コピー

| コマンド | 意味 |
|:--|:--|
| yy |　カーソル行をコピー |
| nyy | n行をコピー(nには数字) |
| nyy | n行をコピー(nには数字) |

#ペースト

| コマンド | 意味 |
|:--|:--|
| p |　ペースト |

#複数ターミナルからの移動
移動元でコピーしたものを他のターミナルでペーストしたい場合に使用できる。

| コマンド | 意味 |
|:--|:--|
| :wv  |　移動元で入力 |
| :rv! |　移動先で入力 |

#元に戻す
| コマンド | 意味 |
|:--|:--|
| u  |　一つ前の状態に戻す。 |
|Ctrl + r|　uで戻した操作を、元に戻す。 |


随時更新していきます。
初心者によるプログラミング学習ログ 250日目

#100日チャレンジの250日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。

すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

250日目は、
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>250日目<br>・webサイト模写<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1232757043766808576?ref_src=twsrc%5Etfw">February 26, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
AWS CLI v2

# AWS CLI v2


```
$ aws logs tail --follow LOG-GROUP-NAME
``` 
ロググループを指定して、ログをリアルタイムでtailすることができるのっていいよね。

## AWS CLI v2 install


とりあえずpipでinstall

```
$ pip install -e git://github.com/aws/aws-cli.git@v2#egg=awscli
pyenv: pip: command not found
```

えっ。そんなわけない。。

pyenvを確認

```
$ pyenv versions
  system
* 3.6.1 (set by ~~~~~)
 　(省略)
```

うーん。とりあえず早く試したいので、別のバージョンならpip使えるので、バージョン切り替えて、とりあえずすすむ。

```
$ pyenv global 3.7.6
$ pip install -e git://github.com/aws/aws-cli.git@v2#egg=awscli
(省略)
ERROR: No matching distribution found for botocore==2.0.0dev5 (from awscli)
```

なんかまたエラー出てきた。
依存ライブラリのbotocoreがうんぬん。

awscliより先にbotocoreを入れてみる。

```
$ pip install https://github.com/boto/botocore/archive/v2.tar.gz
(省略)
Successfully installed botocore-2.0.0.dev5
```

よし、成功。

```
$ pip install https://github.com/boto/botocore/archive/v2.tar.gz
(省略)
Successfully installed awscli cffi-1.14.0 cryptography-2.8 prompt-toolkit-2.0.10 pycparser-2.19 ruamel.yaml-0.15.100 wcwidth-0.1.8
```

よし。成功。

確認。

```
$ aws --version
aws-cli/2.0.1 Python/3.7.6 Darwin/19.3.0 botocore/2.0.0dev5
```

おけおけ。

```
$ aws logs tail --follow LOG-GROUP-NAME
``` 

これで見れた！！

## 追記

python 3.6.1で pyenv: pip: command not foundって出てきたのが相当気持ち悪い。

結論

```
$ cd .anyenv/envs/pyenv/versions
$ rm -rf 3.6.1
```

一回消して

```
$ pyenv install 3.6.1
```

入れ直したら、大丈夫だった。なんか気持ち悪いけど、まぁおk。
テスト投稿（IntelliJで「\」入力できない問題）

# 動機
せっかくQiitaに登録したので、Markdown記法に慣れるために（？）テスト投稿。

# ざっくり自己紹介
- 社会人３年目
- C, Java, Go, Python, PHP が少しばかりわかる程度
- 最近`Haskell`触り始めました
- [AtCoder](https://atcoder.jp/)にも最近登録しました（基本はGo、Haskellを使えるようになりたい）

# 最近の悩み＆解決
IntelliJで`\`が入力できない。。。Issueとして挙がってるっぽいが・・・
### Karabinerの導入
1. [Karabiner-Elements](https://pqrs.org/osx/karabiner/)をインストール。
1. セットアップでJISキーボードを選択。セキュリティがうんたらと言われたら許可。
1. 「セキュリティとプライバシー」 > 「入力監視」にて以下を許可。
    ・karabiner_grabber
    ・karabiner_observer  

1. Karabiner-Elementsを開いてComplex modifications > Add Rule > Import more rules..
    ブラウザが開くので「Swap ¥ and \ always on JIS Keyboards」をImport  

1. もしMacのキーボードの入力ソース側で`\`を入力するようにしていたらこれをOFFに。

で解決！めでたしめでたし.
GCPのVision APIで画像を文字おこし

Vision APIで画像を文字おこし
-

'type': には"TEXT_DETECTION"と
"DOCUMENT_TEXT_DETECTION"の２つがあり、後者を選択した

```
#coding:utf-8
import base64
import json
from requests import Request, Session
from io import BytesIO
from PIL import Image
import pandas as pd

#PILで開いた画像をCloud Vision APIに投げる
def recognize_image(pil_image):
        def pil_image_to_base64(img_path):
            pil_image = Image.open(img_path)
            buffered = BytesIO()
            pil_image.save(buffered, format="PNG")
            str_encode_file = base64.b64encode(buffered.getvalue()).decode("utf-8")
            return str_encode_file
        
        def get_fullTextAnnotation(json_data):
            text_dict = json.loads(json_data)
            try:
                text = text_dict["responses"][0]["fullTextAnnotation"]["text"]
                return text
            except:
                print(None)
                return None

        str_encode_file = pil_image_to_base64(pil_image)###ここは最後に消す
        str_url = "https://vision.googleapis.com/v1/images:annotate?key="
        str_api_key = "APIキー"
        str_headers = {'Content-Type': 'application/json'}
        str_json_data = {
            'requests': [
                {
                    'image': {
                        'content': str_encode_file
                    },
                    'features': [
                        {
                            'type': "DOCUMENT_TEXT_DETECTION",
                            'maxResults': 10
                        }
                    ]
                }
            ]
        }

        obj_session = Session()
        obj_request = Request("POST",
                              str_url + str_api_key,
                              data=json.dumps(str_json_data),
                              headers=str_headers
                              )
        obj_prepped = obj_session.prepare_request(obj_request)
        obj_response = obj_session.send(obj_prepped,
                                        verify=True,
                                        timeout=60
                                        )

        if obj_response.status_code == 200:
            text = get_fullTextAnnotation(obj_response.text)
            
            return text
```

recognize_image("画像のパス"）
Cloudtrailの絞り込み（リソースタイプ）

レコードをいかに絞るか？を検討した際にarnが明確であれば
リソースタイプで絞り込むのがわかりやすいです

以下のようなリソースを作成するイベントのログを抽出する場合
（この場合はIAMのユーザ作成）

```
arn:aws:iam::アカウントID:user/admin
```
CloudtrailのリソースタイプはarnのアカウントIDの後ろにある「user」を
リソースタイプで絞り込めば対象の件数を減らすことができます。
![Screen Shot 2020-02-27 at 3.21.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110457/a7399806-ffbb-0c0e-0957-a990f2ddf872.png)
【Minecraft】ワールドデータの構成とか格納場所とか解析方法とか


これとjqを使ってMinecraftのセーブデータを色々解析したときのメモ

- 【Minecraft】LinuxのCLI上でNBT→JSONするツールを作った https://qiita.com/MirrgieRiana/items/e8bbcb2615506dd0342c

# 前提

- Ubuntu 18.04.3 LTS
- bash

# Minecraftサーバーの構成

Minecraftのセーブデータは、デフォルトではサーバーの実行ディレクトリ内にあるworldディレクトリに格納される。

- サーバー/
    - `config/`
    - `libraries/`
    - `world/`
        - `DIM-1/`
        - `DIM1/`
        - `advancements/`
        - `playerdata/`
            - `12345678-1234-1234-1234-12345678ABCD.dat`
            - 他...
        - `region/`
            - `r.0.-1.mca`
            - 他...
        - 他...
    - `server.properties`
    - `eula.txt`
    - `usernamecache.json`
    - 他...

以下では上記ツリーの「サーバー」をカレントディレクトリとする。

## プレイヤー名⇔UUID

プレイヤーは、英数字の名前と長いUUIDを持っている。

この対応表は`usernamecache.json`にキャッシュされている。

```bash:
$ cat usernamecache.json; echo
{
  "00000000-0000-0000-0000-000000000000": "Player0",
  "11111111-1111-1111-1111-111111111111": "Player1",
  "22222222-2222-2222-2222-222222222222": "Player2"
}
$ cat usernamecache.json | jq -r 'with_entries({"key":.value, "value": .key}).Player1'
11111111-1111-1111-1111-111111111111
```

その他、MojangのWebAPIからも拾ってこれるらしい。

## プレイヤーデータ

プレイヤーデータは、`world/playerdata/12345678-1234-1234-1234-12345678ABCD.dat`みたいな場所に格納されている。
ここで、`12345678-1234-1234-1234-12345678ABCD`は任意のプレイヤーのUUIDである。
UUIDは`usernamecache.json`からコマンドで調べられるので、コマンドだけでユーザー名からそのユーザーのステータスを出したりとかもできる。

以下はユーザー名のキャッシュが残っているすべてのプレイヤーのインベントリ（と装備とオフハンド）の中に直接入っている松明の個数を合計して出力するコマンドである。

```shell:bash
for entry in $(cat usernamecache.json | jq -c 'to_entries[] | [.key, .value]')
do
  uuid=$(echo $entry | jq -r '.[0]')
  name=$(echo $entry | jq -r '.[1]')
  count=$(cat world/playerdata/$uuid.dat | \
    inflate-gzip | \
    nbt2json -cp | \
    jq '.C.AInventory.values | [.[] | select(.Tid == "minecraft:torch").BCount] | add // 0')
  echo -e "$count\t$name"
done
```