猫になりたかった人生です。

猫になりたかった人生です。

とある情報系専門学校生の活動記録

簡易的なTwitterBotを作った話

自動で呟けばBot扱いでいいよね!
やっぱりGASは楽しいぜ
この記事は、所属しているサークルのAdvent Calendar2018の12/11(火)の記事でもあります。

きっかけ

前回の記事を書いて一か月がたった頃、何となく作りたいものが思いつきました。
TRPGってご存知ですか?
\(・ω・\)SAN値!(/・ω・)/ピンチ!とかのSAN値が出てくるクトゥルフ神話マギカロギアなどいろんな世界観のシステムがありまして
Twitterとゲームを介してできた友人達がやっていて気になりすぎて10月くらいにチャレンジしてみたんです。
キャラを作ってダイスを振って行動の成功判定を行ったり、自分次第でシナリオの進み方が変わっていくので物凄く楽しかったです。

仕様

予めフォームで下記情報を登録しておき一定時間ごとに登録された情報でダイスを振ってその結果をツイートするものです。

  • キャラ名
  • 行動名
  • 成功値
  • ダイスの種類
  • ダイスの数
  • 補正値

ちょっと寄り道

前回の記事のコメントに来ていた「clasp」なるものが気になったので、ある程度プログラムを作ってから入れてみた。
参考にした記事
claspを使い、Google Apps Scriptプロジェクトをgitでバージョン管理する - Qiita
gitは元々入れてあったので2のNode.jsを入れるとこから
【数々のやらかしログ】

  1. npmのバージョン確認できない

→「nmp」と入力してたことに気がつかず10分くらい悩んだ

  1. claspを入れるところで何故かエラーが出る。

→そもそも「Node.js command prompt」から実行せずcmdでやってたから管理者権限的にエラー吐くんだと思われ

ついでにローカルに持ってきた際、自動的にディレクトリに変換させたいので。
ファイル名を「ディレクトリ名/ファイル名.拡張子」に変更してみた。
f:id:MI_SAN_CAT:20181202015647p:plainかわいい

いざクローンの儀
clasp clone プロジェクトID
clasp pull
出でよプロジェクトファイル!!
f:id:MI_SAN_CAT:20181202020107p:plain出たー!!いつこの記事書いてるかバレるーーー

よっし!Atomで書いてpullしていくぞー!!!
これで学校のクソ無線の通信切れで更新ができない状態はちょっとはましになるはず
(AtomのテーマはRainってやつに変えてみました)
f:id:MI_SAN_CAT:20181202024456p:plain

構成

情報登録用フォーム

めんどくさかったのでGoogleフォームで......ポンッ!
f:id:MI_SAN_CAT:20181202031539p:plain

情報登録DBもどき

いつも通りspreadsheet作っていく(映ってるデータはオリキャラのもの)
f:id:MI_SAN_CAT:20181202042358p:plain

Twitter投稿

Twitter投稿をする為にライブラリを導入
参考にしたのはこちら
Google Apps Script (GAS) でTwitterへ投稿するだけの機能を実装してみる - Qiita
投稿する文を関数の引数にぶち込んで投稿させてます。

ランダムにロールさせるものを選ぶ

SpreadSheatAPPで登録されている行数を取得し、最小値(2)~最大値(取得最終行)でランダム関数で選びロールさせる関数を呼び出す。
戻ってきた数値たちを文にしてツイート投稿の関数に投げてます。

ロールさせる関数

ダイスの種類でswitchさせて、ダイスの数だけループさせてダイスの値や合計値、成功判定などを連想配列に格納してreturnしてます。

何となく画面も作る

登録した人たちにも楽しめるように最低限かつCSSつけてないです。
f:id:MI_SAN_CAT:20181202064544p:plain

投稿させてみた

TRPGなのでゲーム垢でツイートさせてみた。
f:id:MI_SAN_CAT:20181202061139j:plain

改善点

onFormSubmitを使ってフォームの登録時に登録された内容でデバック兼ねてツイートさせるようにしました。
CUI上でGitHubになぜかpushできない。二重認証的なので引っかかっているぽいので気力があれば認証の確認して再挑戦してみます。

今年の振り返り

スペースが余ったのでちょいと今年の振り返りしますー

今年

丁度学んだHTML系統に手を出して、趣味でのGAS作品がパワーアップしました。CSSはムツカシイ
資格面では、基本情報技術者試験と医療情報技師に無事合格できたのが大きかったですね。誕生日に合否発表だったのでビビってましたが......

来年

診療情報管理士に受かるように頑張りつつWebアプリでのキャッシュに手を出そうかなと思います。
外出先でスマホのアプリをダウンロードするのがめんどいなと思う人である事と、容量や通信料を気にする人が多いと思うのでwebアプリをキャッシュで動作できるようにオフラインで動作させるものを作りつつ学んでいこうと思います。

何というか趣味はweb系統に進んでる気がするなぁ......

照明のお仕事で発狂した話

がんがん効率化したいけど引継ぎを行う際の説明と理解力の差に難易度が上がる
前回からはてな記法に変更して書き始めてます。
どうも猫さんです。今回は私が所属している軽音サークルでの照明でぐだった話を備忘録も兼ねて書いてます。
この記事は、所属しているサークルのAdvent Calendar2018の12/5(水)の記事でもあります。

背景

学園祭が近づいてきている夏のある日、猫さんは弊学の八階に設置している照明に対する問題の解決に乗り出そうとしていた。
・教師経由に伝えられた「演技をするのにまだ暗いので何とかして」問題
プログラミングコンテストの際に知らされずに増えた照明と卓につながれたケーブルが既存の物と混ざり天井でスパゲティケーブル状態な問題

問題対応

明るさ確保

その1.数作戦
パーライトを増やして、一部の照明を移動して照らす方向を増やす&明るさUP。
その2.機能作戦
説明書を読んで各照明のDMXモードのDIM調整の事を知ったので、照明卓でパーライトのDIMを上げることで明るさUP。

照明類注文

パーライトの注文時に品切れがあったので同じメーカーの別の機種に変更
機種によってはDMXモードのチャンネル数が違うので照明卓のチャンネル整備が必要になった
チャンネルの整備と同時に照明卓の割り振り変更
下:実際に整備したチャンネル
f:id:MI_SAN_CAT:20181121160255p:plain

打倒スパゲティケーブル

お前なんかスパゲティコードよりも攻略は簡単なんだよ!!!!!
ということで配線の引き直しと届いた照明の設置&テストを行うことに
設営にあたり照明の用語や知識を理解しつつ仕込み図を作成
(下:実際に作った仕込み図)
f:id:MI_SAN_CAT:20181121150223p:plain
設置班人員が足りても脚立が足りず、時間を持て余す人が非効率的な作業になってしまった。
ついでに練習をしたいが時間も設置とは別の照明班が予定合わずに集まれなかったので前日準備の際に行うことに。

実践 in 前日準備

さあ、事前設置はやっておいた!!リハという名の急ぎの照明班の研修に入れる!!!
と思うやん?思ったやん??

弊学の学園祭のステージは普段のイベントと違って大きく設置されるのですが、その設置が前日リハの日で出来上がらない限り大きさも把握できないのです。
いざ出来上がったステージはダンス部さんの踊る予定のスペースを大幅に圧迫して照明が当たらなくなってしまった!
あれれー?おかしいなーーー元から設置してある照明の列は動かしていないのに!
照明の再設置!事前設置の苦労は水の泡と化したのだ!!!
※仕込み図も書き換えなければいけないが手を付けていない

最終的に照明班の説明&練習が開始できたのはステージ演者たちのリハ開始時でした。
照明初心者の人たちに分かりやすく用語説明しつつ実践ってクッソ難しいね!!!

同時に効率化

ダンス部さんの照明のご要望が意外と多かったのでちょうどいい機会だと思いつつ効率化に挑戦しました。
やったのは「シーン登録」「シーン再生」の二つだけです。卓の 1 4 4 8 が染みついた
様々な照明のDMXのチャンネルごとの全ての入力値を保存して一つのつまみだけで呼び出して調整できるようにしました。
PCで操作できるようにしても引継ぎ先の人のPCスキルで問題が出そうなので却下しています。(IT科って何だろう)

プログラミング的に言うと、オブジェクト指向カプセル化みたいな・・・関数にして呼び出すみたいな・・・うーん難しい

録画して、再生する!これで通じるはず!

照明班の人員不足問題

経験のある人員がクラス出店にいってしまったのでビクビクしつつも初めて触る&二回目組に教え込みました。
理解度も適応力も高く即戦力になってくれて心身ともに本当に助かりました。(本人たちがブログにたどり着くことは多分ないけど改めて感謝を)
急にバンドとして追加出演することが初日終了後に報告された際の友人への怒りは決して忘れないでしょう。
来年もやりやがったら頬抓ってやりますので新軽音部長さん覚悟をしておいてください?
ぶっつけ本番で照明を上手く出来ていた彼らは照明班の素質があると思います。
今年度卒業と来年度卒業でなければ引継ぎ先にしてました。(私は再来年度卒業)
というわけで引継ぎ先がいないので来年度も地獄を見そうな気がします・・・お笑いライブあるし、人集めなければ・・・

まとめ

説明書読もうね、海外メーカーだけど多分サウンドハウスさんが日本語のマニュアル付けてくれるので少しは怖くない
実際に弄れ!!!リハではちゃんと動いてたのに当日で動かないときは電源入れなおしゃ直るかもしれん!
用語は調べて理解しつつ操作して自分の印象で単語帳作るといいかも(例:SHUTTER→蓋 GOBO→エフェクトの形)
仕込み図はExcelで頑張るのもいいけど出力時に地味に面倒だったのでして図面作成ソフトとかで効率化してもいいかも
練習と時間はあっても無駄にはならない。
設営に関してはステージ設置関係者(今も知らない)と相談が必要です。
分身はできないし手も二本しかありませんから諦めて人を集めましょう。
ステージ上でベース弾きながら照明弄るなんてことできませんから・・・
紙媒体として残しておかないとIT科と言っていてもまともに引き継げない可能性が高い!

GASの作品がちょっとだけ進化した話

GAS(Google Apps Script)から逃れられない。

慣れてくると便利だなと離れられなくなってしまいました。
今年も美味しい食べ物と仕事が増える季節がやってきました。
どうも、猫さんことセンセです。

本記事は、去年4月から作りたいと思いつつもできていなかったGASの天気予報の発展版を見せれる程度にはできたので、紹介記事になります。
前に投稿されていたものから更新を兼ねた書き換えです。
今後も作品について詳しい説明を更新していこうと思います。

成果物

作品URL:天気予報ノート
コード:GitHub

画像


f:id:MI_SAN_CAT:20181024143136p:plain
f:id:MI_SAN_CAT:20181024143139p:plain
f:id:MI_SAN_CAT:20181024143142p:plain
f:id:MI_SAN_CAT:20181024143145p:plain


Ⅰ.f:id:MI_SAN_CAT:20181024145501p:plain
Ⅱ.f:id:MI_SAN_CAT:20181024145458p:plain

関数の説明

調べながら組み合わせて作成したので、あまりよろしくないプログラムになっていると思います。
語彙力が地獄に落ちてしまっているので、説明もざっくりと

doGet

function doGet() {
var htmloutput = HtmlService.createTemplateFromFile('Page').evaluate();
htmloutput.setTitle('天気予報ノート').addMetaTag('viewport', 'width=device-width, initial-scale=1');
return htmloutput;
}

お馴染みのdoGetです。
他の環境で開発する際は他にも長い内容が必要なのが多いですが、GASだと基本これだけで済みます。(だから離れられなくなる)
createTemplateFromFile等の説明はhttps://tonari-it.com/gas-web-application-beginner/:こちらのサイトが分かりやすかったです(/・ω・)/
titleタグやmetaタグ等は、読み込まれない的なめんどくさいことがあるのでsetTitleでタイトル設定しています。
addMetaTagではスマホからの表示に対応させています。

画像のセレクトボックスのonChange

    function areaSet(obj) {
      var check;
      if (obj.id == 'Area') {
        check = 0;
        var areaIndex = obj.selectedIndex;
        google.script.run.withSuccessHandler(setArea).withUserObject(check).areaList(areaIndex);
      } else if (obj.id == 'Point') {
        check = 1;
        var areaName = document.getElementById('Point').value;
        google.script.run.withSuccessHandler(setArea).withUserObject(check).setPoint(areaName);
      }
    }

    function setArea(area_list, check) {
      var setsel;
      var desc_str;
      if (check == 0) {
        setsel = document.getElementById('Point');
        desc_str = '②都道府県を選択してください';
      } else if (check == 1) {
        setsel = document.getElementById('DoArea');
        desc_str = '③観測地点を選択して、「天気取得」ボタンをクリックして下さい';
      }
      setsel.options.length = 0;
      clearChildNodes(setsel);
      for (var key in area_list) {
        // option要素の宣言
        var option = new Option(area_list[key], key);
        // 作成したoption要素をselectに追加
        setsel.appendChild(option);
      }
      document.getElementById('result_area').textContent = desc_str;
    }

選択された地方の都道府県や選択された都道府県の観測地点を連想配列にして返してセレクトボックスのOptionに追加します。
都道府県はswitchで、観測地点はスプレッドシートをDBに見立てて取得しています。
スプレッドシートは、地点一覧の開始と終了位置を別のシートに置いておき二度取得させています。(ⅠとⅡ)

天気取得のonClick

function getWeather() {
      var strset = document.getElementById('result_area');
      var val = document.getElementById('DoArea').value;
      strset.textContent = '天気取得中';
      google.script.run
        .withSuccessHandler(setWeather)
        .withFailureHandler(dontset)
        .getJson(val);
    }

    function setWeather(strBox) {
      var titlis = [
        ['today_date', 'today_weather', 'today_high', 'today_low'],
        ['tommorow_date', 'tommorow_weather', 'tommorow_high', 'tommorow_low'],
        ['tommorows_date', 'tommorows_weather', 'tommorows_high', 'tommorows_low']
      ];
      var idlist = ['today', 'tommorow', 'tommorows'];

      document.getElementById('result_area').innerHTML = strBox['location'];

      for (var i = 0; i < 3; i++) {
        var cls = document.getElementById(idlist[i]);
        if (cls.hasChildNodes()) {
          for (let i = cls.childNodes.length - 1; i >= 0; i--) {
            cls.removeChild(cls.childNodes[i]);
          }
        }
        var pTag = document.createElement('pre');
        pTag.setAttribute('class', 'pre');
        for (var j = 0; j < 4; j++) {
          pTag.textContent += strBox[titlis[i][j]];
          pTag.textContent += '\n';
        }
        cls.appendChild(pTag);
      }
      var txt = document.createElement('pre');
      txt.setAttribute('id', 'text');
      txt.setAttribute('class', 'pre');
      txt.innerHTML = strBox['text'].split('】').join('】\n');
      document.getElementById('tommorows').insertAdjacentElement('afterend', txt);
      document.getElementById('weather_announce').innerHTML = strBox['announce'];
      document.getElementById('weather_link').href = strBox['link'];
      document.getElementById('weather_link').textContent = '天気予報取得元';
    }

    function dontset() {
      document.getElementById('result_area').textContent = '天気取得失敗';
    }
  function getJson(point) {
    point = '' + point;

    var data = UrlFetchApp.fetch('http://weather.livedoor.com/forecast/webservice/json/v1?city=' + point);
    var json = JSON.parse(data.getContentText());
    Logger.log(json);
    var text = makeText(json);
    return text;
  }

  function makeText(json) {
    var titlis = [
      ['today_date', 'today_weather', 'today_high', 'today_low'],
      ['tommorow_date', 'tommorow_weather', 'tommorow_high', 'tommorow_low'],
      ['tommorows_date', 'tommorows_weather', 'tommorows_high', 'tommorows_low']
    ];
    var strBox = {};
    var hightem;
    var lowtem;
    //天気取得位置
    strBox['location'] = json['title'];

    for (var i = 0; i < 3; i++) {
      for (var j = 0; j < 4; j++) {
        switch (j) {
          case 0: //日付
            strBox[titlis[i][j]] = json['forecasts'][i]['date'];
            break;
          case 1: //天気
            strBox[titlis[i][j]] = '天気:' + json['forecasts'][i]['telop'];
            break;
          case 2: //最高気温
            if (json['forecasts'][i]['temperature']['max'] == null)
              hightem = 'データ無し';
            else
              hightem = json['forecasts'][i]['temperature']['max']['celsius'];
            strBox[titlis[i][j]] = '最高気温:' + hightem;
            break;
          case 3: //最低気温
            if (json['forecasts'][i]['temperature']['min'] == null)
              lowtem = 'データ無し';
            else
              lowtem = json['forecasts'][i]['temperature']['min']['celsius'];
            strBox[titlis[i][j]] = '最低気温:' + lowtem;
            break;
        }
      }
    }
    strBox['text'] = json['description']['text'];
    //発表日時
    strBox['announce'] = '発表日時:' + json['description']['publicTime'];
    //サイトのリンク
    strBox['link'] = json['link'];
    return strBox;
  }

前の処理で③のセレクトボックスの選択項目のvalueに地点のIDをセットしておき、そのIDをgetJsonに投げて天気予報のJSONを取得してきます。
取得したJSONをmakeTextに投げて一つの連想配列にしてsetWeatherに投げてpreタグに追加して表示しています。

去年からの進化

授業でHTMLを少し勉強したので一気にかっこよくなった()
onChangeで実装出来たので地点の選択項目一覧が少なめになっている。
GitHubでコード管理をできるようにした。Chrome拡張機能で便利に!
CSSってすごいね!未だによく分かってないけど自分の描きたいデザインが沢山ある(お借りした)
SNS共有できるようになりました(TwitterとLINE)

その他

相変わらずスプレッドシートをDBに見立てて使用しているが、改善しないと動作が遅いかもしれないと思っています。

当日の最低気温が出ないのが少し残念なので、別のAPIの使用を考慮するか天気予報系からの卒業をする予定です。

メール送信機能が実装できていないので、いつか本文の見た目を弄って実装しておきます。

時間ごとの自動ツイートもアプリ連携でユーザごとに変えたり出来たらいいなと思います。

エディターの色を変えるとあら不思議、失いかけていたモチベが復活したではありませんか。(Chromeの拡張です)

目標を考える話

3時間以上体育館でバスケ、バレー、バドミントン等やって筋肉痛を極めた

どうも、筋肉痛2日目を迎えた猫さんことセンセです。

今日は所属しているプログラミングサークルでのサークル目標と個人目標を立てる記事になります。

サークル目標って必要でしたっけ?

新入部員いなきゃ誰が引き継ぐのって思ったり思わなかったり

とりあえず外部イベントがんがん参加したい。

折角ブログ書きゃ公欠扱いにできる制度あるのに活用しなきゃ勿体ないんじゃない?ってね。

この学校に入学して1年経ったけどまあプログラミングする授業がない。

おまけにCASLSQLをちょっとやったくらいでチーム開発やれは去年の私には精神的にだいぶきつかった。

あまりプログラムする気力が湧かない人が多い気がするので折角のサークルで、学生だから外部イベントに行くこと増やしてみませんか?

一人で今年のABC行くことができなかったので皆で行けば怖くない的な感覚です。

MakerFaireTokyoは商談の為であるコンテンツEXPO東京とは違って、子供向けの体験とかもあるしがっつりIT系でもないので外部イベント入門としても私はおすすめします。

個人目標

 1.新しく作りたいもののアイデアを思いついて作成に取り掛かる。

去年はGASで天気予報の自動ツイートやら中途半端に暗号化に挑戦したりとアイデアが生まれてきていたのに資格試験だー、ベース練習しなきゃーと自分に言い聞かせていたらアイデアが浮かばなくなってしまった。

とりあえず外部イベントに参加したりいつもとは違うことをしたり自分とは違う考え方をたくさん見て聞いて面白いアイデアを浮かべたいと思います。

2.資格試験合格

医療情報技師の合格とちまちま応用情報かセキュリティの勉強も始めていかなければなぁと思います。

3.ベースの技術力をあげる

ベースを初めて1年が経ったのでスラップとかも練習して、経験者組のやりたい曲をできるようになりたいなと......

その他

6/30に人生初のアイデアソンをしました。

私の中では学校選抜に選ばれてしまった介護デジタルハッカソンの話し合いの練習がてらでしたが、各チームのアイデアが独特かつ面白かったので参加してよかったと思います。

ゆるっとまるっと振り返り

今年の漢字は「北」らしいです。北海道のイクラ丼が食べたい...... 

adventar.org

というわけで今回は上記アドベントカレンダーの17日目になります。

今年はどんなことをしたのか、過去に書いた記事を一部取り上げつつ振り返りたいと思います。

ゆるーっと振り返り

入学後、2つ系統の違うサークルに所属しつつ8ヶ月とあっという間に過ぎ去っていきました。

 技術系イベント参加履歴

人生初の技術系イベント参加は6月でした。

ついでに初の名刺も作ってもらいました!あとビックサイトも初ですね。

私の知っている技術は、もはや過去のものでありあったらいいなが既に実現しているという事を実感しました。

これは学校の行事として参加してきました。

電子お薬手帳骨伝導についてはここで知ることが出来ました。

企業の方とお話しするのも楽しいですね。

期間が開いて3年ぶりの幕張メッセにも行ってきました。

 

実際に開発した話

これは後に断念していますが高校の時に学んだ暗号方式を組み合わせて遊ぼうとしてました。

 

こちらはアドベントカレンダーにも載っていますがちゃんとした開発を行おうとしてた話です。しばらくcase文は見たくありません。

 

番外編

秋葉原での探検の話です。ここでワクワクしている物は実際に技術系イベントで知ったものや授業でまとめたものが基盤になっているので、また時間とお金があれば一日パーツ屋さん巡りしたいなぁ......

来年の目標 

授業で行っている開発を完成させること

基本情報技術者試験に合格すること

何かハードウェア関連で作りたい、ボタン押してツイートさせるだけでも

 

こんな感じで今年は終わりですね。忘年会シーズンなのでどこも人が多くて人酔いがしやすくて辛いです。あと匂いに敏感になっているのか直ぐにむせるのだけは治したい...

 

来年もよい年でありますように

 

 

 

開発初心者が初めてシステムを開発しようとした話

 

どうも、猫さんです。

今回は9月末にグダグダと決まった会計システム作成の振り返りを題材にしつつAdvent Calendarの12日目を書いていこうと思います。

 

adventar.org

あらすじ(スキップ可)

9月末のとあるサークルでのMTG

約一か月後に控えた学園祭での出し物について話していた......

 

そこで使用する会計システム、もしそれを生徒で作るとするならば誰が作るか

先輩は乗り気ではない、それだけは空気で、反応でめんどくさいとわかる。てかめんどいから嫌だとも言われた。

 

私は迂闊だった。後に装飾にも名乗りを上げてしまい仕事を増やしてしまうなんて思っていなかったからだ。

やろうとしたこと

 

f:id:MI_SAN_CAT:20171204142128p:plainGoogleスプレッドシートをデータベースとして扱い

GoodleAppsScriptでスプレッドシートへの読み書きやJSON変換で送信

HTMLで取得したデータの表示や入力データの送信

を行わせています。改行の表示とかが残っていますが急いで作ったので許してください。

何故複数人になったか

最初は1人での開発に挑戦していましたがHTMLでの入出力処理や、GASとのデータのやり取りの実装が知識不足によりなかなか出来ず泣く泣く五段先輩に依頼したわけです。

 

簡単に説明すると...

フロントエンド(HTML)側:五段先輩

バックエンド(GAS及びスプレッドシート)側:猫さん

ということで本番まで残り20日ほどで再スタートとなりました。

今回の記事で書くのはバックエンド側です。

仕様

スプレッドシート

は商品リスト用と販売履歴用の2つのシートを同じスプレッドシート上に作成しています。

GAS

GASとスプレッドシート間はGoogle Sheets APIで、

GASとフロントエンド側へはJSONに変換してからdoGetとdoPostを利用しています。

doGetでは、modeというパラメータを追加することで2つのモードを実装。

allで商品リスト、fiveで販売履歴5件を最新の5件前から最新までのをJSON形式でそれぞれ返します。

更にWebアプリケーションとして導入することで面倒な「Developer ConsoleでのExecution API設定」等を省いています。

ソースコード
var url = 'スプレッドシートのURL';
var sheetName = '商品リストシート';
var book = SpreadsheetApp.openByUrl(url);
var sheet = book.getSheetByName(sheetName);

 // フロントエンドへのデータ送信
function doGet(e){
  switch(e.parameter.mode){
    case 'all':
      var json = convSheet(sheet);
      Logger.log(JSON.stringify(json));  
      return ContentService.createTextOutput(JSON.stringify(json)).setMimeType(ContentService.MimeType.JSON);
      break;
    case 'five':
      var sheetH = book.getSheetByName("販売履歴シート");
      var json = GetList(sheetH);
      Logger.log(JSON.stringify(json)); 
      return ContentService.createTextOutput(JSON.stringify(json)).setMimeType(ContentService.MimeType.JSON);
      break;
    default:
      return ContentService.createTextOutput("EROOR!");
      break;
  }
}

// シートからデータを取得する function GetList(sheetH){ var LastRow=sheetH.getLastRow(); var FirstRow=LastRow-4; var column = 1; var numcolumns =11; var range = sheetH.getRange(FirstRow, column, 5, numcolumns); var data =range.getValues(); return data; } // シートからのデータを並び替える function convSheet(sheet) { var colStartIndex = 1; var rowNum = 1; var firstRange = sheet.getRange(1, 1, 1, sheet.getLastColumn()); var firstRowValues = firstRange.getValues(); var titleColumns = firstRowValues[0]; var lastRow = sheet.getLastRow(); var rowValues = []; for(var rowIndex=2; rowIndex<=lastRow; rowIndex++) { var colStartIndex = 1; var rowNum = 1; var range = sheet.getRange(rowIndex, colStartIndex, rowNum, sheet.getLastColumn()); var values = range.getValues(); rowValues.push(values[0]); } var jsonArray = []; for(var i=0; i<rowValues.length; i++) { var line = rowValues[i]; var json = new Object(); for(var j=0; j<titleColumns.length; j++) { json[titleColumns[j]] = line[j]; } jsonArray.push(json); } return jsonArray; }
// フロントエンドからのデータをシートへ書き込み function doPost(e){ var data = JSON.parse(e.postData.contents); var Time = new Date; var Total = data.total; var Deposit = data.deposit; var Set = data.set; var Pudding = data.pudding; var Jelly = data.jelly; var Cake = data.cake; var Coffee = data.coffee; var Milktea = data.milktea; var Straighttea = data.straighttea; var Drpepper = data.drpepper;
// シート取得 var ss = SpreadsheetApp.openByUrl(url); var sheetH = ss.getSheetByName("販売履歴シート"); // データ入力 sheetH.appendRow([Time, Total, Deposit, Set, Pudding, Jelly, Cake, Coffee, Milktea, Straighttea,Drpepper]); //レスポンス返し return ContentService.createTextOutput("POSTFIN!"); }

 これは、後に見つかったバグを修正したものです。

当時のやらかし

変数名を変更後に更新できていないとによるエラーを初日にやらかしました。

また、処理はきちんとされているがレスポンスがEroor!を出す問題も2日目に出てきていて当時も直すことができていませんでした。

......が、このブログを書くためにソースコードを見直していると出てきた違和感により発覚したバグ。

 

 

>>>break文が抜けている<<<

 

 

うわあああああああああああ▂▅▇█▓▒░(’ω’)░▒▓█▇▅▂ああああああああああああああ

先輩方申し訳ありません。これ本当に完成してるのかなとか言われていたのは知っていますが、データの取得はできています。

所詮プログラムもかじった程度の奴が先輩方すら忙しいとか面倒とかで触れなかった大掛かりな物に挑戦しようとして申し訳ありませんでした。

 参考にしたもの

【GAS】スプレッドシートのデータをJSON出力する関数をExecution APIで外部のNode.jsから実行する - Qiita

Google Apps Scriptの開発手法まとめ - Qiita

得たもの

今回の開発で得たものについて得たものが沢山ありました。

  • doGetやdoPostについて
  • レスポンスの重要さ
  • 看板方式を体感する事
  • 知識がある人を頼る事
  • 早めの行動
  • 仕事を増やしすぎない
  • 弊学の学園祭に過度な期待はしないこと
  • GitHubの便利さ

普段からMTGにいる人が仕事できるとは限らない事

今思いつくのはこれだけですがこの件で成長と自分の愚かさの理解ができました。

また、現在基本情報技術者試験の勉強をしていますが経験から用語の意味を理解しやすくなったことを実感しています。

挑戦はいいことだと思いますがリスクマネジメントも大事です。この経験を今後に活かしつつ程よく精神疲労を防いで2年に上がりたいと思います。

 

さて、次は17日のお楽しみです。

ゆるっと今年の活動を振り返りたいと思います。それでは!(o´・ω・`o)ノシ

電子部品屋さんで目を輝かせた話

辛い物って辛すぎると胃がびっくりするし、鼻水止まらなくなるんだね

どうも、その後は胃が暫く温かくなっていた猫さんです。

今日は公欠を取って秋葉原にチーム開発で使用する電子部品を調達しに行ってきました!

f:id:MI_SAN_CAT:20171122234557j:plain

今回パーツを調達してきたのは秋月電子さん(秋葉原店)

本日調達したパーツ

今現在必要であると思われるパーツをディスプレイを除いて

  • フォトリフレクタ
  • プッシュスイッチ
  • スライドスイッチ
  • ロータリーエンコーダ
  • 赤外線LED
  • ジャンパーワイヤー(オス・メス)

のスイッチ3種、センサやその他各種1つずつ確保完了!

パーツって見飽きないですね!ずーっとパーツ(主にスイッチ)を見ていたらのびあに拗ねられました(´・ω・`)

 

後は個人的に秋月電子さんから30秒くらいのところにあるマルツ 秋葉原でカバー付きスイッチ(ミサイルスイッチ)を買いました。

別に用途は決めてません。ただカチカチしたかっただけ()

固いので指の力が強くなりそうだなぁと思いつつこの記事を書いています。f:id:MI_SAN_CAT:20171123022140p:plain

来週の猫さんは?

Raspberry Piに触れます。

プログラムを書く以前の問題に躓きそうな気配がするけど自分で動かなきゃ駄目だと自分に叱っています。

既に慣れていない言語での開発は確定なので資料をいくつか読まなければね

おまけ

昼飯の辛い物で死んだ私を休めた後にのんびり歩いてみようとなって、たまたま選んだ方向にCEATECで変な部品作っているとかで記憶に残っていたマックエイトさんを見かけました。

私以外の同学年でCEATECに行ってたのは今回の開発チームの相方、のびあだけですので二人で大興奮してました(笑)

あのスタンドむっちゃ便利です。秋葉原CEATECも両方行ってよかったなf:id:MI_SAN_CAT:20171123024253j:plain

mi-neko-maple.hatenablog.com