OmniAICreator/Qiita-1.07M huggingface dataset:
PythonのJupyter NotebookでグラフだけRのggplot2で描きたい（ほぼ標準ライブラリ）

データ分析をしていて、基本的にはPythonでの作業が快適だけど、グラフだけはRのggplot2で描きたい、ということが私はよくあります。
そういうとき、普通は次の２つの手段を取ることが多いと思います。

* [ggpy](https://github.com/yhat/ggpy) ライブラリを使う。これは、ggplot2の機能をPythonに移植したものです。
* [rpy2](https://pypi.org/project/rpy2/) ライブラリを使い、Rのコードをセルに書く（[例](https://github.com/crscardellino/python-with-ggplot/blob/master/python_with_ggplot.ipynb)）

1つめの手段はPythonネイティブなのが嬉しいものの、完璧な移植とは限らないのと文法の差を覚え直す必要があるところが難点です。
2つめの方が個人的には好みですが、Rでやりたいことがggplot2のグラフを書くだけなら、もう少し簡単にできそうです。

そこで、ggplot2でグラフを書いて表示させるだけの関数です。`IPython`とデータフレームを渡す場合に`pandas`の機能を使う以外は標準ライブラリで完結しています。
やっていることはシンプルです。

1. 一時フォルダを作成
1. データフレームを利用する場合、それらを一時フォルダのCSVファイルに書き出し
1. Rコードを生成
    1. ライブラリの読込
    1. データのロード
    1. ggplot2による描画を画像ファイルとして保存
1. 保存した画像ファイルを表示
1. 一時フォルダごと削除

```python
import os
import subprocess
from tempfile import TemporaryDirectory
from IPython.display import Image

def ggplot(plotcode, libs=("magrittr", "ggplot2"),
           dispwidth=None, dispheight=None,
           width=None, height=None,
           showcode=False, **dataframes):
    with TemporaryDirectory() as tmpdir:
        importcode = ";".join(f"library({l})" for l in libs)
        readcode = []
        for name, df in dataframes.items():
            filename = os.path.join(tmpdir, f"__data_{name}.csv")
            df.to_csv(filename, index=False)
            readcode.append(f"{name} <- read.csv('{filename}', as.is=TRUE)")
        readcode = ";".join(readcode)
        
        graphfile = os.path.join(tmpdir, "__graph.png")
        if width is None:
            width = "NA"
        if height is None:
            height = "NA"
        code = f"""
        {importcode}
        {readcode}
        ..g <- {{
          {plotcode}
        }}
        ggsave("{graphfile}", ..g, width={width}, height={height})
        """
        if showcode:
            print(code)
        subprocess.run(["Rscript", "-e", code])
        
        display(Image(filename=graphfile, width=dispwidth, height=dispheight))
```

上のセルを1回実行したうえで、下記のようなコードでグラフの描画ができます。
`width`, `height`は保存時のサイズ、`dispwidth`は表示時のサイズです。

```python
import pandas as pd
import numpy as np
df = pd.DataFrame({"x": np.linspace(-10, 10, 100)})
df["y"] = np.sin(df.x)

df2 = pd.DataFrame({"x": np.linspace(-10, 10, 100)})
df2["y"] = 1.2*np.cos(0.6*df2.x)

ggplot(
  """
  ggplot(dat, aes(x=x, y=y)) +
    geom_line() +
    geom_line(aes(x=x, y=y), data=dat2, linetype="dotted") +
    theme_bw()
  """,
  dat=df, dat2=df2, 
  width=4, height=2, dispwidth=640)
```

こういった出力がでます。基本的にはRのコードを実行しているだけなので、自由度は高いです。
![Screenshot_2021-09-08_01-44-19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80588/007b2d43-9b01-b850-40a9-ae817a047bb7.png)

関数に少し変更を加えれば、Jupyter上で表示するのではなく指定の場所にファイルを書き出すようにもできます。
Gitの初期設定

## バージョン管理システム「Git」
Gitは、プログラム開発の作業履歴を記録するツール


## gitのインストール確認
```
git --version
```

結果、　`git version 2.5.●`などのバージョン情報が出ればインストール済み


## ユーザー登録
```
git config --global user.name "YOUR_NAME"
git config --global user.email "YOUR_EMAIL_ADDERESS@gmail.com"
```

###### ユーザー登録情報の確認
```
git config --list

#user.name=YOUR_NAME
#user.email=YOUR_EMAIL_ADDERESS@gmail.com
```


## リポジトリを作る

```
mkdir myfirstwork
cd myfirstwork
git init
 #Initialized empty Git repository in /home/ubuntu/myfirstwork/.git/
```
![スクリーンショット 2021-09-06 22.39.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1977965/cb252ad0-4f5f-6e0c-8278-616b177ddc80.png)



<!--
- コードの変更を記録 add, commit
- 状態や変更箇所を確認 log, diff
- 前の状態を復活 reset, revert
- 作業箇所を分岐 branch, checkout
- 作業結果を統合 push, merge
- -->
＃3,Javaマスターへの道　1

#はじめに
大学1年生です。
学校でJava のプログラミングについて学習しているので復習も兼ねて投稿していきます。
これから勉強するって人は一緒に頑張っていきましょう！

#目次
1.プログラミングとは
2.Javaのプログラム
3.プログラムの要素
4.初めてのプログラミング
5.バグ

#1.プログラミングとは
プログラムで伝える命令は、コンピュータが解釈できる文法をもつプログラム言語で書く必要があります。この文法を学ぶことがプログラミングを習得することになります。
コンピュータは命令がないとまったく動きません。コンピュータに何か仕事をしてもらうには命令の羅列である**プログラム**を作る必要があります。
プログラムを作ることを**プログラミング**といいます。

#2.Javaのプログラム
Javaのプログラムは以下のような形をしています。

```Java
package cp1;
import java.util.Scanner;
public class Test {
	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
//ここにプログラムを書く
	}
}
```
public(パブリック)、static(スタティック)、void（ボイド）、main（メイン）と何やら最初から正体不明の英語みたいなものが並んでいますが、ほとんどはおまじないです。プログラミングに「おまじない」はつきものなのでそんなものかと無視しておきましょう。
今分かっておいて欲しいのは
```
//ここにプログラムを書く
```
と言う部分にプログラミングを書くということです。
ここにはプログラミング言語の「文」を書きます
文は記憶、演算、制御などの命令を伝え、最後にセミコロン；をつけます。

>ヒトコトmemo
プログラムの中では（）も{}も[]も使いますがそれぞれ別の意味があり、勝手に別のカッコで置き換えてはいけません。開けたカッコは対応したカッコで閉じる必要です。

#3.プログラムの要素
プログラムの基本要素を簡単に分類すると次の5つになるといわれています
1.**出力**
コンピュータ内部データを表示させたり、他のデバイスに移すことを出力といいます。
>ヒトコトmemo
\#4で出力について学習します。主にprintlnという命令を使いますが、Javaではprintlnのようなまとまった処理を指示する命令を**メソッド**といます。

2.**入力**
コンピュータにデータを読み込ませることを入力といいます。
入力は\#5で扱う予定です

3.**記憶**
データをコンピュータに覚えさせることが記憶です。記憶は　変数　というものを用意し、　変数＝式;　という形の代入文を使います。

4.**演算**
演算とは加減乗除のほか、各種の数値計算、文字列の操作、データの検索、データの並び替えのことをいいます。このうち加減乗除には＋ー＊/などの記号が使われますが、このような記号を**演算子**といいます。
一方それより複雑な計算の場合　Math.abs(*num*)のような命令、即ちメソッドを使うこともありますし、演算子やメソッド、その他の制御を組み合わせて演算を行うこともあります。

5.**制御**
プログラミングは通常打ち込まれたプログラムを上から下へ順番に実行しますが、条件判断によって枝分かれしたり、繰り返したりします。Javaにはその繰り返しや枝分かれを実現するために**構文**が用意されています。

#4.初めてのプログラミング
プログラミングについての基礎知識を身につけたらいよいよプログラムを書いてみます

```java
public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		System.out.print("こんにちは　私の名前はxxxxです");//プログラム本文
	}
}
```
もちろん　xxxx　の部分は自分の名前で置き換えてください。書けたら実行してみましょう。
実行すると、「こんにちは　私の名前はxxxxです」と表示されると思います。このプログラムが私のプログラム第1号ですね。
上の見出し2つ目でもでてきましたが、プログラム中にスラッシュ記号が二つ　**//**　現れたら、その記号から後ろは**コメント**です。コメントはプログラムの本文や実行に関係しないメモや説明のことでよくプログラムの解説のためにコメントを書き加えることがあります。
プログラムを後から見返したときの理解の助けになることもあるので書く習慣をつけましょう。
>ヒトコトmemo
プログラミング言語を勉強しはじめたとき、最初に書くプログラムはどのプログラム言語でも大概画面に「Hello world」と表示させることが一般です。

#5.バグ
プログラムの間違いのことを**バグ**とよびます。コンピュータは1文字の間違えも許してくれません。例えば文字列や数字を表示させる　printlm　を　printIm　と打ち込んでしまったり、　;　が　:　と書いた場合全てバグとなり、コンピュータは正常に動作せず、プログラムが実行できなくなります。
こういったエラーが起きた場合は次のことに注意しましょう。

1.文字の確認
数字のいち「1」、小文字のエル「l」、大文字のアイ「I」や、数字のゼロ「0」、大文字のオー「O」、小文字のオー「o」のように区別がつきにくいものがあります。よく確認しましょう。
2.エラーメッセージの確認
エラーが発生した場合なにがいけなかったのかコンピュータがメッセージとして表示してくれます。もしメッセージの意味が分からなくてもコピペしてインターネットで調べると解決策を知ることができます。
3.プログラムの意味を確認
どれだけ熟練のプログラマーでも達人のようなシステムエンジニアでもバグを生んでしまうことはあります。バグに対する対処もスキルの一つです。バグを直すことは**デバッグ**とよびます。
デバッグ能力もプログラミング能力のうちということですね。
railsチュートリアル第４章 CSS

####CSS、再び

```css
<%= stylesheet_link_tag 'application', media: 'all',
                                       'data-turbolinks-track': 'reload' %>
```
Railsではスタイルシートを追加するための特別なメソッドを使っています。

```css
stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track': 'reload'
```
このメソッドを呼んでいます
第一に、丸カッコがありません。
``` Ruby では丸カッコは使用してもしなくてもいい。```

次の2つの行は等価です。

```rb
# メソッド呼び出しの丸カッコは省略可能。
stylesheet_link_tag('application', media: 'all',
                                   'data-turbolinks-track': 'reload')
# 上は以下のように書いても同じ
stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track': 'reload'
```

media引数はハッシュのようだ。　　
```ハッシュがメソッド呼び出しの最後の引数の場合は、波カッコを省略できる。 ```

次の2つの行は等価です

```rb
# 最後の引数がハッシュの場合、波カッコは省略可能。
stylesheet_link_tag 'application', { media: 'all',
                                     'data-turbolinks-track': 'reload' }
# 上は以下のように書いても同じ
stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track': 'reload'
```
これでなぜ動いているのか？

```css
stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track': 'reload'
```
上のコードには途中に改行が含まれている。
```Rubyは改行と空白を区別していません。 ```
行を分割した理由は、1行を80字以内に収めて```ソースコードを読みやすくする ```ためです。

#####最初のコード

```rb
stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track': 'reload'
```
stylesheet_link_tagメソッドを```2つの引数```で呼んでいます。
最初の引数である文字列は、スタイルシートへのパスを示しています。
次の引数であるハッシュには2つの要素がある。
最初の要素はメディアタイプを示し、
次の要素はRails 4.0で追加されたturbolinksという機能をオンを示す。

<%= ... %> で囲まれているコードを実行した結果がERbのテンプレートに挿入されるようになります。
ブラウザ上でこのページのソースを表示すると、必要なスタイルシートが含まれていることを確認できます

######読み込まれたCSSによって生成されたHTMLソース

```css
<link rel="stylesheet" media="all" href="/assets/application.self-
f0d704deea029cf000697e2c0181ec173a1b474645466ed843eb5ee7bb215794.css?body=1"
data-turbolinks-track="reload" />
```
railsチュートリアル第４章 ブロック

####ブロック
配列と範囲はいずれも、ブロックを伴うさまざまなメソッドに対して使える。

```rb
>> (1..5).each { |i| puts 2 * i }
2
4
6
8
10
=> 1..5
```
(1..5)に対してeachメソッドを呼び出す。
メソッドに渡されている{ |i| puts 2 * i }が、ブロックと呼ばれる部分
|i|では変数名が縦棒「|」に囲まれている。　ブロック変数に対して使うRubyの構文
範囲オブジェクトのeachメソッドは、iという1つのローカル変数を使ってブロックを操作

```rb
>> (1..5).each do |i|
?>   puts 2 * i
>> end
2
4
6
8
10
=> 1..5
```
短い1行のブロックには波カッコを使う。
長い1行や複数行のブロックにはdo..end記法
iの代わりにnumberを使っている。
この変数（ブロック変数）の名前は固定されていません。

```rb
>> 3.times { puts "Betelgeuse!" }   # 3.timesではブロックに変数を使っていない
"Betelgeuse!"
"Betelgeuse!"
"Betelgeuse!"
=> 3
>> (1..5).map { |i| i**2 }          # 「**」記法は冪乗 (べき乗)
=> [1, 4, 9, 16, 25]
>> %w[a b c]                        # %w で文字列の配列を作成
=> ["a", "b", "c"]
>> %w[a b c].map { |char| char.upcase }
=> ["A", "B", "C"]
>> %w[A B C].map { |char| char.downcase }
=> ["a", "b", "c"]
```

```rb
>> %w[A B C].map { |char| char.downcase }
=> ["a", "b", "c"]
>> %w[A B C].map(&:downcase)
=> ["a", "b", "c"]
```

######テストがブロックなっている

```rb
test "should get home" do
  get static_pages_home_url
  assert_response :success
  assert_select "title", "Ruby on Rails Tutorial Sample App"
end
```
テストコードにdoというキーワードがあることに気付き
そこからテストの本体が「そもそもブロックでできている

###演習
1.2乗にせよ

```rb
>> (0..16).each{ |i| puts i ** 2}                                          
0
1
4
9
16
25
36
49
64
81
100
121
144
169
196
225
256
=> 0..16
```
2.メソッドを定義してメソッドを使え。

```rb
>> def yeller(s)
>>   s.join.upcase
>> end
=> :yeller
>> yeller(['o', 'l', 'd'])
=> "OLD"
```
mapを使いきれなかった。　一応書いてみた。

3.メソッドを定義して、メソッドを使え。

```rb
>> def random_subdomain
>>    b = ("a".."z").to_a.shuffle[0..15].join
>>    puts b
>> end
=> :random_subdomain
>> random_subdomain
uztpyrijhcvesxnl
=> nil
```
一応できたと思う。

4.コードを書き換えろ

```rb
>> def string_shuffle(s)
>>   s.split('').shuffle.join
>> end
=> :string_shuffle
>> string_shuffle("foobar")
=> "arfoob"
>> string_shuffle("foobar")
=> "ooabfr"
>> string_shuffle("foobar")
=> "bfooar"
```
【Swift】シングルトン（Singleton）パターン

##はじめに

コードレビューをしていただいた際シングルトンを教えていただき、コードがかなりスッキリしたので備忘録として書きます！

##シングルトンパターンとは

シングルトンパターンとは、``あるクラスのインスタンスの生成を一つに制限する設計``のことをいいます。


##どのようなケースで使うのか

アプリケーション全体で統一しなければならない仕組みを実装する際に使用されます。
例えば、``インスタンスに共通の値を保持させたい場合``、``画面遷移やAPI、ログイン機能等のロジックを集約したい場合``などに使用します。


##使用方法

```swift 
final class Singleton {
    // 初期化
    static var singleton: Singleton = .init()
    // 外部からのイニシャライズを防ぐ
    private init() {}
```

##最後に

シングルトンパターンは共通化する分、デメリットも多く存在しますが、適切な場面で使うことで便利に使用することができます！（随時更新予定）
競プロ典型90問　001 - Yokan Party

#問題
[競プロ典型90問　001 Yokan Party](https://atcoder.jp/contests/typical90/tasks/typical90_a)

#解法
###使用する考え方

* 二分探索法
* 貪欲法

####二分探索法
ソートされた複数のデータの中からあるデータを探す際に、中央値よりも大きいか小さいかで探す範囲を絞っていく方法。
また、何番目のデータか探すだけではなく、何番目と何番目の間に入るかを調べることもできる。
先頭から見ていくよりもかなり速い。

<details><summary>例</summary><div>
1,2,4,8,16の数字の中から8の場所を見つける場合について考える。

~~~python3
list = [1,2,4,8,16]

lo = 0
hi = len(list)
search = 1

while hi - lo > 1:
    mid = (lo+hi)//2
    if list[mid] <= search:
        lo = mid
    else:
        hi = mid

print(lo)
#3
~~~

1. 1回目は0番目~4番目を調べるため、中央値である2番目の4との大小を比較する。
1. 4より大きいので次は3番目~4番目の数字を調べる。
1. 3番目と4番目の中央値である8との大小を比較する。
    - 統計学等で中央値という場合、データが偶数個の場合は中央の2つの平均を取る。
    - 今回は何番目と何番目の間にあるかを調べたいため、インデックスの3と4の平均の3.5を切り捨てて3番目の8との大小比較を行なっている。
1. 8以下なので3番目~3番目の数字を調べる。
1. 調べる数字が1つになったため8の場所が3番目で確定する。

先頭から調べて行った場合最悪5回かかるが、この方法ならば最悪でも3回で済む。
データの数が大きくなって行った時に真価を発揮する。

**注意**

平均値ではなく中央値と比較すること。
例えば、1というデータの場所を探す際に、1回目に1と16の平均値で8.5と比較してしまった場合、2回目は1,2,4,8の中から探すことになってしまう。最終的に5回の確認が必要になる。


</div></details>

####貪欲法
「このアルゴリズムは問題の要素を複数の部分問題に分割し、それぞれを独立に評価を行い、評価値の高い順に取り込んでいくことで解を得るという方法」らしい。
最初に聞いた時は意味がわからなかったし、今もよく分かってはいないが、例を見て自分の考えをまとめていく。

<details><summary>例</summary><div>
例として上がっていたのは以下の2つがあったのでこれらを見ていく。
なお以下の例は貪欲法で最適解が出るわけではないので注意する必要がある。

1. ある金額を払う時に最小の貨幣で払うための組み合わせを求める問題
    - 評価値 = 1枚あたりの貨幣の価値
    - 日本の貨幣であれば1枚あたりの価値が高い1万円札を出せるだけ出して、次は5千円札、千円札・・・と続いていく。
1. ナップサック問題
    - 評価値 = 重さあたりの価値[v/w]
    - 重さあたりの価値が高い順に、荷物を入れられるだけ入れていく。
</div></details>

####実際の問題での使い方
貪欲法は、羊羹をある基準の長さ以上切り分ける時、切り分けられるだけ切り分けた時いくつになるかを調べるのに使っている。切り分けた数がK+1個以上なればその基準の長さは答えになりうる。

そしてK+1個以上に切り分けられる長さの中で最大のものが答えであるため、それを調べるために二分探索法を使っている。

###　ソースコード

以下が実際に解答したソースコードになる。
check関数に引数として基準の長さを渡すことで、K+1個以上に切り分けられるかをチェックしている。
そしてその範囲を二分探索法で絞っている。

~~~python3
N,L = map(int,input().split())
K =  int(input())
A = list(map(int,input().split()))

A.insert(0,0)
A.append(L)
maxLen = L//(K+1)
minLen = 0

def check(halfLen):
    cnt = 0
    work_a = 0
    for a in A:
        if a - work_a < halfLen:
            continue
        else:
            work_a = a
            cnt += 1
    if cnt >= K+1:
        return True
    else:
        return False

while minLen != maxLen:
    halfLen = ((minLen+maxLen)//2) + 1
    if check(halfLen):
        minLen = halfLen
    else:
        maxLen = halfLen -1 

print(minLen)
~~~

##最後に
###プログラミングに関して
初めは一番小さい切れ目を順番になくしていけば良いのかなとか考えて実装してみましたが全然ダメで、
>L = 6 , A<sub>1</sub> = 2 , A<sub>2</sub> = 3 , A<sub>3</sub> = 4

というテストデータを自分で作ってすぐ詰んでしまい、解法を調べながらコードを書いていきました。

二分探索法は考え方自体は知っていて、例の数字を探す時のように単体で使ったこともありましたが、実際に他の考え方と組み合わせて使うのが初めてだったため、かなり手間取ってしまいました。ただ、かなりの頻度で使うと思うので今回自分なりに整理できてよかったと思います。
貪欲法は一見速くなさそうに見えたんですが、実際に使ってみると計算量自体はデータ量に比例するため使い方によっては計算量がそこまで多くならないのかなと思いました。 

###記事に関して
正直、記事はまだ書き慣れていなくて全く読みやすい記事にはなっていないと思います。
そこは他の人の記事を読んでどういう構成にしたらわかりやすいとか、学んでいけたらと思います。あと、ここをこうしたら読みやすくなる等あれば教えていただけると幸いです。
あと自分で読み返して気になったのが常体じゃなくて敬体の方が良いかなと思いました。常体だと事実を述べているっていうイメージがあるんですが、その割にはふんわりとした説明だったり曖昧な理解だったりが多すぎるかなと。
なので次回からは敬体でもう少し人に説明するような形で書けたらと思います。

以上、最後まで読んでいただきありがとうございます。
Jetpack Compose の Modifier に連なる関数には親子関係が存在する

```kotlin
Box(Modifier.a().b().c()) { Text("hello") }
```

```kotlin
Box {
  A {
    B {
      C {
        Text("hello")
      }
    }
  }
}
```

この2つのコードはほぼ同じ意味を持つ。

`a`拡張関数と`A`コンポーザブルの定義を比較する。

```kotlin
fun Modifier.a() = layout { measurable, constraints ->
  val placeable = measurable.measure(constraints)
  layout(placeable.width, placeable.height) { placeable.place(0, 0) }
}

@Composable
fun A(content: @Composable () -> Unit) {
  Layout(content) { measurable, constraints ->
    val placeable = measurable.map { it.measure(constraints) }
    layout(0, 0) { placeable.forEach { it.place(0, 0) } }
  }
}
```

関数の中身だけを抜き出す。

```kotlin
// a
layout { measurable, constraints ->
  val placeable = measurable.measure(constraints)
  layout(placeable.width, placeable.height) { placeable.place(0, 0) }
}

// A
Layout(content) { measurables, constraints ->
  val placeables = measurables.map { it.measure(constraints) }
  layout(256, 256) { placeables.forEach { it.place(0, 0) } }
}
```

細かな違いはあるものの、ほぼ同じ構造をしていることがわかる。

`A`コンポーザブルの処理順序は次のようになる。

1. `measurables.map { it.measure(constraints) }`：制約を子達に渡す
1. `val placeables = ...`：子達の大きさが決定し、親が受け取る
1. `layout(256, 256)`：子達の大きさを参考に、自分の大きさを決定する
1. `placeables.forEach { it.place(0, 0) }`：子達の位置を決定する

つまり、コンポーザブルの大きさを決めるのは制約と自分と子孫であり、位置を決めるのは先祖である。

この性質は`a`拡張関数にも当てはまる。`b`にとって`a`は親、`c`は子である。
【必須】grepコマンドを使いこなす

grepコマンドとは、linuxのコマンドです。
基本はファイルの中の「文字列(パターン)」が含まれている行を表示するコマンドです。

#grepコマンドを使う場面
・ファイルの中に特定の文字が含まれている行を抽出する時
・文字列がどのファイルにあるかを探す時

##基本の使い方

```
$grep [オプション] 文字列 ファイル名
```
##よく使う方法

例1 　errorという文字がある全ファイルを抽出する

```
$ grep error ./*
```
※複数のファイルから検索するためにワイルドカード（＊）を利用します。

<hr>

例２ postディレクトリの中にある全てのerrorという文字列を抽出する

```
grep error post/*
```
<hr>

例３　現在いるディレクトリは以下の全ファイルからerrorがあるファイルを検索する。なお、

```
grep -rl error .
```
※最後のドットは現在いるディレクトリ配下の全ファイルが検索対象という意味
※-rlオプションはディレクトリの中も検索し、結果はファイル名のみ表示します。
<hr>

複数の文字列を探す方法
①②ともに含まれているファイルを探す

```
grep ①検索文字列 ファイル名 | grep　②検索文字列
```
<hr>

##よく使うgrepコマンドのオプション

-C
検索結果に一致した箇所から前後に指定した行数表示する

-i
大文字と小文字を区別せず検索する

-e
一致処理に指定した正規表現を使う

```
$ grep –e p –e e post/*
```
【補足】-eオプションは一致処理に指定した正規表現を行うオプションだが、実際には、または（or）の検索を行うときに使われる。
ちなみに上記コマンドは、-eオプションを利用し、postディレクトリ内のファイルすべての中から小文字のp、またはeのいずれかを検索できるようにするコマンドです。

-v
一致しないものを検索する

-l
検索結果にファイル名のみ表示する
【使用用途】ファイルのリストを作りたい時

-r
ディレクトリ内も検索対象とする
例　postディレクトリ内のさらに下層のディレクトリ内のファイルすべての中からaの文字を検索するコマンド

```
$ grep -r a post/*
```

・特定のディレクトリを除く場合

現在いるディレクトリから　cartの文字が入っているディレクトリを検索する方法
その際に、vendorディレクトリを除いて検索しております。

```
grep -rl cart ./ --exclude-dir=vendor
```

vendorとstorageディレクトリを除いております。

```
grep -rl cart ./ --exclude-dir={vendor,storage}
```

grepコマンドは使いこなせないと厳しいです。
少しでもご参考になれば幸いです。

参考記事
https://qiita.com/YASU_ojisan/items/8225c87acb4e1468dc90
AWS Certified Cloud Practitionerを受けようと思った人へ

# なぜ書くのか
- 自分がこの試験に興味を持った時に、「勉強法から受験方法までを流し読みできる記事」があればいいと思ったから
- 特に受験方法（オンライン試験の時間帯や当日のやり取り）はあまり情報がなくて不安だったから（→　「受験してみての感想」を参照）

# なぜ受けたのか
- 仕事でAWS使いそうだけど、知識がまったくなかったから
- AWSサービス名となんとなくの役割を理解して、会議やドキュメントを理解できるようになるため
- (Djangoの勉強してたらクラウドでサーバー立ててみたくなったから）

# 筆者について
- 社会人3年目
- メーカーでソフトウェア開発担当
- クラウド開発経験ゼロ

# 勉強方法
#### 作戦
初級の試験かつ選択式の問題ということで、とにかく過去問の数をこなす方針を立てました。

#### 勉強時間
- 約2週間
- 平日1時間、休日3, 4時間ほど  
  実際にやってみて、多すぎず少なすぎずちょうどいい勉強時間だったと思います。サーバー管理やデプロイに関する知識・経験がもとからあれば、この半分くらいの勉強時間で合格できる印象です。

#### 実際にやったこと
- AWSの講座([AWS Cloud Practitioner Essentials](https://www.aws.training/Details/eLearning?id=66479))　1周
    - 目的としては過去問を解く土台を作ること
    - 多少分からない説明があってもとりあえず早く終わらせて過去問に入ることを優先していました。
- Udemyの過去問題集([この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集](https://www.udemy.com/course/aws-4260/))　基礎と応用2週ずつ
    - 目的は、①問題の形式に慣れることと ②合格できるレベルに達すること
    - ここでは分からない問題についてじっくり考えるようにしました。
    - 特に初級者にとっては似たようなサービスが多くみえ、違いが分からなくなることが多々ありました。その度に立ち止まって理解を整理するようにしていました。その方が闇雲に解くより効果があったと思います。

# 受験結果
- 810点/1000点で合格

# 受験してみての感想
- 受験の申し込みなどの準備段階でけっこうつまずきました.
    - まず、オンライン試験（ピアソンVUE）が平日しかやってない。しかも時間帯が就業時間に丸被り(タイミングで変わるのかもしれませんが8:00~17:00くらい)でした。泣く泣く昼休みをつぶして受験する羽目に・・・
    - 試験時にオンラインで確認される書類が結構厳しいです。英語氏名記載の身分証明書がいるのでほぼパスポート一択です。自分はパスポートが見当たらず家中探すはめになりました。パスポート持ってない人どうなるんだろう・・
    - 試験時の机の確認が厳しかったです。試験開始時に机の周り試験官にカメラで確認されるのですが、自分は机にクランプ式の照明まで外すように指示されました。机の上には本当に何もない状態で準備しておく方が良いです。あせります。

- 当初の目的通りAWSのなんとなくの名称とサービスの役割は理解できました。実務で役に立つレベルではないですが、試験合格を目標に頑張れたのでダラダラ勉強するよりは良かったと思います。
- 受験料が高い。。。税込み12100円はけっこう痛い出費です。オンライン受験なら安くなるとかあればいいのに。
picoCTF Scavenger Hunt writeup

# 1. はじめに
ここ２ヶ月ほど、CTFを初めて勉強してるうちにアウトプットも大切と思い、初投稿。picoCTFのwebExploitation分野の問題ScavengerHuntが個人的に為になったという備忘録。

# 2. Writeup
>There is some interesting information hidden around this site [http://mercury.picoctf.net:27393/](http://mercury.picoctf.net:27393/). Can you find it?

リンク先のwebページに隠された情報を見つけられますか？という問題。

アクセスしてみると以下のページが表示される。
![2021-09-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1196804/9daf066e-ee42-7847-f4c3-ad71f8baee57.png)
Whatのタブを押すと表示内容が以下に変化。

```
What
I used these to make this site:
HTML
CSS
JS (JavaScript)
```


ページに情報が隠されているということなのでひとまずF12で開発者ツールを開きソースコードを見てみる。

```
--- http://mercury.picoctf.net:27393/
 |-- index.html
 |-- mycss.css
 |-- myjs.js
```

こんな感じのディレクトリ構成をしていた。それぞれのファイルの中にコメントアウトされいる文字列。

`<!-- Here's the first part of the flag: picoCTF{t -->`

`/* CSS makes the page look nice, and yes, it also has part of the flag. Here's part 2: h4ts_4_l0 */`

`/* How can I keep Google from indexing my website? */`

3つ目のフラグは無く、ヒントになりそうな文字列があった。和訳すると、`どうやってwebサイトがインデックスされないようにしているか？`ということなのでwebサイトをインデックスされないようにする方法を調べる。

[Googleにインデックスされない原因と対策方法について](https://seolaboratory.jp/40191/)

いろいろあるが、フラグを探すということでrobots.txtが怪しい。
`http://mercury.picoctf.net:27393/robots.txt`にアクセスするとビンゴ！

`User-agent: *
Disallow: /index.html
\# Part 3: t_0f_pl4c
\# I think this is an apache server... can you Access the next flag?`

まだ次のフラグメントがある模様。Apacheサーバを使っているらしく、`Access`が大文字なのでその特徴を調べる。`.htaccess`というファイルを配置してディレクトリ毎にサーバの設定ができる様子。
`http://mercury.picoctf.net:27393/.htaccess`にアクセス

`\# Part 4: 3s_2_lO0k
\# I love making websites on my Mac, I can Store a lot of information there.`

今度のヒントはweb制作にマックを使っているというヒント。`Store`が大文字なので関わりありそう。macはファイル作成時に`.DS_Store`という隠しファイルを自動生成する。

`http://mercury.picoctf.net:27393/.DS_Store`にアクセス

`Congrats! You completed the scavenger hunt. Part 5: _d375c750}`

フラグが出揃ったので、つなげると以下のようになる

`picoCTF{th4ts_4_l0t_0f_pl4c3s_2_lO0k_d375c750}`

# 3. 終わりに
Qiitaへの投稿にハードルの高さを感じていたけど、まずは書いてみることが大切そう。継続していろいろ載せていきたい。
Swiftでフィボナッチ数列

Playgroundsで遊んでみた。

``` Swift
func fib(n:Int64) -> Int64 {
    if n==0 {
        return 0
    }else if n==1{
        return 1
    }
    return fib(n:n-1) + fib(n:n-2)
}
print(fib(n:20))

func fib2(n:Int64) -> (Int64, Int64) {
    if n==0 {
        return (0, 1)
    }
    let (x, y) = fib2(n:n-1)
    return (y, x+y)
}
print(fib2(n:20).0)

func fib3(n:Int64) -> ((Int64, Int64), (Int64, Int64)) {
    if n == 1 {
        return ((0, 1),
                (1, 1))
    }else if n%2==0 {
        let ((a, b), (c, d)) = fib3(n:n/2) 
        return ((a*a+b*c, b*(a+d)),
                (c*(a+d), d*d+b*c))
    }else{
        let ((a, b), (c, d)) = fib3(n:n-1) 
        return ((b,a+b),
                (d,c+d))
    }
}
print(fib3(n:20).0.1)
```

実行回数がリアルタイムで見れるのが便利。
シェルスクリプトのforはPOSIXで規定されてるのはforeachスタイルのループだけである

bash のドキュメント（`man bash`）をみると `for` の使い方は以下の ２ つがあり、どちらも同じ `for` というキーワードを使いますが別の機能です。この記事では「foreach スタイル」と「C 言語スタイル」と呼ぶことにします。

**foreach スタイル** 

```sh
for name [ [ in [ word ... ] ] ; ] do list ; done
```

**C 言語スタイル**

```sh
for (( expr1 ; expr2 ; expr3 )) ; do list ; done
```

foreach スタイルは Bourne シェルの最初、つまり 1979 年の [Unix Version 7 に搭載されたバージョン](https://www.in-ulm.de/~mascheck/bourne/v7/)の頃あります（余談ですが最初の Bourne シェルでは `shift` は 1 つしかずらすことができなかったようです）。

POSIX シェルの範囲ではシェルスクリプトには「配列」はありませんが、それに近いものとして「位置パラメータ」があります。`for` はその位置パラメータ（や単語リスト）を処理するものとして作られたものです。また bash、mksh、ksh、yash、zsh という配列があるシェルでは `for` で配列を扱うこともできます。ちなみに (t)csh では同じことをするコマンド名はそのまま `foreach` です。（`foreach name (wordlist)` ... `end`）

一方 C 言語スタイルは ksh88 で導入されました。名前からも分かる通り 1988 年頃の話です。Bourne シェルの開発者はスティーブン・ボーンですが、ksh の開発者はデビッド・コーンで開発者が異なります。ksh では C 言語由来の機能が多く取り入れられました。その一つが C 言語スタイルの `for` です。

POSIX シェルは ksh88 をベースとしていますが、残念ながら C 言語スタイルの `for` は POSIX には取り入れられませんでした（`while` で十分だからでしょうか？）。C 言語スタイルの `for` が使えるのは bash、ksh、zsh のみです。

多くの言語では　C 言語スタイルが最初に実装され、後から foreach スタイルが導入されたのとは反対に、シェルスクリプトでは先に foreach スタイルが実装され、（POSIX では採用されなかったとは言え） 後から C 言語スタイルができたというのは興味深い話だと思います。

とりとめのない話になりましたが、シェルスクリプトにおける `for` コマンドの雑学でした。
コンピュータ回路について　[半加算器と全加算器]

#半加算器と全加算器

###そもそも加算器とは

２進数の足し算を行う回路

#半加算器

１桁目など<font color="red">下位からの桁上がりを考慮しないもの</font>

１桁目では、繰り上げされてくる数字はない


###半加算器の形

![スクリーンショット 2021-09-02 22.56.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803385/1de2cc2e-503d-4ab7-481e-0656fba633f0.png)



半加算器はこの２つの回路からなっている

上が<font color="red">論理積回路</font>、下が<font color="red">排他的論理和回路</font>


#全加算器

２桁目以降の計算など<font color="red">下位からの桁上がりを考慮するもの</font>

###全加算器の形

半加算器の計算を筆算で表すと

![スクリーンショット 2021-09-02 22.57.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803385/923d46ab-2d32-f14f-01e8-afcb7a68c76f.png)



全加算器はこのCSに、下位の繰り上げられてきた数字C’をSに足さないといけない

![スクリーンショット 2021-09-02 22.58.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803385/d0a5493d-df44-6e13-bfb0-75fdcac789da.png)



そしてS + C'という計算になるが、ここではもう繰り上げられてくる数字を考慮する必要はない
つまり**半加算器で計算できる**

よって図にすると

![スクリーンショット 2021-09-02 23.10.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803385/34064808-37ee-f411-f19d-4c4f37f5825a.png)



最後に２つの半加算器から出た出力Cはまとめないといけない

ここでは単なる２進数の計算から、出力Cに当てはまる組み合わせを考慮すると、
論理演算は<font color="red">論理和回路</font>となる

###つまり

全加算器は

<font color="red">半加算器２つと論理和回路でできている</font>
>参考書籍
>きたみりゅうじ　『キタミ式　イラストIT塾　基本情報技術者　令和０３年』 技術評論社 2020年
homebrewをM1チップのmacにインストールする手順と注意点

###◎こちらの記事を参考に実行

https://www.teamxeppet.com/macbook-m1-homebrew-install/

この記事の最後で実行している以下のコマンドについて補足

```
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/ユーザ名/.zprofile
```

`eval`コマンドとは
指定した文字列を評価後（環境変数も評価後）に連結して、現在のシェルに実行させます。

今回の場合は`brew shellenv`を実行しているようだ。
`brew shellenv` は数行の export 文が出力されるので、コレを `eval` することで、`brew` コマンドがそのシェルで動作するようになる。

※参考記事

https://neos21.net/blog/2020/08/28-03.html
Algorithmためのデータ構造をPythonで実現しましょう。ーその3[linked list unorderedの実現]

タイトルの通り、今回はLinked list unorderedというData structureはpythonでどのように実現するのかを見ていきます。


# linked list unorderedはなに？
今回はunordered、要するに順番に並ぶではなく、好きな場所で、数値の大きさと関係なく、自由に並んでいるLinked listのこと。

じゃLinked listはなんでしょう？
図で見てみます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729963/0ba9f8dd-ca8e-8b08-b64c-0a7d9ea79bfc.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729963/fcce2313-1083-9af3-a568-8c536d26deb4.png)

左の感じと右の感じを合わせて、Linked listと呼ばれています。

では、早速Linked list unorderedの要素を確認しましょう！

- Linked listには箱みたいなものがありまして、それはNodeと呼ばれます。
    - Nodeには保存されているデータ(値)と次のNodeを連結するための情報が含まれています。
    - 次のNodeを連結するための情報はNoneの場合、今の指しているNodeが最後となります。
- Head はLinked listの始まり(入口)で、EndはLinked listの最後を指します。

それほど難しく考えなくてもいいので、まとめると：
Linked listはNodeという箱は必須で、Nodeにはまた値と次のNodeに連結するための情報が含まれています。

# Pythonで実現しよう！
```python
class Node(object):
    def __init__(self, init_data):
        self.init_data = init_data
        self.next_data = None

    def getData(self):
        return self.init_data

    def getNext(self):
        return self.next_data

    def setData(self, new_data):
        self.init_data = new_data

    def setNext(self, new_Next_data):
        self.next_data = new_Next_data
```

```python
class unorderedList(object):
    def __init__(self):
        self.head = None

    # insert data
    def insert(self, item):
        temp = Node(item)
        temp.setNext(self.head)
        self.head = temp

    # calculate size
    @property
    def size(self):
        current_node = self.head
        count = 0
        while current_node:
            count += 1
            current_node = current_node.getNext()
        return count

    # search data
    def search(self, target):
        current_node = self.head
        found = False
        while current_node and not found:
            if current_node.getData() == target:
                found = True
            else:
                current_node = current_node.getNext()
        return found

    # remove data
    def remove(self, item):
        current = self.head
        previous = None
        found = False
        while current and not found:
            if current.getData() == item:
                found = True
            else:
                previous = current
                current = current.getNext()
        if previous == None:
            self.head = current.getNext()
        else:
            previous.setNext(current.getNext())
```
remove methodについてちょっと補足します。
ある特定のNodeを削除したい場合、特定されたNodeの一個前のNodeを特定された一個後ろのNodeに関係を構築するば良いです。

では実物化してみます。(日本語は多分実物化かな...間違いたらごめん)

```python
obj = unorderedList()
obj.insert(5)
obj.insert(8)
obj.insert(2)
obj.insert(11)
obj.insert(4)
print(obj.size)
print(obj.head.getData())
print(obj.remove(2))
print(obj.search(4))
print(obj.size)
```

出力>>>

```python
5
4
None
True
4
```
うまくできました！5個の数値をlinked listに追加し、一個removeした後、4個の数値は残されました。
SalesforceのOauthでinvalid_grant authentication failure

## 記事の概要
Salesforce Oauth2のuernameとpasswordを使用するパターンでinvalid_grantエラーに悩まされたので、備忘録


## エラーが出た場合の確認チェックポイント
・grant_typeにpasswordという文字列が設定されているか

・client_idに接続アプリケーションのコンシューマ鍵を設定しているか

・client_secretに接続アプリケーションのコンシューマの秘密を設定しているか

・usernameにsalesforceにログインする時に使用するユーザ名を設定しているか

・passwordにsalesforceにログインする時に使用するパスワードを設定しているか

・接続アプリケーションの管理で「IP制限を緩和」に設定されている
->passwordの末尾にセキュリティトークンが付与されていないことを確認。IP制限を緩和の場合はセキュリティトークンは不要


・接続アプリケーションの管理で「IP制限を適用」に設定されている
->passwordの末尾にセキュリティトークンが付与されていることを確認。IP制限を適用の場合はpasswordの末尾にセキュリティトークンを付与する必要があります

・OAuth ポリシーの許可されているユーザが「すべてのユーザは自己承認可能」に設定されているか

・postするアドレスは正しいか

```
本番環境
https://login.salesforce.com/services/oauth2/token
テスト環境
https://test.salesforce.com/services/oauth2/token
```

問題の切り分け方としては、まずはIP制限を緩和に設定し、認証が成功するかどうか確認してみる。
IP制限を適用に戻し、認証が失敗するようならセキュリティトークンが誤っている可能性が高いです。
（今回は、プロパーから連携されたセキュリティトークンが間違っていて1日溶かしました・・・）


## おまけ　エラーに関係ありそうでなかった設定値

・セキュリティ->ネットワークアクセスのIP制限リスト
->いくつかstack_overflowで設定を確認との記事があったが、セキュリティトークンを使用できる環境であれば、関係なかった。
（IP制限されていてもセキュリティトークンが正しい場合は認証に成功する）

・プロファイル->接続アプリケーションへのアクセスのチェックボックス
->チェックボックスの有無で特に認証に影響はなかった。
UITextViewのtextに表示する文字列を改行して読みやすくする。

#今回の内容
*  表示する文字列を改行して、読みやすくします。
*  今回、私が使った改行方法についてだけを投稿しています。

<img width="150" alt="2A7C86A5-A0F6-47F3-A771-4E1FD3D52464_1_201_a.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/945fa214-ddd5-f154-dc58-8d90a9b9282a.jpeg"> 

#コードと簡単解説

* 緯度と経度を取得して、住所などに変換した値をUITextViewのtextに表示しています。

* 表示したい文字列などを,下記のコードのように`"""`で囲むと上の画像の様に改行します。

```Swift:

           ~~~~~~~~~~省略~~~~~~~~~~

    @IBOutlet weak var currentLocationTextView: UITextView!

           ~~~~~~~~~~省略~~~~~~~~~~

    //使用者の現在地の緯度と経度を取得して、住所か建物の名前などに変換
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        
        CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: (locations.first?.coordinate.latitude)!, longitude: (locations.first?.coordinate.longitude)!)) { placeMark, error in
            
            if error != nil{
                
                return
            }
            
            if let resultPlaceMark = placeMark?.first{
                
                if resultPlaceMark.administrativeArea != nil || resultPlaceMark.locality != nil{
                    
                    self.currentLocationTextView.text = """
                        緯度
                        [\((locations.first?.coordinate.latitude)!)]
                        
                        経度
                        [\((locations.first?.coordinate.longitude)!)]
                        
                        場所
                        [\(resultPlaceMark.administrativeArea!)]
                        [\(resultPlaceMark.subLocality!)]
                        [\(resultPlaceMark.name!)]
                        """
                    
                }else{
                    
                    self.currentLocationTextView.text = resultPlaceMark.name!
                    
                }
            }
        }
    }
```

#終わり
間違いの指摘、ご質問などありましたら、コメントまでお願い致します。
sliceとspliceの違いを簡単にまとめる。

#はじめに
文字の並びが似ているけれど使い勝手は全く異なる、sliceとspliceの違いについてまとめます。

#sliceとspliceの違い

###slice

* 元の配列の値を変更しない。
* 取得する値のstartとendの位置を指定するのみで値の挿入などはできない。

###splice

* 元の配列の値を変更する。
* 取得する値の範囲を決めて、別の値を追加したり削除したりできる。

sliceが配列を参照のみするのに対して、spliceは積極的に配列の値を変化させたいときに使えます。

#sliceの使用例
sliceはカッコ内に1つもしくは2つの数字を取ることができます。
最初の数字はスタート位置を、2つ目の数字は終了位置を示します。
仮に数字が1つの場合は指定したスタート位置から最後の配列まで取得します。

```jsx
const numArray = [1, 2, 3, 4, 5, 6, 7, 8];

const list = numArray.slice(0, 2);

//出力　[1, 2]
console.log(list);

//出力　[1, 2, 3, 4, 5, 6, 7, 8]
//元の配列は変化していない。
console.log(numArray);
```


#spliceの使用例
spliceの場合は、1つ目がスタート位置、2つ目がスタート位置から何個目までを取り出すかを示します。
そして3つ目以降に値がセットされた場合、スタート位置の後にそれらの値を追加します。
このように元の配列の値を変化させるメソッドを破壊的メソッドと呼びます。

```jsx
const numArray = [1, 2, 3, 4, 5, 6, 7, 8];

const list = numArray.splice(0, 3, "one", "two", "three");

//出力　[1, 2, 3]
console.log(list);

//出力　["one", "two", "three", 4, 5, 6, 7, 8]
//元の配列が変化している。
console.log(numArray);
```

#さいごに
使い勝手が良いのは元の配列を破壊せずに配列内の任意の値を持ってこれるsliceだと思います。
しかし、前から2つずつ塊として配列から取ってきたい場合などはspliceの方が便利な場合もあります。
postgres外部接続備忘録

#postgres外部接続備忘録

サーバーエンジニアが退職して、サーバー関連のことを任されることになった私の備忘録。

今回はpostgresSQLを外部から接続できるように設定した際にハマったのでメモ。

環境
SentOS 6.7
postgres 9系

##まずは外部接続できるように設定

私の環境ではまずpostgresというユーザーでログイン

```
# su - postgres
```

dataディレクトリに移動

```
$ cd $PGDATA
```

$PGDATAにはdataディレクトリのPATHが入っているみたい
この辺の理解はかなり薄いのでインストールする機会があれば勉強してみようと思う。

postgres.conf内の内容を書き換える。

```
$ vi postgres.conf
```

```postgres.conf
#listen_addresses = 'localhost'
listen_addresses = '*'　#ここを追記
```
IPアドレスを指定することも出来るらしいが今回はこれで。

##外部接続できるIPアドレスを登録
同ディレクトリ内のpg_hba.confを編集
一番下より少し上の方に
\# IPv4 local connections:
という場所に以下に追記していく

```pg_hba.conf
host  DBname  Username  ***.***.***/32    md5
```
hostというのはTCP/IPの事らしい、fmfm。

設定を読み込むために

```
$ pg_ctl reload
```

##ポート開放する

sentOS6ではiptablesとやらを設定してポート開放しないといけないらしい
とりあえず中身を見てみる。
rootに戻って

```
# cd /etc/sysconfig
# vi iptables
```

うーーーーん、ずらずらと記述がしてある・・・
参考サイトには該当箇所をコピーして、番号を書き直せばOKと書いてあるのでその通りやってみる。

```iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
```
22というのはsshのことだな
こいつを利用させてもらう
今回はデフォルトの５４３２を利用

```iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport ５４３２ -j ACCEPT
```

設定を読み込み

```
# /etc/init.d/iptables restart
```

よしこれでOK！！！なはず！
手元のphpのプログラムから接続を試みる・・・・・

・・・・・
・・・・・
・・・・・

接続できない・・・・
記述ミスがないか確認

強強エンジニアに聞いても書き間違い無いですか？？
ちゃんとリロードしました？？
という返答しか返ってこない。

リモートワークはすぐに手元が見せれないのが難点ですよね。

いろいろ調べた結果
postgres.confの設定を変えると変えた中身次第ではpostgres本体の再起動が必要みたい。
ということでpostgresの再起動。

```
# su - postgres
$ pg_ctl stop
$ pg_ctl start
```

とここで起動した際にエラー

```
FATAL:  lock file "postmaster.pid" already exists
・・・
・・・
・・・

```
動いているプロセスがあるのにシャットダウンしたらこんなエラーがでるらしい？？
プロセスを確認

```
$ ps auxww
```

たくさん動いてるのでとりあえずkillコマンドで削除しまくる。

そしてpostmaster.pidというファイルがあるとLOCKされていると書いてあるので削除

```
$ rm postmaster.pid
```

改めて

```
$ pg_ctl start
```

無事接続、お疲れ様でした。
色々省いている部分もありますが、変なこと書いてたら指摘していただけると嬉しいです。
サーバーに関してはまだまだひよっこなので危なっかしいところもありますが
顧客は待ってくれませんので、がんばります！！

参考サイト
>https://qiita.com/nao_yoshi/items/a5106e8f08547a54d5ea
>https://loups-garous.hatenablog.com/entry/20120917/1347900472
>https://gist.github.com/taea/8865831

忘れっぽいので記憶に留める＆見返すためにちょくちょく更新していこうと思います。
Workato：RubyコネクターでSlackのユーザー一覧を取得する


# はじめに
Slackのメンテナンスや、Bot処理の際に、現在のSlackワークスペース上のユーザーを取得したい場合があります。

このような処理はノーコードで実装すると複雑になりがちですので、Rubyコネクターを利用して実装することとします。

# 前提条件
https://api.slack.com/ で以下の対応が事前に行われていること

- Rubyコネクターで利用するSlackアプリのOAuthトークン（Bot User Token）が取得済みである
- 上記OAuthトークンにおいては、Bot token scopesとして `users:read` が有効になっている（許可されている）

# 手順
## １．Rubyコネクターを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/9b31ad3e-563e-74c4-10f3-659844d16393.png)

## ２．Inputに以下の変数を定義します。必要に応じて値をセットします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/7f11980a-a21c-1a35-601c-d5c324a57520.png)

|変数|値|
|:---:|:---:|
|token|SlackのOAuth(Bearer)トークン |

## ３．Output schemaを以下のとおり定義します。
### １）「Use JSON」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/d328d68a-61f5-5e66-45e2-180e1a5ea28a.png)

### ２）下記ページの「Example responses」の『Common successful response』をコピーし、Workatoの「JSON Sample」へペーストし、「Next」をクリックします。

https://api.slack.com/methods/users.list

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/609d69b8-0339-3dfc-0430-8f24a81b0c37.png)

### ３）内容を確認し、「Generate schema」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/921964ba-1367-f43a-94f7-70ccd8beb16c.png)

### ４）JSONをもとに、スキーマが自動的に生成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/5c1c47f6-16f0-d6b2-624a-dd0b3e419c28.png)


## ４．Codeへ以下のコードをセットします。

```ruby

url = 'https://slack.com/api/users.list'
cursor = ''
is_last = false
 
result = []
while ! is_last do
    res = get(url)
        .params(
          cursor: cursor,
          include_locale: 'false',
          limit: '100'
        )
        .headers(Authorization: 'Bearer ' + input['token'])
        .response_format_json
 
    res["members"].each do | member |
        if ! member['deleted'] && ! member['is_bot'] && ! member['is_app_user']
            result.push(member)         
        end
    end
     
    if res["response_metadata"]["next_cursor"].blank?
      is_last = true
    else
      cursor = res["response_metadata"]["next_cursor"]
    end
end
       
{
  members: result
}
 
```


# その他

以下のようにCallable Recipeとすることで、複数のレシピで本レシピの処理を活用いただけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/aa6f6ab4-cb62-ff10-a46f-2a76cc12a59c.png)
ubuntuで録画鯖

PXS1UDのドライバーインストール

```
wget http://plex-net.co.jp/plex/px-s1ud/PX-S1UD_driver_Ver.1.0.1.zip
unzip PX-S1UD_driver_Ver.1.0.1.zip
sudo cp PX-S1UD_driver_Ver.1.0.1/x64/amd64/isdbt_rio.inp /lib/firmware/
```
カードリーダードライバーのインストール

```
sudo apt install -y build-essential git
sudo apt install -y pcscd libpcsclite-dev libccid pcsc-tools
```
B-Casのデコード用ライブラリのインストール

```
sudo apt install -y cmake g++
wget https://github.com/stz2012/libarib25/archive/master.zip
unzip master.zip
cd libarib25-master
cmake .
make
sudo make install
cd ../
```
録画用コマンドのインストール

```
sudo apt install -y autoconf automake libtool autoconf-doc libtool-doc
wget http://www13.plala.or.jp/sat/recdvb/recdvb-1.3.1.tgz
tar xvzf recdvb-1.3.1.tgz
cd recdvb-1.3.1
./autogen.sh
./configure --enable-b25
make
sudo make install
cd ../

```


node.js Ver.16・pm2 curlインストール

```
apt install -y curl
(但しraspberryOSは入れなくても大丈夫）
curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt install -y nodejs
sudo apt install -y npm
sudo npm install -y pm2 -g
```
mirakurun インストール

```
sudo npm install mirakurun -g --unsafe --production
sudo nano /usr/local/etc/mirakurun/tuners.yml
```

```
PX-S1UD
- name: PX-S1UD-1
  types:
    - GR
  command: recdvb --b25 --strip --dev 0 <channel> - -

- name: PX-S1UD-2
  types:
    - GR
  command: recdvb --b25 --strip --dev 1 <channel> - -
```
```
PX-Q1UD
- name: PX-Q1UD-1_1
  types:
    - GR
  command: recdvb --b25 --strip --dev 0 <channel> - -

- name: PX-Q1UD-1_2
  types:
    - GR
  command: recdvb --b25 --strip --dev 1 <channel> - -

- name: PX-Q1UD-1_3
  types:
    - GR
  command: recdvb --b25 --strip --dev 2 <channel> - -

- name: PX-Q1UD-1_4
  types:
    - GR
  command: recdvb --b25 --strip --dev 3 <channel> - -
```

そして地元局をスキャンしていく

```
curl -X PUT "http://localhost:40772/api/config/channels/scan"
```
終わったら
sudo mirakurun restart

```
sudo apt install -y sqlite3
sudo apt install -y ffmpeg
```

```
git clone https://github.com/l3tnun/EPGStation.git
cd EPGStation
npm run all-install
npm run build
```
```
cp config/config.yml.template config/config.yml
cp config/operatorLogConfig.sample.yml config/operatorLogConfig.yml
cp config/epgUpdaterLogConfig.sample.yml config/epgUpdaterLogConfig.yml
cp config/serviceLogConfig.sample.yml config/serviceLogConfig.yml
cp config/enc.js.template config/enc.js
```
```
sudo npm install pm2 -g
sudo pm2 startup
pm2 start dist/index.js --name "epgstation"
pm2 save
```
ライブ視聴するには

cd EPGStation/config
nano config.yml

ffmpeg: /usr/local/bin/ffmpeg
ffprobe: /usr/local/bin/ffprobe
のところを

```
ffmpeg: '/usr/bin/ffmpeg'
ffprobe: '/usr/bin/ffprobe'
```
に直して
pm2 restart epgstation
してあげれば大丈夫です。
毎週自動でシート名が日付のスプレッドシートを作成したい

理想はこんな感じ。
毎週自動でスプレッドシートを指定フォルダに作成する。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1955768/96959ebb-2db1-7ffb-3e8d-46ff2d6582e5.png" width=50%>

# コード
余力のある方は`try-catch-finally`でエラー処理。
エラー発生時、自分宛てにメール送信すると良いかも。
メール送信は`GmailApp.sendEmail`。

```gas:auto.gs
function makeSpreadSheet() {
  // 今日の日付
  const DateObj = new Date();
  const Today = Utilities.formatDate(DateObj, 'Asia/Tokyo', 'yyyyMMdd');

  // 新規シート作成
  const SpreadSheet = SpreadsheetApp.create(Today);

  // シート名を日付に変更
  SpreadSheet.getSheetByName("シート1").setName(Today);

  // ファイルのオブジェクトを定義
  const File = DriveApp.getFileById(SpreadSheet.getId());

  // 指定フォルダにファイルを移動
  DriveApp.getFolderById('******************').addFile(File);

  // 元ファイルを削除
  DriveApp.getRootFolder().removeFile(File);
}

```

*の部分は下図の黒いところ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1955768/0f0d2ed5-8917-003b-00c8-5a96301d0d6e.png)

# トリガー作成
トリガーをクリック。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1955768/2cfddd05-f542-d0da-ebe6-58ba6ac8429c.png">

画面右下の「トリガーを追加」をクリックして下図のようなトリガーを作成して保存する。
※例の場合は毎週水曜日の0時～1時に関数を実行するトリガーとなる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1955768/61bc8560-9f73-95c5-e089-6d6b12692884.png)

# まとめ
作成できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1955768/2fa03b60-7477-4c5f-9b2e-4f389178f459.png)
セルに何か書いた状態で保存もできると思う。
phpMyFAQの業務導入顛末記（その１）

### 1. 背景 ###


筆者の職場では、主にユーザーのサーバーやネットワーク環境の構築～保守・運用をやっています（筆者はやってないけど）。
作業は小規模ながらも多量の案件を効率よくさばく必要があり、特に顧客ごとの担当も決まっていないため、過去に各人が経験したノウハウやヒヤリハットをどう全員に共有するかが課題となっていました。

そういった情報共有を目的として、OSSなどフリーの「情報共有ツール」と称するツールを探している途中で見つけたのが、今回取り上げるOSSの<b>phpMyFAQ</b>です。
https://www.phpmyfaq.de/

これがなかなかの「めっけもん」やったんで、以降そのインストールからデータ移行、業務への導入に関してその顛末をご紹介していきたいと思います（現在進行形）。

***
### 2. phpMyFAQの特徴 ###

1)PHPを使った、フリーのオープンソースツールである：ある程度の調整や不具合は自分で対処
　最新版のver.3.0.9は、PHP7.2～で稼働します。
　もちろんソースも公開されていて、カスタマイズ可能です。
　https://www.phpmyfaq.de/docs/3.0

2)特殊な環境を要しない：「Apache + PHP + MariaDB」etc.というコテコテの環境で稼働
　筆者は職場のMariaDBを使いましたが、PostgreSQLやSQLiteも使えるようです。

3)FAQサイトにありがちな、「一方的上意下達」なサービスではない
　これは、たぶんこのツールの最大のウリなんで後述。

***
### 3. phpMyFAQでできること ###

図解します。
機能的には、「FAQサイト構築ツール」と言うより「情報共有コミュニティサイト」といった感じです。

1)管理者が記事を記載し公開：通常のFAQサイトのイメージです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170624/d8c515f2-269a-5be3-95bc-390e8fea7d80.png)
2)一般ユーザーが記事を提案し、管理者が承認して公開
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170624/d0cb39f1-721d-a61e-d5be-561bb21311b2.png)
3)ユーザー間のQ&Aを管理者が承認して公開
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170624/c1b7291f-1ee0-a3c0-1b92-029688c1c2f2.png)

***
### 4. phpMyFAQのインストール＆設定 ###

・・・と書いてはみたものの、ことインストール＆設定**だけ**に関して言えばネット検索すれば山ほど出ますし:sweat:、きわめて簡単ですので省略。

ただ、（ネット記事でもほとんど言及はありませんが）インストールに当たっては下記のような制約がありますのでお気を付けを。
※筆者の環境は
　・CentOS7
　・Apache2.4.6
　・PHP7.3.27
　・MariaDB5.5.68
　・OpenSSL1.0.2
　です。

1)".htaccess"が使えるディレクトリであること
これはちょっとハマりました。
Apacheの設定で、せめてインストール先ディレクトリだけは".htaccess"が使えるようにした方がよいです。

```httpd.conf
<Directory "/var/www/html/phpmyfaq/">
Allow Override All
Order deny,allow
allow from all
</Directory>
```
2)拡張機能"Pecl-Zip"が必要
後から分かったことなんですが・・・これオプション機能なんで、必要であればインストールすればええんです。
それが必須になってるって・・・:confounded:
しゃーないんで、
php-pecl-zip-1.19.3-2.el7.remi.7.3.x86_64
をインストールして解消。
アニメーションをつける方法

◾️ アニメーションをつける方法が超絶簡単！！

　　書き方：
 
https://gyazo.com/c825cbc5540ebe5dc7d25cf6a98f8a7a

解説：　trasitionとは文字にアニメーションをつける方法。５sと書かれているのは秒数を表している。
　　　　今回は５秒間だけアニメーションをつける指示を出したので5sとなっている！
　　　　是非この内容を頭にマージしていこう！:merge:
Workato：RubyコネクターでSlackのチャンネル名からチャンネルIDを取得する


# はじめに
WorkatoでSlackに関する何らかの処理を行う際に、Slackのチャンネル名に対応するチャンネルIDが必要となる場合があります。

Workatoではこのような処理をノーコードで実装することは出来ますが、実装の複雑化や実行タスク数の増加が生じるため、Rubyコネクターを利用するのが効果的です。

ここでは、Rubyコネクターによるチャンネル名からチャンネルIDを取得する手順についてご説明します。

# 前提条件
https://api.slack.com/ で以下の対応が事前に行われていること

- Rubyコネクターで利用するSlackアプリのOAuthトークン（Bot User Token）が取得済みである
- 上記OAuthトークンにおいては、Bot token scopesとして `channels:read` `groups:read` `im:read` `mpim:read` が有効になっている（許可されている）

# 手順
## １．Rubyコネクターを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/9b31ad3e-563e-74c4-10f3-659844d16393.png)

## ２．Inputに以下の変数を定義します。必要に応じて値をセットします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/5011b48f-77dd-5774-292b-09e8ce539959.png)

|変数|値|
|:---:|:---:|
|token|SlackのOAuth(Bearer)トークン |
|channel|チャンネルIDを取得したいSlackチャンネル名 |

## ３．Output schemaを以下のとおり定義します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/42e0b2ea-a699-aa50-c344-f57633aa33c8.png)

## ４．Codeへ以下のコードをセットします。

```ruby

url = 'https://slack.com/api/conversations.list'
cursor = ''
is_last = false
is_exist = false
 
result = {
  id: '',
  channel: input['channel']
}
 
while ! is_last do
    res = get(url)
        .params(
          cursor: cursor,
          exclude_archived: 'true',
          limit: '100',
          types: 'public_channel, private_channel'
        )
        .headers(Authorization: 'Bearer ' + input['token'])
        .response_format_json
 
    res["channels"].each do | channel |
        if input['channel'] == channel['name']
          result['id'] = channel['id']
          is_last = true
          is_exist = true
        end
    end
     
    if res["response_metadata"]["next_cursor"].blank?
      is_last = true
    else
      cursor = res["response_metadata"]["next_cursor"]
    end
end
       
{
  id: result['id'],
  channel: input['channel'],
  exists: is_exist
}
 
```




なお、以下のようにCallable Recipe化していただきますと、様々なレシピで本処理を活用いただけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/8dde7b0d-f3ee-45a7-a648-c60cb9b27d66.png)
【4枚目】おっさんが入門CakePHP　(動画第５回：Modelを使ってデータを表示)

今回はDB使って画面表示するらしい。
今回も動画に従って進めます。
https://www.youtube.com/watch?v=AxnQ1K3yDME&t=559s

XAMPPコンパネで各サービスを開始
![xampp_st.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/f0b2c05d-9e49-a6a3-89e9-ab611132bd58.png)

ブラウザでアパッチの動作確認。
※databaseの個所が赤いのでDB接続できていないということ。
![cake_st.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/d5975d06-1ef6-608f-ecd1-9c594bc2e6e4.png)

XAMPPコンパネでphpmyadminを起動
![x_mysql_admin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/3a56cb3d-390b-5661-225a-e30848ef89b5.png)

phpmyadminで捜査を進める。
DB作成し
![db_make.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/bc6b3dd7-dbf1-7778-04da-8ba89a019885.png)
ユーザ作成して権限付与。
SQLでusersテーブルを作成

```
CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `account` varchar(20) NOT NULL COMMENT 'ログインID',
  `password` varchar(255) NOT NULL COMMENT 'パスワード',
  `name` varchar(20) NOT NULL DEFAULT '' COMMENT '名前',
  `email` varchar(255) NOT NULL DEFAULT '' COMMENT 'E-Mail',
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '作成日',
  `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新日',
  `created_user` varchar(45) DEFAULT NULL COMMENT '作成者',
  `modified_user` varchar(45) DEFAULT NULL COMMENT '更新者',
  PRIMARY KEY (`id`),
  UNIQUE KEY `account` (`account`)
);
```

1回目にSQLをコピペ実行した際は文字化けで上手く実行できなかった。
手打ちSQL実行で成功。
制作担当者に伝えて修正してもらった。
担当はMacで制作しているらしく正常動作するとの事。
※私はWindows10proで勉強進めてる。

CakePHP側の接続設定だが
configフォルダ内のapp.phpに設定記述がある。　↓　この辺
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/76540043-c002-ead0-1923-20b0b1ce28e4.png)

設定がすんだらブラウザで確認。
赤枠内が緑の表示ならOK。
![cake_db_ok.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/ae73cab0-d298-0a3d-1b09-0e0a60bd2c72.png)

GitHubからはこんな感じでまとめてダウンロードした。
![git_hub_dl.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/be31a6b9-0fa8-5f1c-3051-f6cbf7558911.png)

今回使うのは　↓　ココの下
![dl_src_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/2438ce1e-c589-eaa5-5bc2-e6b0c2237b31.png)
src下のファイルをプロジェクトにコピーしてブラウザで確認
動画と同様に確認できる。

データをSQLでインサートして再度ブラウザで確認。

```
INSERT INTO `users`(`account`, `password`, `name`, `email`, `created`, `modified`, `created_user`, `modified_user`) 
  VALUES ('taro','12345','山田　太郎','xxx@xxx.xxx',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP,'admin','admin');

```

データが上手く表示されていない。
ソース見ても特に悪いところもなさそうなので
atomにリロード的な機能が無いか確認。
reopen project　っての有りました。
![atom_reopen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/bdd3a8ac-84ac-2c47-b71d-ab202173c79b.png)

リオープン後にブラウザで確認。
今度はちゃんとデータ表示されました。
![webusers.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/2cff5d9e-f02f-38c0-e4df-5e4ab64630f5.png)

今回のまとめ
・動画や指示書の指示どおりに進めてもうまくできない場合はある。
・文字化け注意
・リロードや再起動は基本
ターミナルを使う時に知っておくと便利


# ターミナルコマンド編
ターミナルでコマンドを編集する時によく使うコマンドを紹介します。
### cursorの移動

- `Ctrl+A` 一番最初に移動
- `Ctrl+E` 一番最後に移動
- `Ctrl`+`Left Arrow Key` 1文字ずつ後ろに戻る
- `Ctrl`+`Right Arrow Key`1文字ずつ前へ進む

### 削除

- `Ctrl+K` cursorから最後まで削除
- `Ctrl+X`+`Backspace Key` cursorから前のすべて削除

## viエディター編
viを使う時によく使うコマンドを紹介します。
### cursorの移動

- `^` 一番最初に移動
- `$` = `Shift+4` 一番最後に移動
- `b` 1文字ずつ後ろに戻る
- `w`1文字ずつ前へ進む

### 削除

- `d`+`$`  cursorから最後まで削除
- `d`+`^` cursorから前のすべて削除
- `:d` or `dd` cursorのある行の削除
-  `:d5` or `5dd` cursorから下の5行の削除


####下記もよく使います

- `:set number`
- `:set nonumber`
- `:set autoindent`
- `:set noautoindent`
- `/検索したい文字列`