寝坊検知&遅刻の言い訳提案システム #2
お疲れ様です。高橋です。
昨日作った遅刻の言い訳提案システムですが、Tweetの採取(search)と言い訳の提案(reply)、提案内容のA/Bテスト、寝坊した人の反応(ネガ/ポジ)を踏まえ、色々な知見を得ることが出来ました。
わかった事
- 土日の寝坊者は、遊び関連イベントへの遅刻が多い
- 個人に対するピンポイントなReplyなので、面白系の提案が来たらリツイートする率が高い
- いかにも自動的に生成した風なReplyのほうがポジ反応
- 10分前以上の「寝坊した」に提案するとネガ反応
- まるっきり的外れな提案するとネガ反応
- ドンピシャな提案するとポジ反応
対応した事
- 土日は完全対象外としました。
- 面白系をもっと増やそうと思います。
- もう少し「人間っぽい」パターンと「機械っぽい」パターンを継続し、ネガポジを見極めます。
- 毎分、1分以内の物にしか提案させないようにしました。
- これはもう、面白系の率を増やすしか無いかと思います。
- その人の過去Tweetの内容やTweet時間帯、プロフィール内容、Follower/Followの人たちを自動分析した上で出せれば究極。いつか、余力があったら。
コード
テーブル構造は最終的に下記の通り。
+------------+----------+------+-----+---------+-------+ | Field | +------------+----------+------+-----+---------+-------+ | tweet_id | TwitterのStatusID | user_id | TwitterのuserのID | user_name | Twitterのscreen_name | tweet_date | 寝坊Tweetの日時 | reply_date | 言い訳提案Replyの日時 | tweet | 寝坊Tweetの文言 | reply | 言い訳提案Replyの文言 +------------+----------+------+-----+---------+-------+
cron的に 「* 7-8 * * 1-5」(月曜~金曜 7時~8時 毎分)として動かすコードは下記の通り。
<?php
// initialize
require 'twitteroauth/autoload.php';
use Abraham\TwitterOAuth\TwitterOAuth;
// configure
$consumerKey = 'consumer keyを入れて下さい';
$consumerSecret = 'consumer secretを入れて下さい';
$accessToken = 'access tokenを入れて下さい';
$accessTokenSecret = 'access token secretを入れて下さい';
$db_host = 'dbのhost';
$db_user = 'dbのuser';
$db_pass = 'dbのpass';
$db_name = 'dbのname';
//$reply_tweet = 'もしかして寝坊しましたか?相手が納得出来る遅刻の言い訳を作るAndroidアプリは http://curious4dev.mydns.jp/ewake/redirect.php?tid=';
$reply_tweet = array('寝坊を検知しました。遅刻の言い訳を提案します。','もしかして寝坊しましたか?勝手に遅刻の言い訳を考えました!');
$sql_select = 'select count(1) as count from ewakeLog where date_add(reply_date, interval 24 hour) > now() and user_id = :user_id;';
$sql_insert = 'insert into ewakeLog (tweet_id, user_id, user_name, tweet, reply, tweet_date, reply_date) values(:tweet_id, :user_id, :user_name, :tweet, :reply, :tweet_date, now());';
// load file
$ewake_text = file('ewake.txt');
// conenct to mysql
$pdo = new PDO("mysql:dbname=" . $db_name, $db_user, $db_pass, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET `utf8`"));
// create Twitter object and search from tweets
$twObj = new TwitterOAuth($consumerKey, $consumerSecret, $accessToken, $accessTokenSecret);
$search_key = "寝坊した";
$options = array('q' => $search_key, 'count' => '100', 'lang' => 'ja');
$json = $twObj->get('search/tweets', $options);
// check tweets
foreach ($json->statuses as $result) {
// get parameters from tweet
$tweet_id = $result->id_str;
$user_id = $result->user->id_str;
$tweet = $result->text;
$user_name = $result->user->screen_name;
$created_at = $result->created_at;
// delete \n
$tweet = str_replace("\r\n", '', $tweet);
$tweet = str_replace("\n", '', $tweet);
// is Reply?
if (mb_substr_count($tweet, '@') > 0 ) {
$isReply = true;
} else {
$isReply = false;
}
// is RT?
if (strpos($tweet, "RT") ==false) {
$isRT = false;
} else {
$isRT = true;
}
// is寝坊した?
if (mb_strpos($tweet, $search_key) ==false) {
$isNebou = false;
} else {
$isNebou = tue;
}
// with HashTag?
if (strpos($tweet, "#") == false) {
$isHashTag = false;
} else {
$isHashTag = true;
}
// is Fresh Tweet?(less than 1 minute)
$now = strtotime("-1 min");
$check = strtotime($created_at);
if($now <= $check) {
$isFresh = true;
} else {
$isFresh = false;
}
// check already send last 24 hour
$statement = $pdo->prepare($sql_select);
$statement->bindValue(':user_id', $user_id, PDO::PARAM_INT);
$statement->execute();
$count = 0;
if ($row = $statement->fetch()) $count = $row['count'];
if ($count == 0) {
$isAlreadySend = false;
} else {
$isAlreadySend = true;
}
// send reply when not reply and not RT and not send
if ($isReply == false && $isRT == false && $isAlreadySend == false && $isHashTag == false && $isFresh == true && $isNebou == true) {
// send reply
$tmp_text = $ewake_text[mt_rand(0,count($ewake_text)-1)];
$tmp_text = str_replace("\r",'',$tmp_text);
$tmp_text = str_replace("\n",'',$tmp_text);
$tmp_text = str_replace("\r\n",'',$tmp_text);
$ewake = $reply_tweet[mt_rand(0,1)] . '「' . $tmp_text .'」';
$reply = '@' . $user_name. ' '. $ewake;
$reply_json = $twObj -> post('statuses/update', ['status'=>$reply, 'in_reply_to_status_id'=>$tweet_id]);
// insert to log when success
$created_at = date('Y-m-d H:i:s', strtotime($created_at));
$statement = $pdo->prepare($sql_insert);
$statement->bindParam(':tweet_id', $tweet_id, PDO::PARAM_STR);
$statement->bindParam(':user_id', $user_id, PDO::PARAM_STR);
$statement->bindParam(':tweet', $tweet, PDO::PARAM_STR);
$statement->bindParam(':reply', $reply, PDO::PARAM_STR);
$statement->bindParam(':tweet_date', $created_at, PDO::PARAM_STR);
$statement->bindParam(':user_name', $user_name, PDO::PARAM_STR);
$statement->execute();
}
}
?>
コードの中で、A/Bテスト用パラメータとして、人間っぽいのと機械っぽいのを設定しているのが下記の部分で、
$reply_tweet = array('寝坊を検知しました。遅刻の言い訳を提案します。','もしかして寝坊しましたか?勝手に遅刻の言い訳を考えました!');
↑の2つのどっちかをランダムに冒頭部分で使い、reply文言を生成してます。
$ewake = $reply_tweet[mt_rand(0,1)] . '「' . $tmp_text .'」';
あとは、
- 寝坊ツイートの中に @ が入っていたら提案しない
- 寝坊ツイートの中に # が入っていても提案しない
- RTされた寝坊ツイートにも提案しない
- 本当に「寝坊した」が含まれていないと提案しない
- 取得時点から1分以内のものにしか提案しない
- 24時間以内に同一寝坊者に再提案しない
という条件を定めています。
採用事例
採用してくれると、ちょっと嬉しい。
しかし、たまに「本当に人が送ってくれている」と誤認されている方がいらっしゃるようです。丁寧な御礼のリプライを頂いた事例が3例あり、いずれも年齢層若いような感じでした。
ネガにしろポジにしろ、反応がすぐに返ってくるから楽しいです。
もう、アプリじゃなくても良いんじゃないか?という考えが一瞬だけ頭をよぎりましたが、それは考えちゃダメだな、と。
明日の朝7:00~08:59がいよいよ平日の本番となります。
以上、よろしくお願い致します。
関連記事
-
-
Twitter上に広がる寝坊市場について
お疲れ様です。高橋です。 遅刻の言い訳アプリ 初週DL数 2/26頃にリリースし …
-
-
遅刻の言い訳アプリのDL数が急増した原因
お疲れ様です。高橋です。 ふとgooglePlayのダウンロード状況を見たら、言 …
-
-
街頭インタビュー 入力UI実装
お疲れ様です。高橋です。 今日は文字入力UI及び、背景人物の切り替え機能を実装し …
-
-
TwitterアナリティクスからCSVがダウンロード出来ない
お疲れ様です。高橋です。 TwitterアナリティクスのCSV 遅刻の言い訳提案 …
-
-
androidアプリから総務省APIをコールしてみる
お疲れ様です。高橋です。 androidアプリから総務省APIをコールする事に成 …
-
-
歌詞生成アプリ「カナかな?」の動詞をチューニングしてみた。
お疲れ様です。高橋です。 昨日はサーバ周りに熱中してしまってクライアント側を全く …
-
-
「カナかな?」の2週間分のダウンロード数
お疲れ様です。高橋です。 本日の貴重な帰宅後の時間は、妻からの「なんとかっていう …
-
-
「遅刻の言い訳」実機デバッグ結果
お疲れ様です。高橋です。 本日、Androidを持っている同僚にお願いして、実機 …
-
-
遅刻の言い訳提案システムとウコンの力
お疲れ様です。高橋です。 現在稼働を続けている遅刻の言い訳提案システムは、改めて …
-
-
遅刻の言い訳提案システム 稼働三日目 ~大失敗~
お疲れ様です。高橋です。 三日目を迎えた遅刻の言い訳提案システムですが、重大なバ …

