LoginSignup
5
1

More than 1 year has passed since last update.

彼女の怒りを早急に鎮火。むしろ怒りを遊びに転換したい。〜obnizで早押しゲームつくり〜

Last updated at Posted at 2022-12-23

続・彼女のブチギレ案件

どうもこんにちは。
以前、トイレの蓋を閉め忘れて彼女にブチギレられたので、obnizでアラート機能をつくった者です。

その後、トイレの蓋の閉め忘れはなくなり、トイレ文脈で彼女にキレられることはなくなりました。
一方で、これは根本的な解決ではありません。
彼女がブチギレる火種は生活の中に溢れているのです。
最近だと、こんな事象が発生し、ブチギレられてしまいました。

  • 氷結とスルメイカの食べ残しを机に放置してブチギレられたり
  • プレゼントでもらった財布をタクシーに置き忘れてブチギレられたり

毎度毎度、事象に対して対策をあてていってもキリがありません。
なので、今回は彼女のブチギレに対して根本的な解決をはかりました。

彼女の怒りの鎮火作業は「業務」

僕にとって、彼女の怒りを鎮火する行為は「業務」です。
鎮火作業において最も重要なことは、炎上する前に、火種を消すことです。
炎上してしまったら最後、取り返しがつかないことになってしまうからです。
 
炎上防止において必要な要件は二つ(サービスの保守運用みたいですね。。。)

  • 怒りを漏れなく検知すること
  • 怒りを検知したら早急に対応すること。

とはいえ、僕は普段仕事をしている時は、あまりスマホの通知を見ません。
そして、彼女のブチギレを見逃してしまうことが多々あります。
なので、自宅で作業をしていても、彼女がブチギレた際は、ひと目で把握できる・対応できることが重要になります。

「業務」を「遊び」に変えられないのか?

ずっと業務・業務言っていますが、どうしても「やらされてる感」が出てしまいます。
僕としてはテンションが下がってしまいますし、彼女にとっても誠意が伝わりません。
なので、今回は怒りの鎮火作業を、「遊び」に転換できないかと考えました。
image.png
普段の鎮火作業を、怒りが発生してから対応するまでの早押しタイムアタックにしてみたらどうでしょうか?
僕としては、スコアを伸ばしたいというゲーム性が生まれるのでテンションが上がります。
そして、良いスコアが出れば、対応の早さに彼女は誠実さを感じてくれるはずです。
お互いにとってWIN-WINの構造。完璧なソリューションとなるはずです。

イメージムービー

早速ですがプロダクトの映像をどうぞ

プロダクトの詳細

■よしだの家編:obniz

  • 彼女がブチギレるとLEDディスプレイに警告メッセージが表示される
  • ボタンを押すとディスプレイ表示〜ボタン押しまでの時間を計測して結果をディスプレイに表示する

完成デモ

■彼女の家編:LINE bot

  • ブチギレたらLINE botの「よしだじゅんやにブチギレ」を選択
  • よしだがボタンを押すと、結果タイムをプッシュメッセージで受け取る
  • 結果タイムだけではなく、botがよしだのフォローを入れてくれる(えらい)

完成デモ

使ったもの

  • obniz・・救世主
     
  • マトリクスLED
    彼女がブチギレた際によしだ宅のディスプレイに警告メッセージを表示する
     
  • JoyStick
    警告メッセージ表示後、ボタン押す。所要時間を計測
     
  • 愛するということ
    LEDの台座(めちゃくちゃサイズピッタリだった)
    「能動的に愛すること」の重要性を説くフロム先生の名著

サンプルコード

クリックで表示
anger.js
const Obniz = require('obniz');
const obniz = new Obniz('********');

let finalTime = 0;

// obnizと接続確立したとき
obniz.onconnect = async () => {

    obniz.display.clear();
    obniz.display.print('obniz Ready');
}
// ディスプレイを表示する
const matrixgo = async () => {
    // マトリクスLED
    const matrix = obniz.wired("MatrixLED_MAX7219", {
        vcc:11,
        gnd: 10,
        din: 9,
        cs: 8,
        clk: 7
        });
        matrix.init(8*4, 8);
        matrix.brightness(15);
        
        const ctx = obniz.util.createCanvasContext(matrix.width, matrix.height);
        
        let x = matrix.width;
    
        obniz.repeat(async function() {
    
            ctx.fillStyle = "black";
            ctx.fillRect(0, 0, matrix.width, matrix.height);
            ctx.fillStyle = "white";
            ctx.font = "10px sans-serif";
            ctx.fillText("ブチギレチュウ ブチギレチュウ タダチニ スイッチオセ",x, 7);
    
            x--;
            
            matrix.draw(ctx);
            }, 1000 / 80);
    }

//ボタンを使って早押し
const button = async (event,startTime) => {

    const joystick = obniz.wired("JoyStick", {gnd:4, sw:0, y:1, x:2, vcc:3});
    joystick.onchangesw = function(pressed){
        //ボタンが押されたらディスプレイの表示を変更
        if(pressed){
            const endTime = new Date();
            finalTime = Math.floor(endTime - startTime);
            obniz.repeat(async function() {

                matrix2.clear();
                const ctx2 = obniz.util.createCanvasContext(matrix2.width, matrix2.height);
                ctx2.fillStyle = "black";
                ctx2.fillRect(0, 0, matrix2.width, matrix2.height);
                ctx2.fillStyle = "white";
                ctx2.font = "10px sans-serif";
                ctx2.fillText(finalTime/1000, 0, 7);

                matrix2.draw(ctx2);
            }, 1000 / 40);  

            //LINE botに計測時間をプッシュメッセージ
            console.log(finalTime);
            client.pushMessage(event.source.userId, {
                type: 'text',
                text: `結果:${finalTime/1000}秒です! \n 早い!強い!誠実!!!!!`,
            });
        }
    }
 };

 


// ########################################
//          LINEBot イベント処理部分
// ########################################
const config = {
    channelSecret: 'ef1822a6767e72e7e39ebd259d71c48f',
    channelAccessToken: '8eSJERvh0U0NpNeXdWp+68VI8psc4pO4y6yIVI8nIsHV/fOSYCCkv/OI8yZCfQB5cudmb3sO8zLMZTJywu1KDZoWplN4c83udo4plQL0S42xogNiTrV6qvxLmx4uMuvQ8rkRqMQajCy6BVH+51lPwgdB04t89/1O/w1cDnyilFU='    
};
const line = require('@line/bot-sdk');
const client = new line.Client(config);
// ExpressからMessaging APIイベントを渡されて処理するところ
const handleEvent = async (event) => {
    // テキストメッセージ以外を受信したときは何も行わずresolveを返す
    if (event.type !== 'message' || event.message.type !== 'text') {
        return Promise.resolve(null);
    }
    // テキストメッセージを受信したとき
    //「ブチギレてます」と言われたとき
    if (event.message.text === 'ブチギレてます') {
        // アラートかけますね!メッセージを「リプライ」で先に返す
        await client.replyMessage(event.replyToken, {
            type: 'text',
            text: 'よしだじゅんやにアラートをかけますね!!!'
        });
        //タイマーを計測開始
        const startTime = new Date();
        //ディスプレイとボタンを呼び出し
        await matrixgo();
        button(event,startTime);

        

  
    }else{
        // メッセージの中身が「ブチギレてます」以外だったとき
        client.replyMessage(event.replyToken, {
            type: 'text',
            text: 'メニューのボタンを押してね'
        });
    }
    // resolveを返す
    return Promise.resolve(null);
}


// ########################################
//          Expressサーバー部分
// ########################################
const express = require('express');
const PORT = process.env.PORT || 3000;
const app = express();
// 「(サーバーURL)/webhook」にアクセス(LINEサーバーからのWebhook)があったとき
app.post('/webhook', line.middleware(config), (req, res) => {
    // 受信したイベントをターミナルに表示
    console.log(req.body.events);
    // イベントをhandleEventに渡して1つずつ処理
    Promise.all(
        req.body.events.map(handleEvent)
    ).then(
        result => res.json(result)
    );
});
// PORT番号のポートでサーバーを開始
app.listen(PORT);
console.log('express runnning: PORT =', PORT);

彼女に使ってもらった結果

こんな感じで新たな火種を生み出してしまいましたが、なんだかんだ喜んでくれました。
今後も「早急!強い!誠実!!!」で謝罪していきます。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1