OmniAICreator/Qiita-1.07M huggingface dataset:
AtCoder Beginner Contest 150

https://atcoder.jp/contests/abc150

今回まだunratedになった。

###C - Count Order

直接にitertools.permutationsを利用する。

```python
from itertools import permutations as perm
import sys
readline = sys.stdin.buffer.readline

n = int(readline())
p = tuple(map(int, readline().split()))
q = tuple(map(int, readline().split()))

p_lst = list(perm(list(range(1, n + 1)), n))  # 排列を生成する。辞書順整理済み
pn = qn = 0
for i, j in enumerate(p_lst, 1):
    if p == j:
        pn = i
    if q == j:
        qn = i
    if pn * qn != 0:
        print(abs(pn - qn))
        quit()
```

###D - Semi Common Multiple

```python
import sys
read = sys.stdin.buffer.read
from fractions import gcd
from functools import reduce

n, m, *alst = map(int, read().split())
mm = 2 * m  # 2Xはaiの奇数倍


def lcm(x, y):
    g = gcd(x, y)
    if x // g % 2 == 0 or y // g % 2 == 0:
    # 両方の余りが同時1でないとlcmがどちらかの偶数倍になる
        print(0)
        quit()
    g = x * y // g
    if g > mm:
        print(0)
        quit()
    return g


g = reduce(lcm, alst)
res = (mm // g)
print(res // 2 + res % 2)
```

###E - Change a Little Bit

C列が整理済みとする。(C1<=C2<=C3...)
規則を見つけてみる。

|n=1, 0|C1|
|:--|--:|
|1|1|
|合計|1|

|n=2, 00|C1|C2|
|:--|--:|--:|
|01|0|1|
|10|1|0|
|11|2|1|
|合計|3|2|

|n=3, 000|C1|C2|C3|
|:--|--:|--:|--:|
|001|0|0|1|
|010|0|1|0|
|100|1|0|0|
|011|0|2|1|
|101|2|0|1|
|110|2|1|0|
|111|3|2|1|
|合計|8|6|4|

|n=4, 0000|C1|C2|C3|C4|
|:--|--:|--:|--:|--:|
|...|...|...|...|...|
|合計|20|16|12|8|

よって規則は、
$\quad 2^{n}* {\sum_1^n} C_i*(n+2-i)*2^{n-2}$

$ = 4^{n-1}* {\sum_1^n} C_i*(n+2-i)$
(n=1時も満足する)

```python
import sys
read = sys.stdin.buffer.read

mod = 10**9 + 7
n, *clst = map(int, read().split())
clst.sort()
res = sum((n + 2 - i) * item for i, item in enumerate(clst, 1))
print((4**(n - 1) * res) % mod)
```

###F - Xor Shift

自分のKMPが全然間に合わなかったからZ-functionを勉強した。
[Z-function and its calculation](https://cp-algorithms.com/string/z-function.html)

```python
import sys
read = sys.stdin.buffer.read

n, *lst = map(int, read().split())
al = lst[:n]
bl = lst[n:]


def convert(A):
    return [x ^ y for x, y in zip(A, A[1:])] + [A[-1] ^ A[0]]


a = convert(al)
b = convert(bl)


def Z_algorithm(s):
    n = len(s)
    z = [0] * n
    l, r = 0, 0
    for i in range(1, n):
        if i <= r:
            z[i] = z[i - l] if z[i - l] < r - i else r - i - 1
        while i + z[i] < n and s[z[i]] == s[i + z[i]]:
            z[i] += 1
        if i + z[i] - 1 > r:
            l, r = i, i + z[i] - 1
    return z


Z = Z_algorithm(b + [-1] + a + a)[n + 1:n + n + 1]

K = [i for i, x in enumerate(Z) if x == n]
X = [al[k] ^ bl[0] for k in K]

print('\n'.join('{} {}'.format(k, x) for k, x in zip(K, X)))
```
コードはともかく、重要なのはZ-functionの理解です。
振り返り Atcoder ABC150 C問題

# 目的
[公式解説](https://www.youtube.com/watch?v=9MphwmIsO7Q)を観てもよく分からなかった人向けに個人的な備忘もかねた解説メモ

# 対象の問題
[ABC150 C - Count Order](https://atcoder.jp/contests/abc150/tasks/abc150_c)

# 解法の大まかな流れ
1. 順列を辞書順で全て作成する
   - `mp`というMapを作成
   - key:順列
      - 例えば1~3ならば、 {1,2,3},{1,3,2},{2,1,3},{2,3,1},{3,1,2},{3,2,1}の順でkeyとして格納される
   - value:keyで作成された順列の辞書順の番号。0はじまり
      - keyが{1,2,3}なら0。keyが{3,2,1}なら5
   -  辞書順の順列生成は[next_permutation](https://cpprefjp.github.io/reference/algorithm/next_permutation.html)という関数を使う
2. `mp`に順番を求めたい2つの順列を与えて、差分の絶対値をとる

# 解説のコードにコメント追記
[こちらの解説コード](https://atcoder.jp/contests/abc150/submissions/9407674)にコメントを追記

```c++

#include <bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < (n); ++i)
using namespace std;
typedef long long ll;
 
int main() {
  int n;
  cin >> n;
  vector<int> p(n), q(n);
  rep(i,n) cin >> p[i];
  rep(i,n) cin >> q[i];
  vector<int> a(n);
  rep(i,n) a[i] = i+1;
 
  map<vector<int>, int> mp;
  do {
    mp[a] = mp.size();
    //辞書順に順列を生成してmpに格納するので、mapのキーペアの数(サイズ)をとれば
    //それが順番になる。それを生成した順列に対応するkeyとして格納
  } while (next_permutation(a.begin(), a.end()));
 
  int ans = abs(mp[p] - mp[q]);
  //cf) mp[p]つまりmp[{1,3,2]のkeyは1。mp[q]つまりmp[(3,1,2}]のkeyは4
  // ansで差分の絶対をとるので、上記例だと3
 
  cout << ans << endl;
  return 0;
}
```
AWS EC2でyumが使えない

こんにちは[@yukifreeworld12](https://twitter.com/yukifreeworld12)です。
EC2でyumコマンドを使ったところエラーが出て数日ハマったのでメモとして、そして後世の同じエラーにハマった人の為にも...
#1. エラー文
EC2のインスタンス内でyumを使おうとすると以下のエラー文が表示される

```
One of the configured repositories failed (不明),
 and yum doesn't have enough cached data to continue. At this point the only
 safe thing yum can do is fail. There are a few ways to work "fix" this:

     1. Contact the upstream for the repository and get them to fix the problem.

     2. Reconfigure the baseurl/etc. for the repository, to point to a working
        upstream. This is most often useful if you are using a newer
        distribution release than is supported by the repository (and the
        packages for the previous distribution release still work).

     3. Run the command with the repository temporarily disabled
            yum --disablerepo=<repoid> ...

     4. Disable the repository permanently, so yum won't use it by default. Yum
        will then just ignore the repository until you permanently enable it
        again or use --enablerepo for temporary usage:

            yum-config-manager --disable <repoid>
        or
            subscription-manager repos --disable=<repoid>

     5. Configure the failing repository to be skipped, if it is unavailable.
        Note that yum will try to contact the repo. when it runs most commands,
        so will have to try and fail each time (and thus. yum will be be much
        slower). If it is a very temporary problem though, this is often a nice
        compromise:

            yum-config-manager --save --setopt=<repoid>.skip_if_unavailable=true

Cannot retrieve metalink for repository: epel/x86_64. Please verify its path and try again
```

#2. 解決策
セキュリティグループのアウトバウンドのルールに以下の開放が必要なポートを追加する。

**80/tcp**
**443/tcp**
**53/udp**


##参考
[yum が使えなくなりました。どのようにすればいいですか？](https://pfs.nifcloud.com/cs/catalog/cloud_faq/catalog_160822002738_1.htm)


##最後に
今日も見てくれてホンマありがとな!!
記事がええなと思ったらフォローといいねホンマよろしくな!!
(ジョーブログ風に)
Swift5でファイルの更新日時を取得する方法

ファイルの情報を取得するには`FileManager`を使います。
まずは取得するためのコードから。

```swift:main.swift
import Foundation
let manager = FileManager()
var attributes = try manager.attributesOfItem(atPath: "パス")
print(attributes[.modificationDate]!)
```
`パス`に任意のファイルのパスを入力することでそのパスの指すファイルの更新日時を取得することができます。
続いてこのコードの説明です。

```swift
let manager = FileManager()
```
まず`FileManager`のインスタンスを作り、

```swift
var attributes = try manager.attributesOfItem(atPath: "パス")
```
`attributes`という変数にそのファイルの属性(attributes)を入れます。これは辞書型になっています。
この辞書のキーは[https://developer.apple.com/documentation/foundation/fileattributekey](https://developer.apple.com/documentation/foundation/fileattributekey)のAccessing File Attributesのところに書いてあります。
今回は更新日時なので`.modificationDate`を使っています。

# 最後に
最後まで読んでくださり、ありがとうございます。
もしこの記事の中に改善すべきところ、間違っているところがありましたら、コメントなどで教えてください。

# 参考
[https://nshipster.com/filemanager/](https://nshipster.com/filemanager/)
[https://developer.apple.com/documentation/foundation/fileattributekey](https://developer.apple.com/documentation/foundation/fileattributekey)
[https://developer.apple.com/documentation/foundation/filemanager](https://developer.apple.com/documentation/foundation/filemanager)
改行コードエラーでherokuへのマイグレーションに失敗した件

#改行コードエラーでHerokuへのマイグレーションに失敗した件

Herokuにアプリをアップロードする際に以下のエラーが発生し、
マイグレーションに失敗したので、その時の対処法をまとめておきます。


```bash
/usr/bin/env: ‘ruby\r’: No such file or directory
```


## 目次
* [動作環境](#動作環境)
* [エラー内容](#エラー内容)
* [試したこと](#試したこと)
* [おわりに](#おわりに)

---------------------------------------
## 動作環境
ホストOS : windows 10
ゲストOS実行環境 : Vagrant 2.2.5 
ゲストOS : Ubuntu VERSION="16.04.6 LTS (Xenial Xerus)"
ruby : 2.6.3p62
rails : 5.2.4
エディタ: Atom

## エラー内容
Herokuでマイグレーションをする際に以下のエラーが発生し、マイグレーションに失敗。

```bash
vagrant@ubuntu-xenial:~/workspace/rails_exercise/social_app$ heroku run rails db:migrate
Running rails db:migrate on ⬢ mysterious-plains-71936... up, run.9817 (Free)
/usr/bin/env: ‘ruby\r’: No such file or directory
```

また上記が発生する前にもローカル環境でwebサーバを起動する際に以下のwarningが発生していた。ただし、ローカル環境では特に問題なくアプリが動いていたため、Herokuのデプロイまでは無視していた。

```bash
vagrant@ubuntu-xenial:~/workspace/rails_exercise/social_app$ rails s -b 0.0.0.0
/home/vagrant/.rbenv/versions/2.6.3/bin/ruby: warning: shebang line ending with \r may cause problems
=> Booting Puma
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
```

## 試したこと
ネットで調べるとどうやら改行コードに原因がありそうだということがわかったため、
Atomを開き改行コードを変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526570/48713ab2-3385-018a-b10c-34963bb79dd3.png)

その後、git commitをし、Heroku runをすると無事に成功

```bash
vagrant@ubuntu-xenial:~/workspace/rails_exercise/social_app$ heroku run rails db:migrate
```

## おわりに

今後、このようなことが内容にAtomのデフォルトの改行コードをUnixのLF形式に変更しておきました。

変更方法：
Settings -> Packages -> Line Ending Selector -> change the “Default line ending” setting to “LF” instead of “OS Default”.


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526570/da017c4a-a47d-4459-c4b4-b7504e08b8c3.png)
mysql-connector-pythonでMySQLに接続試行すると「SSL connection error: SSL_CTX_set_tmp_dh failed」エラーで接続できない

# はじめに
Pythonの「mysql-connector-python」ライブラリを使って、Dockerイメージから起動したMySQLサーバに接続を試みたところ、「**SSL connection error: SSL_CTX_set_tmp_dh failed**」エラーが発生し、MySQLに接続できない問題が発生しました。

```python:test.py
import mysql.connector

conn = mysql.connector.connect(
    host='127.0.0.1',
    port='3306',
    user='user',
    password='password', 
    database='sample_db'
)
cursor = conn.cursor()
```
↓ 実行後

```python:エラーメッセージ
Traceback (most recent call last):
  File "/Users/user1/opt/anaconda3/lib/python3.7/site-packages/mysql/connector/connection_cext.py", line 200, in _open_connection
    self._cmysql.connect(**cnx_kwargs)
_mysql_connector.MySQLInterfaceError: SSL connection error: SSL_CTX_set_tmp_dh failed

# // 省略
```

こちら一旦、接続できる状態になったので備忘録として残します。

# 実行環境
**■クライアント**
- macOS Catalina 10.15.2
- Anaconda3に含まれる以下パッケージを利用

```console
$ conda list --show-channel-urls
mysql-connector-c         6.1.11               hccea1a4_0
mysql-connector-python    8.0.18           py37h3febbb0_1
openssl                   1.1.1d               h1de35cc_3
python                    3.7.4                h359304d_1
```

**■MySQLサーバ**
- MySQL 5.7（デフォルト設定）

# 対策
DBコネクションを作成するときの引数に ```use_pure=True``` を指定し、利用するモジュールをデフォルトのC拡張版ではなくPython純正版に変更したところ接続できるようになりました。

[7.1 Connector/Python Connection Arguments](https://dev.mysql.com/doc/connector-python/en/connector-python-connectargs.html)

```python:test.py
import mysql.connector

conn = mysql.connector.connect(
    host='127.0.0.1',
    port='3306',
    user='user',
    password='password',
    database='sample_db',
    use_pure=True  # ←追加
)
cursor = conn.cursor()
```


ざっと調べた限り、本エラーは mysql-connector-pythonとopensslの互換性の問題？に起因して発生しているようです。
私の環境では試してはいないですが、以下issueによるとopensslのバージョンを1.0.2にダウングレードすると接続できるようになったとのコメントがあります。

・ [MySQLdb and mysql.connector are incompatible with openssl 1.1.1a #10646](https://github.com/ContinuumIO/anaconda-issues/issues/10646)


なお、Python純正と比較してC実装版を使うほうがパフォーマンスが向上するらしいので、大量データを扱う場合は注意が必要そうです・・・。

・ [Chapter 8 The Connector/Python C Extension](https://dev.mysql.com/doc/connector-python/en/connector-python-cext.html)
・ [SSL Error when connecting on Linux/Mac using Openssl 1.1.1 #22n](https://github.com/conda-forge/mysql-connector-python-feedstock/issues/22)
AWS SOAを取得するまで

[AWS SAAを取得したので](https://qiita.com/sicksixrock66/items/fa7be87c0dc9a6ce1e63)、
より知識の定着を図るために
AWS 認定 SysOps アドミニストレーター – アソシエイトを続けて受験し合格しました。

#勉強期間
AWS SAA合格が１２月２２日で翌年の１月１１日に受験したので３週間ぐらい

#勉強した内容
対策の書籍はない（少なくともSOAに特化している日本語の書籍はない）
ので公式の試験概要を参照してそれに付随するサービスのBlackBeltやよくある質問を読みました。

https://aws.amazon.com/jp/certification/certified-sysops-admin-associate/

>推奨される知識と経験
AWS の信条 (クラウドのアーキテクチャの設計) に関する理解
AWS CLI および SDK/API ツールの実践経験
AWS に関連するネットワーク技術の理解
セキュリティ概念の理解と、セキュリティコントロールとコンプライアンス要件の実装の実践経験
仮想化テクノロジーの理解
システムのモニタリングおよび監査経験
ネットワークの概念に関する知識 (DNS、TCP/IP、ファイアウォールなど)
アーキテクチャの要件を解釈する能力
>

例えば、Cloudformation,Cloudtrail,AWS Configなどの運用系・監査系サービス

#試験を振り返って
正直SAAより難しいです。。。AWS SAAの参考書は全くあてになりません。
運用者向けの試験なので、当然といえば当然ですがAWSを実際に触っていないと合格は難しいと思いました。
SAAで問われていた適切なアーキテクチャを選ぶのではなくトラブルシューティング的な聞き方が大半を占めていました。（トラブルを解決するためのオペレーション方法など）

特に、
>
AWS CLI および SDK/API ツールの実践経験
セキュリティ概念の理解と、セキュリティコントロールとコンプライアンス要件の実装の実践経験
>

に該当するサービスに関しては実務経験がないと厳しいかもしれません。
（SAAと違って文章だけでなく実際のコードを問われる部分もありました。）

#まとめ
テストの点数は744点でかなりギリギリで合格でした。。。
AWS SAAと違って机上の勉強だけでは難しい試験だと思いますのでCloudformationで実際にリソースを作成するなど手を動かすのが大事だと思いました。

次はAWS DVAの取得をめざします。
[更新][漏洞通告]CVE-2019-19781/Citrix ADC&NetScaler存在目录遍历&远程代码执行

### 漏洞描述
在`Citrix ADC&NetScaler`的10.5、11.1、12.0、12.1、13.0等版本中，被发现存在目录遍历.该漏洞可允许未授权访问服务器上的一些文件.随着各大安全研究员进一步深入研究，发现`/vpn/portal/scripts/`存在一些perl脚本.尤其是`newbm.pl`脚本，该脚本运行写入一些文件到服务器中.那么结合这些脚本，原本是目录遍历的漏洞升级成为远程代码执行的漏洞.目前该漏洞远程代码执行方式的EXP已经公布于互联网，请资产管理员尽快采取缓解措施.
### CVE编号
CVE-2019-19781
### 漏洞威胁等级
高危
### 影响范围
10.5
11.1
12.0
12.1
13.0
### 漏洞验证
使用公开的RCE payload进行验证
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/c6a1032c-f42b-7e64-217e-f966b65b65e2.png)
### 缓解措施
参考官网：https://support.citrix.com/article/CTX267679
### 时间轴
[0] 2019/12/27 NVD发布该漏洞
[1] 2020/01/09 亚信安全网络攻防实验室根据公开的路径遍历POC复现该漏洞并发布漏洞通告
[2] 2020/01/11 亚信安全网络攻防实验室根据公开的RCE POC复现该漏洞并发布漏洞通告
### Reference
https://nvd.nist.gov/vuln/detail/CVE-2019-19781
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-19781
https://github.com/projectzeroindia/CVE-2019-19781
https://www.mdsec.co.uk/2020/01/deep-dive-to-citrix-adc-remote-code-execution-cve-2019-19781/
シーザー暗号を使って、splitメソッド、ordメソッド、chrメソッド、joinメソッドの勉強

# この記事で得られる知識
Rubyで、入力された文字列をシーザー暗号で暗号化し、暗号化された文字列を復号するプログラムを作ってみました。

①　シーザー暗号とは
②　splitメソッドの使い方。
③　ordメソッド、chrメソッドの使い方。
④　joinメソッドの使い方。

# シーザー暗号とは
決まった文字数分のアルファベットをシフトさせて作られる暗号。
例えば"study"という文字列を、シーザー暗号で前方に３つシフトさせて
暗号化すると"pqrav"という暗号文ができる。
[シーザー番号 wikipedia](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%BC%E3%82%B6%E3%83%BC%E6%9A%97%E5%8F%B7)

# splitメソッド、ordメソッド、chrメソッド、joinメソッドを使って書いてみる

実装の流れは
１、入力された文字列を各文字に分割して配列に入れる。(splitメソッド)
２、配列に入れた各文字を暗号化する。(ordメドッド、chrメソッド)
３、暗号化され配列に入っている各文字を再び文字列に変換する。(joinメソッド)
となります。
ポイントは各文字には、文字コードという数字が与えられていることです。

```ruby:qiita.rb
# 暗号化するためのメソッド
def encode(input)
  # ①入力された値を一文字ずつに分解して配列に入れるためにsplit("")を使用します。
  #   もし文字列"study"が入力されていれば配列chars_arrの中身は[s,t,u,d,y]になっています。
  chars_arr = input.split("")
  # ②new_charsで、each文で処理された値を受け取るための空の配列[]を準備します。
  new_chars = []

  chars_arr.each do |char|
    # ③ordメソッドを使い、各文字を文字コードに変換し、-3をすることで3つ手前の文字コードに変更します。
    # ④chrメソッドを使い、３つ手前の文字コードに変更された値を、再び文字に戻します。③④で暗号化しています。
    new_char = (char.ord - 3).chr
    # ⑤暗号化された文字列を②で準備した空の配列に入れます。
    new_chars << new_char
  end
  
  # ⑥暗号化され配列に入った各文字をjoinメソッドを使い、一つの文字列にしています。joinメソッドを使う前の
  # 配列new_charsの中身は[p,q,r,a,v]となっています
  puts new_chars.join
end

# 復号するためのメソッド  暗号化するためのメソッドと比べて
# new_char = (char.ord - 3).chr が  new_char = (char.ord + 3).chrとなっているだけでそのほかは同じです。
def decode(input)
  chars_arr = input.split("")
  new_chars = []
  chars_arr.each do |char|
    new_char = (char.ord + 3).chr
    new_chars << new_char
  end

  puts new_chars.join

end

while true do
  puts "番号を入力してください"
  puts "0: 文字列をシーザー番号(-3)で暗号化する"
  puts "   ※使用できる文字列はa~zの小文字"
  puts "1: シーザー暗号(-3)で暗号化された英字文字列を復号する"
  puts "   ※使用できる文字列はa~zの小文字"
  puts "2: 終了する"
  case gets.to_i
  when 0
    puts "シーザー暗号(+3)で暗号化したい文字列を入力してください"
    input = gets.chomp
    encode(input)
  when 1
    puts "復号したい文字列を入力してください"
    input = gets.chomp
    decode(input)
  when 2
    exit
  else
    puts '無効な値です'
  end  

end

```
ターミナルでの出力

```terminal

番号を入力してください
0: 文字列をシーザー番号(-3)で暗号化する
   ※使用できる文字列はa~zの小文字
1: シーザー暗号(-3)で暗号化された英字文字列を復号する
   ※使用できる文字列はa~zの小文字
2: 終了する
0
シーザー暗号(-3)で暗号化したい文字列を入力してください
study
pqrav
番号を入力してください
0: 文字列をシーザー番号(-3)で暗号化する
   ※使用できる文字列はa~zの小文字
1: シーザー暗号(-3)で暗号化された英字文字列を復号する
   ※使用できる文字列はa~zの小文字
2: 終了する
1
復号したい文字列を入力してください
pqrav
study
```
無事、暗号化と復号ができるプログラムが出来上がりました。
読んでいただいてありがとうございました。
【n百番煎じ】LINE Notify APIをPythonで叩く

LINEは全員が使うチャットツールですから、これで通知を送れると非常に便利です。
LINE Notifyは無料で使える通知を送るAPIです。
この記事ではアクセストークン発行からPythonでAPIを叩くところまでやってみます。


#アクセストークンの発行

https://notify-bot.line.me/ja/

上のページにアクセスします。



<img width="250" alt="スクリーンショット 2020-01-11 14.52.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158553/acf7d03e-9cfc-e916-49dc-171ad2a44e34.png">

ログインからログインし、マイページをクリックします。


<img width="250" alt="スクリーンショット 2020-01-11 15.24.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158553/88d1aba9-4fba-993c-95d7-33658b0e0916.png">


LINE NotifyではLINE NotifyというアカウントからLINEメッセージが送られてきますが、そのトークルームを選ぶことができます。
自分に1対1で送ることもできます。

<img width="250" alt="スクリーンショット 2020-01-11 15.02.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158553/0451fafd-f598-c705-0b0d-6974c5097d2c.png">


発行したトークンはこれ以降メモできないので、ちゃん手元に保存しておきます。


<img width="250" alt="スクリーンショット 2020-01-11 15.02.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158553/35c2da56-7bc6-fefe-5f85-14b868749480.png">


#LINE Notify APIを叩いてみる

requestsモジュールを使っています。


```LINE_Noti.py
import requests

access_token = 'ここにアクセストークンを入れます'
message = 'おしらせです'
API_URL = 'https://notify-api.line.me/api/notify'
payload = {'message': message,}

requests.post(API_URL, headers={'Authorization': 'Bearer ' + access_token}, data=payload)
```
UnuboでNuxt.jsを動かす！

# Unuboとは？
皆さんは[Unubo](https://unubo.com/)というサービスを知っていますか？
Go, Node.js, Pythonなどのアプリケーションを無料でデプロイできるサービスです。
DBも、MariaDB, PostgreSQL, Redisの3種類が無料で使えます。


Nuxt.jsを動かす方法は[公式ドキュメント](https://docs.unubo.com/getting-started/deploy-app/)や[github](https://github.com/unubo)を見てもなかったため、実際に動かすまでをまとめたいと思います。

GithubにNuxt.jsのプロジェクトをpushしている事が前提です。

## 実践
1. Unuboにログインし、Node.jsのプロジェクトを作成します。
![Screen Shot 2020-01-11 at 15.23.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36872/afdb15ba-d649-23ec-8580-acc4c5a37a77.png)

2. RepositoryからデプロイしたいNuxt.jsのプロジェクトを選択します。

3. Commandsに下記の3つを登録します。

```
yarn
yarn build
yarn start
```

4. SecretsにHOST=0.0.0.0を登録します。
![Screen Shot 2020-01-11 at 15.29.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36872/f860cf6c-2f4d-4f35-4fa0-cdbb59d0377a.png)

最後にDeployを押して数分待てば無事公開されます！

ログが見辛すぎて1週間以上かかってしまった。。


追記:
~~ts-nodeは動かないっぽいです。
下記のエラーが延々と出続ける。。~~

```
error Command failed with signal "SIGKILL".
```

~~`yarn start`や`npm run start`を使わずに、直接`ts-node`を使うことでいけました！~~

```sh
node_modules/.bin/ts-node server/index.ts
# or
node -r ts-node/register server/index.ts
```

Express + TypeScriptのシンプルな構成だとこのやり方で行けたんですが、Nuxt.jsを使ってると動かないようです。
[Runtime（オプション）](https://typescript.nuxtjs.org/ja/guide/runtime.html)辺りを弄る必要があるのかも。。
当面はbabelでトランスパイルすることで回避したいと思います。
Windows IISのログを自動的に削除する

WindowsのIISで、ログを削除する機能が標準ではありません。放置すると溜まり続け、Cドライブがいっぱいになり爆発します（ウソです）昔はタスクスケジュールでスクリプトを実行していたのですが、１行でできることが分かったので記事にします。

# コマンド

```bash
forfiles /p "C:\inetpub\logs\LogFiles" /s /m *.* /c "cmd /c Del @path" /d -100
```
- IISのログの場所は C:\inetpub\logs\LogFiles です。
- 上の例では100日以上前のログを削除します。

# タスクスケジュール登録

![2020-0110-IIS-log.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253995/3d267c4c-26c4-1927-99d6-5ca2849a1134.png)

```VBScript:AddTask-Delete-IIS-Log.vbs
' タスクスケジューラでIISのログを自動削除
' 毎日午前2時、100日以上前

If WScript.Arguments.Count = 0 Then
	CreateObject("Shell.Application").ShellExecute "wscript.exe", """" & WScript.ScriptFullName & """ uac", "", "runas" 
	WScript.Quit  
End If

CreateObject("WScript.Shell").Exec("schtasks /create /tn ""Delete-IIS-Log"" /tr ""forfiles /p \""C:\inetpub\logs\LogFiles\"" /s /m *.* /c \""cmd /c Del @path\"" /d -100"" /sc DAILY /st 02:00 /ru System")
```

- 上記を VBScript にしてダブルクリックすると、Delete-IIS-Log という名前のタスクスケジュールが登録されます。毎日午前２時に実行します。
- 初めのコマンドは管理者権限で実行するためのものです。

# まとめ

AWS EC2でWindowsサーバーを運用しています。オンプレなら気にしなかったのですが、EC2だとCドライブが40GB程度なので、すぐにいっぱいになります。やはり実運用では予期せぬことが起こります。早くWindowsサーバーから脱出せねば。
database is lockedエラー[SQLite]の解決方法


### はじめに
今回は、SQLiteを使用している時にdatabase is lockedのエラーが出たので、解決方法を記述します。すみませんが細かい説明はしないのでご了承くださいませ...

### 解決方法

#### 1.DBのファイル名を仮のファイル名に変更
(例)
ここでは現在のデータベース名を、database.sqlite
仮のファイル名を、provisional_database.sqliteとします。


```
$ mv database.sqlite provisional_database.sqlite
```
次に
#### 2.DBのファイル名を元に戻す

```
$ cp -p provisional_database.sqlite database.sqlite
```
上記のコマンド後に仮のファイルが残っているので削除をお願いします。

これだけでロックされていたDBを解除して無事に接続することができました。

### 原因
#### プログラムを重複で実行してしまっていたからだそうです。笑

---

#### [参考サイト]

[・database is lockedに悩んだら、コレで解決！原因は予想外のコイツ！でした
](http://fanblogs.jp/scripts/archive/61/0)[・SQLiteを使ってみる](https://www.antun.net/tips/api/sqlite.html)
gasのgetRange()について質問です

ある条件でフィルタされたgoogle spreadシートのデータ範囲のみ

（=可視データ範囲のみ）範囲指定するscriptの書き方を教えていただけますか？:

試しにspreadシートのマクロ機能を使ってみましたが

```
getRange('workSheet!A1:E850')
```

などと固定範囲になってしまいます。

エクセルのマクロでは

```
Resize(.Rows.Count - 1, 16).Offset(1).Copy
```

で解決できるのですが、GASのやり方が調べても分かりません。
大変恐縮ですが、ご回答いただけると幸いです。
【Rails チュートリアル】第６章のbcryptがインストールできずにテストで落ちてしまう。。

Railsのチュートリアルの6章を勉強していた時に、bcryptがインストールできなく手間取ってしまったので解決方法を載せておきます。





これ↓
![スクリーンショット 2020-01-11 15.04.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530825/cd838cee-0737-077d-d0c7-a187a4200276.png)


<h1>解決方法</h1>

１. gem uninstall bcrypt を実行
２. gem uninstall bcrypt-ruby を実行
３. gem install bcrypt --platform=rubyを実行
４. Gemfileにgem 'bcrypt', '~> 3.1.11'を記載
５. bundle installを実行
<br><br><br><br>

少しでも役に立てれば幸いです。
Google DriveでMarkdownファイルを閲覧・編集したい

GitHub や GitLab に慣れたためか、クラウドに保存した Markdown ファイルはブラウザで閲覧できるものと思い込んでいました。

# 問題

ある日確かめもせずに Google Drive に Markdown ファイルを保存して知人と共有したところ、ソースのテキストがそのまま表示されてしまうという問題が発生しました。

Google Drive は標準で Markdown の閲覧ができないようです。

# 解決

以下、PC上 の Google Chrome での操作になります。

## 手順

1\. Google Drive 上で右クリック → 「アプリで開く」 → 「アプリを追加」

![add_app.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169872/cfab3d5a-10e7-fb44-1740-83dc0049558f.png)

2\. "stack" で検索して、StackEdit が表示されたら「＋接続」ボタンをクリック

![add_app_search_stack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169872/041a9d08-a7d7-a8d8-8910-ef24625a73bd.png)

3\. 接続完了。チェックボックスが ON のまま「OK」をクリックすれば、以後デフォルトのアプリとして StackEdit が開かれるので便利。

![add_app_connected_stackedit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169872/197f1eba-d98e-9757-0f83-cf70d859a80b.png)

4\. StackEdit のサイトを開く
https://stackedit.io/

5\. 画面上部の「[START WRITING](https://stackedit.io/app#)」をクリック

![start_writhing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169872/70d42732-8dbf-5b33-1319-0bc2a9d4d569.png)

6\. 編集画面で右上の StackEdit アイコン（Toggle side bar）をクリック

![start_writhing2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169872/62a76c5a-935b-e735-d9df-874864f3b32a.png)

7\. サイドバーが開くので、「Sign in with Google」をクリック

![signin_with_google.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169872/6b81e571-0abe-bf6a-f903-0571194f31a8.png)

8\. 自分の Google アカウントに接続する。

![signed_in_with_google.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169872/a80b4b35-94a9-89e4-cf95-5c3473a09130.png)

9\. 再び Google Drive 上で Markdown ファイルをダブルクリックし、以下のリンク確認で「OK」をクリックする。

![open_with_authentication.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169872/00ab3636-d82f-7208-00b6-715d245cfd72.png)

10\. 無事に Markdown ファイルが StackEdit で開いたら完了です。お疲れさまでした。

以上の操作を各 PC で行う必要があるので、よろしければ Google Drive を共有しているメンバーにこの記事を見せてください。

## 上記の操作をしなかった場合

StackEdit から Google Drive への OAuth 認証ができないため、以下のようにエラー 400 が表示されます。

![error_400.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169872/05444d29-68da-94e2-a021-dfc8cf439a2d.png)

## サードパーティ Cookie の許可

現在の Google Chrome は「サードパーティの Cookie をブロックする」設定がデフォルトなので、StackEdit のサイト全体または一部を許可する設定が必要になりました。

![stackedit-cookie.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169872/32a56ce3-e5c7-d1c4-59f5-67fcfc229453.png)

「設定」-> 「プライバシーとセキュリティ」->「Cookie と他のサイトデータ」->「常に Cookie を使用できるサイト」->「追加」

## 参考

以上は Google Drive で Markdown ファイルを開いて閲覧・編集するための最低限の操作です。

StackEdit 自体の各種操作方法も含めて、以下のサイトを参考にさせていただきました。

* [ブログ執筆はクラウドエディタ「StackEdit」がおすすめ　Part.1](https://www.minihack-lab.com/posts/20180410211752/)
* [ブログ執筆はクラウドエディタ「StackEdit」がおすすめ　Part.2](https://www.minihack-lab.com/posts/20180416205009/)
swiftUI画面遷移時、どうやって遷移先の画面を全画面表示(Ipad上の問題)

swiftUIを使って、Ipadアプリの画面遷移する時、遷移
先の画面が全画面に表示できない。
下記は私のソース：

import SwiftUI
struct ContentView: View {
    @State var showsecondView: Bool = false
    var body: some View {
   
        Button(action: {
            self.showsecondView.toggle()
        }) {
            Text("firstView")
        }.sheet(isPresented: self.$showsecondView){
            secondView(showsecondView: self.$showsecondView)
        }
    
    }
}
 
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
struct secondView: View {
    @Binding var showsecondView: Bool
    var body: some View {
   
       Text("secondView")
    }
}
<img width="762" alt="スクリーンショット 2020-01-11 13.18.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565325/4e0d2756-5f0d-3c27-06b8-dd00b4b3a982.png">
[JavaScript] filter() メソッドは超便利。


# filter() メソッドとは


```filter()メソッド``` は、引数として与えられたテスト関数を各配列要素に対して実行し、それに合格したすべての配列要素からなる```新しい配列```を生成する。

つまり、、**イミュータブルに配列を操作する**ことができる。

# 例

```javascript:例1
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6); // 6文字より大きい要素だけを取り出し、新しい配列に格納する。
console.log(result); => ["exuberant", "destruction", "present"]
```
```javascript:例2
const arr = [
  { id: 0, name: "fdoif", hobby: "soccer" },
  { id: 1, name: "hohfd", hobby: "baseball" },
  { id: 2, name: "fhofi", hobby: "bascketball" },
  { id: 3, name: "fefef", hobby: "soccer" },
  { id: 4, name: "sassa", hobby: "baseball" }
];

const filterByHobby = item => {
  if (item.hobby === "soccer") {
    return true;
  }

  return false;
};

const arrByHobby = arr.filter(filterByHobby); //hobbyがsoccerの要素だけを取り出し、新しい配列に格納する。

console.log("Filtered Array\n", arrByHobby);
```


**超便利!!!**

以上です。

参考: [Array.prototype.filter() | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
Gerrit 古いGerrit 2.6をwgetで導入しようとした時に困った話

# 目的

- Ubuntu 16.04マシンに古いGerrit(ver. 2.6)をオフィシャルリリースノートのリンクを使用してコマンド`wget`を用いてダウンロードしようとしたときにページがなくなっており困った話をまとめる
- 先輩がリンク先を発見してくれたので方法として世の中に出した方が良いと判断したため書く

# 結論

- 先輩がリンク先を見つけてきてくれました。(本当にありがとうございます。)
- 下記にリンクを記載する。
    - [Gerrit Code Review - Releases](https://gerrit-releases.storage.googleapis.com/index.html)

# 取得方法の詳細

1. 下記リンクにアクセスする。
    - [Gerrit Code Review - Releases](https://gerrit-releases.storage.googleapis.com/index.html)
1. ダウンロードしたGerritバージョンの文字の上て右クリック→リンクをコピーする。
1. Linuxマシンで下記コマンドを実行する。

    ```terminal
    $ wget コピーしたリンク先のURL
    ```
After EffectsでECMAScript 2018を使用する

After Effects 16.0以降expressionのエンジンがExtendScriptからJavaScript(ECMAScript 2018)に変わりましたが、
実際使用してみるとExtendScriptと同じでした。
解決法は、
menu > File > Project Settings > Expressions Tab
の"Expression Engine"を変更すればJavaScriptが使えます。
公式にも書いてあったのですが見落として結構悩んでしまいました。

メモ
ExtendScriptの場合のエラー
let
Error: expected: ;

const
Error: foo redeclared
Nuxt.jsのPWAでアプリのURLにサブディレクトリを含んでいる場合の注意点

Nuxt.jsでPWAとして開発したアプリを pages/app/index.vue に配置し、それをビルドして https://example.com/app/ というURLで公開したとします。
（実例→ https://dispbarcode.com/app/ ）

そのとき、ブラウザからは正常に表示されますが、「ホーム画面に追加」をしてPWAとして立ち上げようとすると、設定によってはエラーになります。

# 理由
manifest.json の start_url がルート`/`を指しているままだから。

# 対処
manifest.json を手書きしている場合は、直接 "start_url": "/app/" と書けばOK。

しかし、Nuxt.jsを使っているなら nuxt.config.js での設定が必要。
manifest: ブロックの中に `start_url: '/app/'` と `scope: '/app/'`を追加しましょう。

私の場合、そもそもmanifest: ブロックが存在しなかったので、丸ごと書き加えました。

以下、弊サイト（dispbarcode）での実例です。

```
  manifest: {
    name: 'dispbarcode',
    lang: 'en',
    short_name: 'dispbarcode',
    title: 'dispbarcode',
    'og:title': 'dispbarcode',
    'og:description': 'This app displays a barcode on smartphones. スマホ画面にバーコードを表示できるアプリです。',
    description: 'It is an application that displays a barcode. スマホ画面にバーコードを表示できるアプリです。',
    theme_color: '#ffffff',
    start_url: '/app/',
    background_color: '#ffffff',
    scope: '/app/'
  },
```

短いですが、以上です。
Nuxt.js

```vuejs:sample.vue
<template>
  <div>
    <button @click="getData()">取得</button>
      <table border=1>
        <tr v-for="item in items" :key="item.id">
          <td>{{item.id}}</td><td>{{item.title}}</td>
        </tr>
      </table>
  </div>
</template>

<script>

import axios from 'axios'

export default {
  data: () => {
    return {
      items: []
    };
  },
  methods: {
    getData() {
      const url = 'https://jsonplaceholder.typicode.com/todos';
      axios.get(url).then((res) => {
        console.log(res);
        this.items = res.data;
      })
    }
  }
}
</script>
```
0で割ったエラー ZeroDivisionError の処理

```py
print('start')

try:
    number1 = 200
    number2 = 0
    answer = number1 / number2
    print(answer)
except ZeroDivisionError as e:
    print(e)

finally:
    print('end')
```

```:実行結果
start
division by zero
end
```

tryブロック内で例外が発生すると、
変数eに例外をあらわすオブジェクトが代入される。

tryブロック内で例外が発生した場合、
そこで処理を中断し、
exceptブロックのコードを実行する。

例外処理の後に、
必ず実行したいコードは、
finallyブロックに記述する。
Linuxでbluez-alsaを使いLDACやらAACやらaptXをBluetoothで送信する話

##LDACに関してはUbuntu系にppaがあるが…

pulseaudioで上手く行かなかった。

##ということでpulseaudioを使いたくない

いろいろな様々があり、上手く動かなかったので別解としてALSAのバックエンドで動くbluez-alsaを使ってみようかとなりました。aptXについてはリバースエンジニアリングしたものなのでインストール方法について詳しくは書きません。Bluezも最新の5.52にしました。

##作っていきます

まずはlibLDACを。まあbluez-alsaを最後にすれば順番はどうでもいいです。

[https://github.com/EHfive/ldacBT](https://github.com/EHfive/ldacBT)

まあ、READMEに書いてある通りにやれば出来上がります。足りないライブラリは適宜追加していく感じで。自分でもちゃんとログを取っていないので申し訳ないです。

[https://github.com/mstorsjo/fdk-aac](https://github.com/mstorsjo/fdk-aac)

このライブラリを作るとMac系で標準のAACで送信もできるようになります。まあパッケージはあるんですが、これも適宜ライブラリを追加しつつインストールします。

[https://github.com/Arkq/openaptx](https://github.com/Arkq/openaptx)

まあLDACやAACのBT受信機があればなくてもいいのかな、と。どうしてもやりたい人は試行錯誤してみてください。

[http://www.kernel.org/pub/linux/bluetooth/bluez-5.52.tar.xz](http://www.kernel.org/pub/linux/bluetooth/bluez-5.52.tar.xz)

Bluezに関してはこっからソースコード落としてビルドしてください。

[https://github.com/Arkq/bluez-alsa](https://github.com/Arkq/bluez-alsa)

で、bluez-alsaをビルドします。

##全然詳しく書きませんでしたが

openaptx以外はインストール方法がそれぞれで載っているのでこういうのもあるのよという紹介でした。aptXについてはAOSP由来のものも恐らくどっかにあると思うのでそこから作るのもいいのかも知れません。

Raspberry Pi 3B+でも動きますが、LDAC送信時にtopコマンドで見る限りではbluezalsaが30％ほどCPUを食っており、熱暴走なのか途中でBTの送信が途切れます。というかbluez-alsaが落ちます。4Bにすればマシになるのかなぁ。

AMD64(8年くらい前のCeleron)のサーバーマシンにBTドングルをつけた今の環境では安定して送信できています。

bluetoothctlを使い、scanしてtrustしてconnectすれば```~/.asoundrc```かなんかにBluetoothの受信側の機器が設定されていて、そこから音が出るようになっているはずです。

LDAC受信するヘッドホンを持っていますが、LDACで普通の音源を聞いている限りでは圧縮しているとは思えないほどの音質です。

またAOSPにソースが寄贈されている関係でAndroid8からは標準でLDAC、aptX、aptX HDが送信できるようになっています。それぞれのメーカーの判断に寄りますが…。ちなみにAQUOS R3では開発者オプションからLDACは選べるもののいざつなぐとaptX HDになってしまいました。変な意地張らずにLDAC送信できるようにして欲しかった。シャープめぇ…。

現場からは以上です。
フォームの画像枚数についてのバリデーション

# 環境
Nuxt.js, Vuetify

# やりたいこと
`<v-form>`を使ってフォームを作り、その中で少なくとも一枚以上の写真を要求したい。そして取得した写真を表示したい。

### 写真がない時
<img width="899" alt="スクリーンショット 2020-01-11 10.45.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417223/bfb6dd31-fd89-6907-efde-b01022f8ffae.png">


### 写真がある時
<img width="387" alt="スクリーンショット 2020-01-11 10.41.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417223/aa9b46f2-deea-0d61-0981-5ee377655bc5.png">


# 実装
```item_register.vue
<template>
  <v-card>
  <v-card-text
    v-if="!validInput"
    style="color: red"
  >
    最低一枚以上の写真が必要です
  </v-card-text>
  <v-file-input
    required
    class="pa-4"
    multiple
    label="写真を追加して下さい（複数可）"
    filled
    accept="image/*"
    prepend-icon="mdi-camera"
    @change="onChangeImage"
  />
</v-card>
</template>

<script>
export default {  
  data() {
    return {
      imageUrls: []
    }
  },
  computed(){
    // imageUrlsに写真があるときはtrue、ない時はfalse
    validInput(){
      return this.imageUrls.length > 0 ? true : false;
    },
  },
  methods(){
    // ファイルをbase64を用いて変換
    getBase64(file){
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => {
          resolve(reader.result);
        };
        reader.onerror = error => reject(error);
      });
    },
    // ファイルが入力されたときに使うメソッド
    onChangeImage(File) {
      // 配列を一回初期化してから追加する必要がある。そうしないとどんどん写真が追加されていってしまう。
      this.imageUrls = [];
      File.forEach(file => {
        this.getBase64(file)
          .then(image => {
            this.imageUrls.push(image);
          })
          .catch(error => console.log(error));
      });
    },
  }
}
<script/>
```

# 実装にあたってのポイント
### バリデーション
今回使った`v-file-input`というコンポーネントは、`rules`プロパティを指定することでバリデーションを追加できる。しかし、このrulesでは画像サイズのバリデーション等は実装できるものの、ファイル数についてはうまく動くrulesを設定できなかった。そのため、computedにinputファイル数によってtrue/falseを返すvalidInputを実装し、それをv-ifを使って表示することでバリデーションを実装した。
AlamofireでAF.requestが出ない時に確認すること



今回は自分がAlamofireでAF.requestが出なくて苦しんでいたのですが
そのときに何を確認すればいいか書きました。
初心者なら起こしやすいミスなのではないかと思います。
なお、この記事ではcocoapodsのインストールなどについては触れません。

内容
・最新版のAlamofireが入っているか確認しよう
・podfileの対象iosなどが合っているか確認しよう 


<h1 id= "1">Alamofireの最新版の確認</h1>

まず、Alamofireについて調べます。
"外部ライブラリーでは、そのGithub上に使用方法などがのっているので確認してみてください"

<a href = "https://github.com/Alamofire/Alamofire"> Alamofireのリンクはこちらから </a>

したら下の方にスクロールすると、これが出てきます。
<img width="976" alt="スクリーンショット 2020-01-11 13.39.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558816/aeb476bd-7ed4-5f96-5703-7dfd1daed698.png">
この　pod 'Alamofire', '~> 5.0.0-rc.3'　が自身のpodsの中で最新であるか、確認してターミナルで追加して、pod update でアップデートしてみてください。

<h1 id = "2"> podfileの対象iosなどが合っているか確認しよう</h1>
最新の状態にしたのに直ってない場合は、対象のiosのversionが合っていない可能性があります!
その場合は、AlamofireのGithubページ内でこちらを確認してみましょう。

<img width="523" alt="スクリーンショット 2020-01-11 12.42.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558816/52dfe7ba-0454-f4bf-aadb-acb2f5358ffe.png">

こちらには、最低でもこのバージョンを準備しないと使えないよと言われています。

iosの確認の仕方は
自身のファイルの中にPodfileがあるのでこちらを開きます。
<img width="401" alt="スクリーンショット 2020-01-11 13.55.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558816/5240f989-17d8-ee68-a8ad-c7e07497e250.png">

そうしますと上の方にこのように書かれていると思います。

<img width="490" alt="スクリーンショット 2020-01-11 13.59.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558816/e8f55fcc-14f8-f8ba-3380-dca4cab0b6d3.png">

ここの、IOSのバージョンが先ほど確認した、最低でも用意しなくてはいけない。
ところよりも、古いバージョンですとAF.reuestは出ないかなと思います。
バージョンを変更した場合は、必ず自身のディレクトリーに行って pod update　をしてください。
pod内の確認の仕方は nano Podfileなどでも確認できますので
そちらの方は自身で検索してみてください。

あまり深く説明できませんでしたが、この記事が少しでも役立つことを願っています。
ボックスカルバートの形状予測AI～データ整理編～

## シリーズ目次

- ボックスカルバートの形状予測AI ～データ整理編～
- [ボックスカルバートの形状予測AI ～学習用設計データの作成編～](https://qiita.com/sasaco/items/92e1f8fc09c908b1ef8e)
- [ボックスカルバートの形状予測AI ～ニュートラルネットワークの構築編～](https://qiita.com/sasaco/private/b2aedcd5f91a07199ef1)
- [ボックスカルバートの形状予測AI ～いざ予測 編～](https://qiita.com/sasaco/private/9ea9b67683650deb619c)
- [Tensorflow.Keras で学習したモデルをtensorflow.jsで使う](https://qiita.com/sasaco/items/9c7a4e247710ed747dbd)

## 企画説明

土木構造物のボックスカルバートの寸法を決定するのは設計業務におけるメインの業務内容です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142847/4a7385f3-653d-75fe-53de-7722ce9a38da.png)


寸法を決定する作業は、設計時に毎回検討するのですが、**あらかじめ設計した大量の計算結果をAIに学習させることにより適正な寸法を予測できる**のではないか

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142847/deb23a87-d03b-94dc-d670-4fd1ccc07717.png)

# データ整理編

## 用意したデータ

ボックスカルバートの設計は、下図の通り

- ボックス直上の**埋め戻し土**
- ボックスより上の部分の**地層1**
- ボックスの上半分の**地層2**
- ボックスの下半分の**地層3**

に囲まれた**左右対称の形状**とし、下表のパラメータを学習に用いる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142847/8635e304-6cba-3ced-8a2e-8a14d22257a6.png)

### ニュートラルネットワーク(AI)に入力する情報

| 変数名           | 意味               |備考　　　          |
|:-----------------|:------------------:|:------------------|
| result_max　　　　　　    | 安全率の最大値        |              |
| Df | 地表面から内空までの深さ |   (mm)  |
| b0 |　内空幅 | (mm)           |
| h0| 内空高さ | (mm)         |
| fck | コンクリート強度| (N/mm2)  |
| condition | 環境条件            |一般の環境、腐食性環境、厳しい腐食性|
|coverSoilWeight| 埋め戻し土の湿潤重量   |              |
| ds| 鉄筋の純かぶり   |     (mm)   |
| r1| 1層目の湿潤重量| (kN/m3) |
| type2| 2層目の地盤区分      |砂質土 or 粘性土|
| r2| 2層目の湿潤重量|  (kN/m3)  |
| E02 | 2層目の地盤反力係数(kN/m2 )|          |
| Ko2 | 2層目の静止土圧係数    |              |
| type3 | 3層目の地盤区分      |砂質土 or 粘性土|
| r3 | 3層目の湿潤重量(kN/m3)|              |
| E03 | 3層目の地盤反力係数(kN/m2 )|          |
| Ko3 | 3層目の静止土圧係数    |              |

### ニュートラルネットワーク(AI)が予測する情報

ニュートラルネットワークは 上表の**17**個の入力値を受け取って 下表の**3**個の値を出力する「全結合層」を7つ重ねたシンプルなモデルを作成します。

| 変数名           | 意味               |備考　　　          |
|:-----------------|:------------------:|:------------------|
| tu1　　　　　　          | 上床版の厚み　　　　        |              |
| tb1　　　　　　          | 下床版の厚み　　　　        |              |
| tw1　　　　　　          | 側壁の厚み　  　　　        |              |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142847/ee58fcfa-479c-dbef-3056-c2f8ea6b3664.png)


## 実際に学習に用いる csv データ

下記の csvファイル を学習に用いました

**[boxculvert_data.csv](http://gofile.me/4fNCe/y3K32QQbY)**

上表の設計データが、15万件分 記録されています。


## 次回

次回、この設計データの作成について記事を書きます。

[ボックスカルバートの形状予測AI ～学習用設計データの作成編～](https://qiita.com/sasaco/items/92e1f8fc09c908b1ef8e)
Laravel6 CSV ダウンロードを streamDownload でやるサンプル

streamDownload を使って CSV をダウンロードするサンプルです。Controller の処理だけ書いておきます。
（簡単なサンプルなので、諸々抜けています。）

```php:controller
public function csvDownload()
{
    return response()->streamDownload(function () {
        $handle = fopen('php://output', 'w');
        $list = [[1,'hoge'], [2,'piyo'], [3, 'fuga']];
        foreach ($list as $row) {
            fputcsv($handle, $row);
        }
        fclose($handle);
    }, 'sample.csv');
}
```

公式ドキュメント => https://laravel.com/docs/6.x/responses#file-downloads

以下のような CSV がダウンロードされる。

<img width="522" alt="スクリーンショット 2020-01-11 13.06.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45822/a6bb091f-dced-31a7-de33-52915c80bff8.png">

おわり。

# 補足1

以下のようにもかけるけど、結局 fpassthru で output buffer に渡しているので、あまり変わらないような気がする。けど、まだよくわかっていない。`php://outpt` と `php://memory` `php://temp` の使い分けが全然わかっていない。勉強が必要！

```php:controller
return response()->streamDownload(function () {
    $handle = fopen('php://temp', 'w'); // temp に変更
    $list = [[1,'hoge'], [2,'piyo'], [3, 'fuga']];
    foreach ($list as $row) {
        fputcsv($handle, $row);
    }
    rewind($handle); // 追記
    fpassthru($handle); // 追記
    fclose($handle);
}, 'sample.csv');
```

cf. https://stackoverflow.com/questions/5946526/having-problems-reading-writing-the-php-temp-stream

# 補足2

Content-Type が text/html だった。text/csv にしておきたい気持ちがある。

# 補足3

Windows だと日本語文字化けします。

```php:var_dump
$handle = fopen('php://memory', 'w');
$list = [[1,'hoge'], [2,'piyo'], [3, 'fuga']];
foreach ($list as $row) {
    fputcsv($handle, $row);
}
rewind($handle);
// fpassthru($handle); // これをした後だと、stream_get_contents に入ってこない。
var_dump(stream_get_contents($handle));
fclose($handle);
```

こんな感じでデバッグをして。文字コードを変更するバージョンは以下です。

```php:抜粋
return response()->streamDownload(function () use ($header, $list) {
    $handle = fopen('php://temp', 'w');
    fputcsv($handle, $header);
    foreach ($list as $row) {
        fputcsv($handle, $row);
    }
    rewind($handle);
    echo mb_convert_encoding(stream_get_contents($handle), 'SJIS-win', 'UTF-8');
    fclose($handle);
}, $name);
```
なんで 「メソッド」ってやらないといけないの？　~「mainだけ」ならうまくいってたのに~

#問題点
mainメソッドまでは上手くいってました。
だけど、「メソッド」や「オブジェクト」が登場してから急に難しくなりました。

![スクリーンショット 2020-01-11 13.30.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354233/088324e3-f3ff-0408-a976-c029e4a786fa.png)



#結論
オブジェクト化する事で、好きなファイルに好きなタイミングで設定した変数とメソッドを呼ぶことができる。
メソッド化する事で、保存や加工したデータを戻り値で飛ばせるようにして、引数で受けとる事ができるようになる。
これらによりどんなファイルでも自由自在にデータを渡せるようになる。

どういう事か説明します。

#問題発生の範囲
#####1.「Main1」ファイルから「Human」ファイルを呼びます。

```Java:Main1.java
public class Main1 {
	public static void main(String[] args) {

		Human human = new Human();
		human.name = "あいだ";
		human.hello();

	}
}
```

####2.「Human」ファイルの中身です。

```Java:Human.java
public class Human {
	String name;
	
	public void hello(){
		System.out.println(name +"さん、こんにちは");
	}	
}
```

####3.ターミナルの結果です。

```
あいださん、こんにちは
```

#疑問点
ファイルを２つも用意しなくていいのではないか？
　→mainだけで作ることはできないのか？

####1.「Main2」ファイルだけで、同じ結果になるように作る。

```Java:Main2.java
public class Main2 {

	public static void main(String[] args) {
		String name;
		
		name = "あいだ";
		System.out.println(name +"さん、こんにちは");
	}
}
```

####2.できました。

```
あいださん、こんにちは
```

#結論1

以下の場合は、オブジェクトもメソッドも必要がない事がわかりました。

- 保存するデータ(name)が１つ
- データの処理(nameを使った出力)が1つ

#新たな疑問
先ほどは「あいださん」1人だけでしたが、
「うえださん」も追加したらどうなるのか？

####1.「Main2」ファイルに「うえだ」さんを追加します。

```Java:Main2.java
public class Main2 {

	public static void main(String[] args) {
		String name;
		name = "あいだ";
		//■①「うえだ」さんを追加する。
		name = "うえだ";
		
		//■②「あいだ」さん用の「こんにちは」はそのまま
		System.out.println(name +"さん、こんにちは");
		//■③「うえだ」さん用の「こんにちは」を追加
		System.out.println(name +"さん、こんにちは");
	}
}

```

####2.できませんでした。

```
うえださん、こんにちは
うえださん、こんにちは
```

#結論2
mainメソッドだけでやろうとすると、

- 同じ変数(変数が上書きされる)が使えない。
- 変数が使えないのでデータの処理もうまくいかない。(「うえだ」さんしか出てこない。)

#解決策

####変数を増やす。

```Java:Main2.java
public class Main2 {

	public static void main(String[] args) {
		String name1;
		String name2;
		name1 = "あいだ";
		name2 = "うえだ";
		
		System.out.println(name1 +"さん、こんにちは");
		System.out.println(name2 +"さん、こんにちは");
	}
}
```

#結論3

保存したいデータが２つ以上になってくると、

- 変数を２つ用意しなければならない。
- 変数名を考えないといけない。
- 後から見た時に「どの変数」に「どのデータ」が入っているかわからなくなりそう。

#まとめ

mainメソッドだけで処理するより、オブジェクトで分けた方がいいメリットして
以下の事がわかりました。

- 同じ変数名でデータを保存できる。
- 好きなタイミングでデータを引き出せる。

#反省点

次回の投稿で「まとめ」の
「好きなタイミングでデータを引き出せる」の部分と
「メソッド」を使う利点を説明できるようになる。
mac osをcatalinaにしてからbundleもrailsコマンドも効かない

最近macosをcatalinaにしたんですが、その瞬間からbundleコマンドもrailsコマンドも効かずに途方に暮れる。

```
 9): Library not loaded: /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib (LoadError)
```
上記エラーばっかり出てくる。

以下のようにすると解決。

```
$brew uninstall --ignore-dependencies openssl
$brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/30fd2b68feb458656c2da2b91e577960b11c42f4/Formula/openssl.rb
```

どうやらopensslのversionが問題らしい

参考記事(英語です)
https://forums.meteor.com/t/mongodump-cannot-find-openssl-version-on-macos-catalina/50912/2
Vueのv-modelとBootstrapのradio button groupを一緒に使う．

# やりたい事
Vueの環境で，[Bootstrap Checkbox and radio buttons](https://getbootstrap.com/docs/4.1/components/buttons/#checkbox-and-radio-buttons)を使い，以下のようなトグルボタンを作る．

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="html,result" data-user="hirokazu-narui" data-slug-hash="vYBpqom" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Vue_bootstrap4_checkbox&amp;amp;radio_button">
  <span>See the Pen <a href="https://codepen.io/hirokazu-narui/pen/vYBpqom">
  Vue_bootstrap4_checkbox&amp;radio_button</a> by Hirokazu Narui (<a href="https://codepen.io/hirokazu-narui">@hirokazu-narui</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# はまった事
[Bootstrap Checkbox and radio buttons](https://getbootstrap.com/docs/4.1/components/buttons/#checkbox-and-radio-buttons)に従い，以下のようなコードを書いたところ，Vueの`v-model`がリアクティブでなくなった．

```html:html
<div class="btn-group btn-group-toggle mx-2 my-2" data-toggle="buttons">
  <label class="btn btn-outline-secondary">
    <input type="radio" id="white" v-model="color" value="white"> White
  </label>
  <label class="btn btn-outline-secondary">
    <input type="radio" id="black" v-model="color" value="black"> Black
  </label>
  <label class="btn btn-outline-secondary">
    <input type="radio" id="brown" v-model="color" value="brown"> Brown
  </label>
  <label class="btn btn-outline-secondary active">
    <input type="radio" id="none" v-model="color" value="" checked> None
  </label>
</div>
```

以下のようにトグルボタンの表示は反応しているが，`v-model`の`color`に値が入らない．
<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="html,result" data-user="hirokazu-narui" data-slug-hash="ExaLXQX" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Vue_bootstrap4_checkbox&amp;amp;radio_button_ng">
  <span>See the Pen <a href="https://codepen.io/hirokazu-narui/pen/ExaLXQX">
  Vue_bootstrap4_checkbox&amp;radio_button_ng</a> by Hirokazu Narui (<a href="https://codepen.io/hirokazu-narui">@hirokazu-narui</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# 原因
Stack Overflowの[Vue v-model not reactive with BS4 radio button group](https://stackoverflow.com/questions/49414388/vue-v-model-not-reactive-with-bs4-radio-button-group?answertab=votes#tab-top)の回答のように，VueとBootstrapの両方のJavascriptからトグルボタンの表示をDOM操作しようとしていた．

そのため，Bootstrap側のJavascriptである`div`タグにある`data-toggle="buttons"`を削除し，`label`タグに対して`:class="{ active: color === 'white' }"`のようにVueから`active`クラスにデータバインディングすることで問題を解決．

# 教訓
あるオブジェクトに対してVueとBootstrapから同時にDOM操作してはいけない．
pycharm+beautifulsoupでModuleNotFoundError

# 今回の結論｜pycharmのインタプリタ設定からパッケージインストールで解決
pycharmのインタプリタ設定の確認。
preferences　→　Project → project interpreter

ここで画像下のプラスボタンからパッケージをインストールしたら
pycharm内のプロジェクトから読み込め、実行できるようになりました。

注意：pycharmプロジェクトごとにこのpythonエンジン、パッケージは設定できるため
　　　他のプロジェクトでは再度設定する必要がある場合もある。

# 状況
スクレイピングをやる前にDjangoの本を進めていたり
pythonのテストをしたりといくつかよくわからないままに
仮想環境ができている状態でさらにpycharmを導入したばかり。

beautifulsoupというスクレイピングのライブラリを使おうとしたら
ModuleNotFoundErrorがでた。
何段階かでハマったのでメモしております。

# pycharmでどのpythonを使っているのかを確認
まずは大前提としてpythonのエンジン
python2.7とかpython3.6とかを
同時にPCにインストールできる。
大変便利な機能でありますが初心者のうちはハマりどころでもあります。
「現在どのpythonエンジンを使用しているのか」
を確認する必要があります。
バージョンが違えば動かないプログラムもあるし
インストールされているパッケージも変わったりします。

今回のModuleNotFoundErrorはまさにこれが原因でした。

# pip listでは出てくるのに
今回ハマったポイントその２として

```piplist.sh

pip list
beautifulsoup4    4.6.0

```

pip listコマンドでは出てくるが
pycharmからは参照できていないという現象。

これも原因としてpythonのエンジン（仮想環境）が
pycharmの設定に反映されていなかったのが原因。

# importした時にどのディレクトリが読まれているかを確認

```import.py

import sys
import pprint
pprint.pprint(sys.path)

```

このimport.pyをpycharm内の現在のプロジェクトで実行すると
importと書いた時に読みに行っているディレクトリを表示してくれる。
案の定beautifulsoupはなかった。

参考：[python初心者がimportエラー(ModuleNotFoundError)で詰みかけた話](https://qiita.com/kakari8888/items/86d9c255204b063c87ee)

# モジュール名の変幻
他の言語、フレームワークでもあるあるだと思いますが
インストールする時と使う時で名前が違うというもの。

```install.sh

pip install beautifulsoup4

```

```import.py

from bs4 import BeautifulSoup

```

今回の正解は依存しているパッケージの記載＋アッパーキャメルケースでした。
これは下記の参考図書にも詳しく書いてくれておりわかりやすかったです。
qiitaの記事にも再びお世話になりました。ありがとうございます。
参考図書：[Python2年生 スクレイピングのしくみ 体験してわかる！会話でまなべる！](https://www.shoeisha.co.jp/book/detail/9784798161914)
参考：[python初心者がimportエラー(ModuleNotFoundError)で詰みかけた話](https://qiita.com/kakari8888/items/86d9c255204b063c87ee)

# 備考｜pythonの仮想環境
今回のハマりポイントとしてpythonの開発環境が個人的にはネックとなりました。
これまでvirtual boxでの開発環境を触ってきた経験があり
最近Dockerを触っている状態だったのですが、
pythonの仮想環境の印象としてはDockerに近いと感じました。
自分も理解が浅いためざっくり書くと
virtual boxはsshで接続する
python、dockerはプロセスを管理している
というようなイメージでした。
[baserCMS][メールフォーム]管理側受信詳細画面で、添付された画像ファイルが表示されないとき


baserCMSには、各メールフォームでの入力内容を管理側から確認できる機能が備わってます。
そのメールフォームには、ファイルアップロード機能が利用できます。
受信詳細画面では、もちろん添付された画像が表示されて確認できるようになっているのですが、あるとき画像が表示されないケースがありました。
そんなときのチェック内容です。

## 想定している対象者
- baserCMSでウェブサイトを制作をしている方
- baserCMSでウェブサイトを運用している方


## 発生状況
1. ファイルアップロード用のフィールドを備えたメールフォームが存在する
2. 受信データ内に、アップロード用フィールドに画像ファイルを添付したデータが存在する
3. 管理側の受信詳細画面にアクセスする
4. 添付されている画像ファイルが表示されない

### 環境
 - PHP 5.6.10
 - baserCMS 4.1.6〜


## 原因
受信詳細画面のファイルに対してアクセス制限設定が掛かっていること。

受信詳細画面に表示する画像ファイルは、
MailMessagesController::admin_attachment() を介して表示される動作となっているため、adminプレフィックスに対するアクセス制限判定が走ってました。

## 対処
アクセスするユーザが属するユーザグループのアクセス制限設定に以下を追加。

- ルール名: 受信メール詳細添付画像
- URL設定: （/admin）/mail/mail_messages/attachment/*
- アクセス: 許可
- 利用状態: 利用する


### 補足
ログイン中ユーザがシステム管理グループのユーザの場合、アクセス制限を受けることはないため同様の症状が起きることはありません。
運営グループに属するユーザに対して受信メール詳細画面までのアクセスを通している場合、かつ、メールフォーム内でファイルアップロードフィールドを利用している場合に起きる可能性が高いですね。