@sustny note

忘れっぽさを補うためのメモ

リアルポタリング

自転車乗りの言うポタリングが100kmを下回らないので、やりました。

相変わらず飽きもせず冴えカノ♭聖地巡礼をしております。

環状5の1号線第3工区に大きな変化を確認。東池袋交差点側から千登世橋へ向かう道が若干区役所寄りを抜けるようになりました。

f:id:sustny:20170710120433j:plain

こんな感じ。

開通は2019年頃でまだまだ先ですが、引き続き追っていきたいです。

出ましたのぞき坂。探偵坂とも加藤恵坂ともいう。

私にはおしるこが見える。

私には加藤恵が見える。

都電早稲田駅。冴えカノ2期7話で出てくる。

都電学習院下駅。もう度々出てくる。

1期9話とかで出てきた小学校ここだろ! と思って来てみたけど、違うっぽいですね。

2期3話で出てきた公園。誰もいないし首都高下でうるさいし憩う場所ではなかった。

最後。前回記事でも言及したけど加藤家の最寄りと思わしき都電雑司ヶ谷駅。

アニメで出てきた角度で、電車が離合するところまでバッチリ合わせられたので大満足。

sustny.hateblo.jp


すべての写真は以下から。

goo.gl

以上です。

事実上の冴えカノ聖地巡礼

期せずして冴えカノ聖地巡礼をしてしまった。

これは都電荒川線です。

のぞき坂。冴えカノの中では探偵坂と呼ばれてたやつ。

2期では写真右側のエントランスにおしるこの缶が置かれていたことでも有名。

私には坂の上に加藤恵が見える。

1期ではここを都電が走る姿がOP冒頭で出てきます。

遠くに見える学習院下駅と更に遠くに見えるブリリアタワー池袋(豊島区役所)。

豊ヶ崎学園からの最寄りがここなのか早稲田なのかが曖昧で、もう少し精密に描いてくれれば雑司が谷がより賑わったのではという地元民的な気持ちがある。

加藤恵の最寄り駅。※アングルはだいぶ違う

2期3話でここを降りていったので実質我が家に住んでいるといっても過言ではない。


冴えカノ聖地巡礼以上。家を出ればすぐ聖地ってのは最高だしそれが好きな作品なら優勝です。優勝しました。

以下、関係ない写真。

以上です。

Rebuild of 潮位情報のプログラム

//
// TideInfo.gs
// Created on 2017-06-30 10:00
// Created by sustny(http://sustny.me/)
//

getInfo = function(DATE, SPOT) {
  //1. 日付と行く場所を指定する(行く場所は特定の観測地点である必要はなく、純粋に自身の目的地を入力すればよい)
  var YEAR = parseInt(DATE.substr(0,4));
  var MONTH = parseInt(DATE.substr(4,2));
  var DAY = parseInt(DATE.substr(6,2));
  
  //1-1. 頭が0の2桁(ex:08)をparseIntするとNaNになるのでその処理
  if( parseInt(DATE.substr(4,1)) == 0 ) {
    MONTH = parseInt(DATE.substr(5,1));
  }
  if( parseInt(DATE.substr(6,1)) == 0 ) {
    DAY = parseInt(DATE.substr(7,1));
  }
  
  //2. 入力されたSPOTを緯度・経度に分解する
  for(var i=0;i<SPOT.length;i++) {
    if(SPOT.substr(i,1) == ',') {
      var lat = parseFloat(SPOT.substr(0,i));
      var lon = parseFloat(SPOT.substr(i+1));
    }
  }
  
  //3. 気象庁が公表している潮位表の掲載地点一覧を呼び出し、行く場所から最も近い観測地点を探す
  var FILE = SpreadsheetApp.getActiveSpreadsheet();
  var SHEET = FILE.getSheetByName('Data');
  var CELL = SHEET.getDataRange().getValues();
  var DIST = [];
  for(i=1;i<CELL.length;i++) {
    //3-1. 経緯度差を三平方の定理から求めて、
    var Dlat = parseFloat(CELL[i][3].substr(0,2)) + (parseFloat(CELL[i][3].substr(3)) / 60) - lat;
    var Dlon = parseFloat(CELL[i][4].substr(0,3)) + (parseFloat(CELL[i][4].substr(4)) / 60) - lon;
    DIST[i-1] = Math.sqrt( (Dlat*Dlat) + (Dlon*Dlon) );
    //3-2. 最も近いところを探す
    if(i == 1) {
      var min = DIST[i-1];
      var j = i;
    } else {
      if(min>DIST[i-1]) {
        min = DIST[i-1];
        j = i;
      }
    }
  }
  
  //4. 最も近い観測地点の情報から当該日付の情報(1行)を抜き出す
  var URL = UrlFetchApp.fetch('http://www.data.jma.go.jp/kaiyou/data/db/tide/suisan/txt/' + YEAR +'/' + CELL[j][1] + '.txt');
  var TXT = URL.getContentText();
  
  if(YEAR % 4 != 0) {
    var arrMonth = [0,31,59,90,120,151,181,212,243,273,304,334]; //各月の開始行メモ
    var Row = TXT.substr(( (137*arrMonth[MONTH-1]) + (137*(DAY-1)) ),136);
  } else {
    var arrMonth = [0,31,60,91,121,152,182,213,244,274,305,335]; //各月の開始行メモ
    var Row = TXT.substr(( (137*arrMonth[MONTH-1]) + (137*(DAY-1)) ),136);
  }
  
  //5. 抜き出した情報を分割して配列に格納する
  //Info = [地名、満潮時刻1、満潮潮位1、満潮時刻2、満潮潮位2、満潮時刻3、満潮潮位3、満潮時刻4、満潮潮位4、干潮時刻1、干潮潮位1、干潮時刻2、干潮潮位2、干潮時刻3、干潮潮位3、干潮時刻4、干潮潮位4]
  var Info = [CELL[j][2],
              '' + parseInt(Row.substr(80,2)) + ':' + parseInt(Row.substr(82,2)), parseInt(Row.substr(84,3)),
              '' + parseInt(Row.substr(87,2)) + ':' + parseInt(Row.substr(89,2)), parseInt(Row.substr(91,3)),
              '' + parseInt(Row.substr(94,2)) + ':' + parseInt(Row.substr(96,2)), parseInt(Row.substr(98,3)),
              '' + parseInt(Row.substr(101,2)) + ':' + parseInt(Row.substr(103,2)), parseInt(Row.substr(105,3)),
              '' + parseInt(Row.substr(108,2)) + ':' + parseInt(Row.substr(110,2)), parseInt(Row.substr(112,3)),
              '' + parseInt(Row.substr(115,2)) + ':' + parseInt(Row.substr(117,2)), parseInt(Row.substr(119,3)),
              '' + parseInt(Row.substr(122,2)) + ':' + parseInt(Row.substr(124,2)), parseInt(Row.substr(126,3)),
              '' + parseInt(Row.substr(129,2)) + ':' + parseInt(Row.substr(131,2)), parseInt(Row.substr(133,3))];
  
  //6. 情報が格納された配列を返す
  return Info;
}

function TideInfo_Main() {
  var date = Browser.inputBox('日付を入れろ(ex:20170101)', Browser.Buttons.OK_CANCEL);
  if(date == '') { //入力がないなら今日
    date = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyyMMdd');
  }
  var spot = Browser.inputBox('場所を入れろ(ex:35.305276, 139.317403)', Browser.Buttons.OK_CANCEL);
  if(spot == '') { //入力がないなら東京
    spot = '35.640342, 139.855059';
  }
  var info = getInfo(date, spot);
  var message = '' + info[0] + 'の潮位(' + date.substr(0,4) + '/' + date.substr(4,2) + '/' + date.substr(6,2) + ')\\n'
             + '満潮1: ' + info[1] + ' ' + info[2] + 'cm\\n'
             + '満潮2: ' + info[3] + ' ' + info[4] + 'cm\\n'
             + '満潮3: ' + info[5] + ' ' + info[6] + 'cm\\n'
             + '満潮4: ' + info[7] + ' ' + info[8] + 'cm\\n'
             + '干潮1: ' + info[9] + ' ' + info[10] + 'cm\\n'
             + '干潮2: ' + info[11] + ' ' + info[12] + 'cm\\n'
             + '干潮3: ' + info[13] + ' ' + info[14] + 'cm\\n'
             + '干潮4: ' + info[15] + ' ' + info[16] + 'cm';
  Browser.msgBox(message);
}

スプレッドシートのURL

気象庁が公開している潮位のテキストデータから情報を生成するプログラム。

指定するのは日付(形式: yyyyMMdd)と行先(形式: DEG)の2つ。

行先は自分が行く場所を指定すれば、あとは勝手に行先から最も近い観測地点の情報を返すようにした。

ちなみに日付を指定しなければ今日の情報、行先を指定しなければ東京の情報を返す。

これが一番シンプルな実装かも。

潮位を表示するために必要な場所のIDマップ

drive.google.com

前回記事で公開した潮位を調べるプログラム内で、場所を指定する際に決められたID(1から327までの整数)を入力する必要がありましたが、地名だけだと具体的な場所が分かりにくいのでGoogle Mapにピン立てしました。

立てたピンに今日明日分ぐらいの潮位情報を載せてGoogle Map内で完結できれば一番使い勝手がいい気がしますが、仕様的にも自身の技術的にも出来るのかどうかから調べていく必要があります。

熱が冷めないうちに頑張ります〜。

潮位を表示するプログラム

釣り好きが高じて潮位を表示するプログラムを書いた。

//
// FishingInfo.gs
// Created on 2017-06-20 13:00
// Created by sustny
//
// tide info: http://fishing-community.appspot.com/tidexml/doc
//

function FishingInfo(p, y, m, d) {
  var feedURL = 'http://fishing-community.appspot.com/tidexml/index?portid='+p+'&year='+y+'&month='+m+'&day='+d;
  var response = UrlFetchApp.fetch(feedURL);
  var xml = XmlService.parse(response.getContentText());
  var xmlStr1 = ['port-id', 'port-name', 'latitude1', 'longitude1', 'latitude2', 'longitude2', 'year', 'month', 'day', 'youbi', 'sunrise-time', 'sunset-time', 'moonrise-time', 'moonset-time', 'tide-name', 'tidedetails'];
  var xmlStr2 = ['tide-time', 'tide-level'];
  
  //タイトル
  var message = '\n■□' + xml.getRootElement().getChild(xmlStr1[1]).getText() + 'の潮位情報□■';
  
  //日付...yyyy年mm月dd日(ddd)
  message += '\n◆' + y + '年' + m + '月' + d + '日(' + xml.getRootElement().getChild(xmlStr1[9]).getText() + ')';
  
  var items = ""
  for(i=0;i<2;i++) {
    items = xml.getRootElement().getChildren(xmlStr1[xmlStr1.length-1]);
  }
  
  message += ' - ' + xml.getRootElement().getChild(xmlStr1[14]).getText();
  for(var i=0; i<items.length; i++) {
    var time = items[i].getChild(xmlStr2[0]).getText();
    var level = items[i].getChild(xmlStr2[1]).getText();
    if( (time != "") || (level != "") ) {
      message += '\n時刻: ' + time + ' / 潮位: ' + level + "cm";
    }
  }
  
  //日出・日入時刻
  message += '\n\n◇こよみ\n日出: ' + xml.getRootElement().getChild(xmlStr1[10]).getText() + ' / 日入: ' + xml.getRootElement().getChild(xmlStr1[11]).getText();
  //月出・月入時刻
  message += '\n月出: ' + xml.getRootElement().getChild(xmlStr1[12]).getText() + ' / 月入: ' + xml.getRootElement().getChild(xmlStr1[13]).getText();
  //地図
  message += '\n\n◇場所\nhttps://www.google.co.jp/maps/place/'+ xml.getRootElement().getChild(xmlStr1[4]).getText() + ',' + xml.getRootElement().getChild(xmlStr1[5]).getText();
  Logger.log(message);
}

function Main() {
  var place = 89; //ex: 96-晴海 / 89-立山 / 116-江の島
  var year = 2017;
  var month = 07;
  var day = 07;
  
  FishingInfo(place, year, month, day);
}

GitHubこちら

相変わらずGASで書いています。

ちなみに潮位情報は釣りコミュニティーサービス[fishstar]というところから引っ張っています。

商用利用でなければ無料。ありがとうございます。


場所と日付をコード内で指定するのではなく、外部からの入力によって変化させたりとかアイディアはたくさんありますが、とりあえずコード内で完結できる最少の状態を公開しておきます。

変なところとかあれば教えていただけると幸いです。(xmlから情報引っ張ってくるのとか初めてやった)

以上です。

徹夜釣り部

もうすっかり釣りの虜です。

6月17日16時から隅田川の足立小台付近で開始。

捕まえてきたミミズを針に容赦なく刺し糸を垂らすも、釣れず。

暑い日も増えてきたけど、まだまだ釣りをするには寒かったっぽい。

結局ゴミ袋が2つ釣れただけでした(号泣)

西新井の中華屋とてもよかった。味噌で食べる餃子おいしかったです。

その後、納得行かない3人だけがその足で平塚へ向かう。

駅前のスーパーでアサリを手に入れ、いざ相模川

賑わってます。

が、結局釣れたのはハゼ? の稚魚だけ。泣きながらリリースしました。

場所を変えるも、やはり釣れず。

というわけで釣果0匹で徹夜釣り会は幕を閉じたのでした。


goo.gl

すべての写真は上より。

前回が調子良すぎただけで、普通釣りといったらこんなもんだと思います。仕方ないね。

来月に平塚リベンジをしようと誓い時を待つのであった。

開催するイベントを自動でリマインドするやつ

を作った。

※【追記】2017/06/10 0:05 - ちょっと書き足しました

仕組み

  • Googleスプレッドシートにイベントを書いていく
  • Google Apps Scriptで今日or明日のイベントを探させる
  • 今日のイベントだったら8時、明日だったら20時にリマインドをLINEに送る

コードはGitHubに置いた。

スプレッドシート自体もそのうちどこかで公開するかも。

ぶっちゃけもっと便利でクレバーな通知方法はあふれてると思ってしまってつらい。

スプレッドシート

f:id:sustny:20170609180945j:plain

用意したのはこんな感じのスプレッドシート。用意したというか元から使ってたので、今回のために新たに用意したわけではない。

背景として、毎月集まる友人ら8人と飲み会だの旅行だのやっているので、元々は出欠を明瞭にするためにスプレッドシートを作成していた。

その後、Google Apps Script(以下"GAS")を使用しLINEへ投稿ができることを知り、予定を投げるスクリプトを書いてみようとなったのが今回の始まり。

日付とか場所とかを書いていき、参加者に◯、未定の人に△、不参加なら×を書いていく感じで使っている。

イベントが終わると自動でグレーアウトする(ただの条件付き書式→"=(開催日)<TODAY()“)。

GAS側の処理

  1. 直近で一番近い、もしくは当日の予定を探る
  2. 探ったイベントの日付を確認し、今日なら午前中、明日なら夜に投稿されるよう次の関数に投げる
  3. 概要(イベント名、場所、集合時間、集合場所)を配列へ格納する(空白だったら"(未定)“を格納する)
  4. 参加者一覧(シート右側の欄で"◯"がついている者)を探索し、対応するものの名前を用意した変数へ格納する
  5. 概要と参加者一覧をLINEで通知する関数に投げ、投稿させる
  6. 上記2から5をあと4回繰り返す(下の行にイベントがなければ何も起きない)

LINE側への通知

f:id:sustny:20170609181600j:plain

こんな感じで通知される。


[テスト]
■□(本日|明日)のイベント情報□■
【(イベント名)】
(開催場所)
【集合】
[H:mm]
[集合場所]
【参加者】
(ex.)和泉、山田、千寿、獅童


スクリプト自体はAM8-9時とPM20-21時の2回動いてくれるようにGASのタスクスケジューラ的なやつで登録済み。

スクリプト内で現在時刻が12時より前だったら当日の予定、12時より後だったら翌日の予定を出力するように分岐させてるのでこれで運用上は問題ないはず。

何度もテストはしたけど、ひとまず実際の予定通り動き始めるのが6/16の20時以降なので問題あれば改善する必要あり。

以上。