Created
March 14, 2016 10:11
-
-
Save dolpen/5c1fce0fc2f500ba9de1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.onload = function () { | |
var script = document.createElement("script"); | |
var code = function () { | |
var uiController = [ | |
' <div style="text-align:center;">' | |
, ' <div class="ui icon buttons" style="text-align:left;margin:1rem;">' | |
, ' <button id="plus_select_alpha" class="ui large orange button" style="width: 150px;">Alpha</button>' | |
, ' <button id="plus_select_neutral" class="ui large button" style="width: 70px;"><i class="unmute icon"></i></button>' | |
, ' <button id="plus_select_bravo" class="ui large violet button" style="width: 150px;">Bravo</button>' | |
, ' </div>' | |
, ' <div class="ui icon buttons" style="text-align:left;margin:1rem;">' | |
, ' <button id="po_po" class="ui large green button" style="width: 70px;">ポ</button>' | |
, ' <button id="po_ra" class="ui large red button" style="width: 70px;">ラ</button>' | |
, ' <button id="po_unpo" class="ui large button" style="width: 70px;">~</button>' | |
, ' </div>' | |
, ' </div>' | |
, ' <div style="text-align:center;">' | |
, ' <div class="ui icon buttons" style="text-align:left;margin:1rem;">' | |
, ' <button id="po_tpr" class="ui large button" style="width: 70px;">タプレ</button>' | |
, ' </div>' | |
, ' </div>' | |
, ' <div style="text-align:center;">' | |
, ' <div class="ui segments" style="margin:0 auto;text-align:left;max-width:520px;">' | |
, ' <div id="plus_chat_log" class="ui minimal comments segment" style="height:300px;overflow-y:scroll;">' | |
, ' </div>' | |
, ' <div class="ui segment fluid action input">' | |
, ' <input id="plus_chat_input" type="text" placeholder="メッセージを送信">' | |
, ' <button id="plus_chat_submit" class="ui submit button">送信</button>' | |
, ' </div>' | |
, ' </div>' | |
, ' </div>' | |
, '<div class="ui divider"></div>'].join("\n"); | |
// endpoints | |
var Endpoints = { | |
fes: "https://s3-ap-northeast-1.amazonaws.com/splatoon-data.nintendo.net/fes_info.json", | |
term: "https://splatoon.ink/schedule.json" | |
}; | |
var Period = function (begin, end) { | |
this.beginAt = begin; | |
this.endAt = end; | |
}; | |
Period.prototype = { | |
getBeginLabel: function (now, label) { | |
return label + "開始" + (new TimeDiffer(now, this.beginAt).toString()); | |
}, | |
getEndLabel: function (now, label) { | |
return label + "終了" + (new TimeDiffer(now, this.endAt).toString()); | |
}, | |
getState: function (now) { | |
if (now.getTime() < this.beginAt.getTime()) { | |
return 0; | |
} else if (now.getTime() > this.endAt.getTime()) { | |
return -1; | |
} | |
return 1; | |
}, | |
getStateLabel: function () { | |
return ["終了", "告知", "開催中"][this.state + 1]; | |
}, | |
getProgress: function (now) { | |
var min = this.beginAt.getTime(); | |
var max = this.endAt.getTime(); | |
var prog = now.getTime(); | |
return Math.max(Math.min(Math.floor(100 * ( prog - min) / (max - min)), 100), 0); | |
} | |
}; | |
var Stages = function (label) { | |
this.label = label; | |
this.stages = []; | |
}; | |
Stages.prototype = { | |
setStagesFromRegular: function (regular) { | |
for (var i = 0; i < regular.maps.length; i++) { | |
this.stages.push(regular.maps[i]["nameJP"]); | |
} | |
return this; | |
}, | |
setStagesFromRanked: function (ranked) { | |
for (var i = 0; i < ranked.maps.length; i++) { | |
this.stages.push(ranked.maps[i]["nameJP"]); | |
} | |
return this; | |
}, | |
setStagesFromFes: function (fes) { | |
for (var i = 0; i < fes["fes_stages"].length; i++) { | |
this.stages.push(fes["fes_stages"][i]["name"]); | |
} | |
return this; | |
}, | |
getStageLabel: function () { | |
return "【" + this.label + "】 " + this.stages.join(", "); | |
} | |
}; | |
var Info = function () { | |
this.period = null; | |
this.regular = null; | |
this.ranked = null; | |
this.fes = null; | |
this.label = ""; | |
}; | |
Info.prototype = { | |
setInfoFromFes: function (json) { | |
var info = json; | |
this.period = new Period( | |
new Date(info["datetime_fes_begin"].replace(/-/g, '/')), | |
new Date(info["datetime_fes_end"].replace(/-/g, '/')) | |
); | |
this.fes = new Stages("フェス").setStagesFromFes(info); | |
this.label = "フェス"; | |
return this; | |
}, | |
setInfoFromNormal: function (json) { | |
var info = json, term = null, next = null; | |
var now_time = (new Date()).getTime(); | |
var temp_offset = 0;//60*60*1000; // APIずれてる時がある | |
for (var i = 0; i < info.schedule.length; i++) { | |
info.schedule[i].startTime += temp_offset; | |
info.schedule[i].endTime += temp_offset; | |
if (info.schedule[i].startTime <= now_time && info.schedule[i].endTime >= now_time) { | |
term = info.schedule[i]; | |
if (i + 1 < info.schedule.length)next = info.schedule[i + 1]; | |
} | |
} | |
if (term == null) return this; | |
this.period = new Period( | |
new Date(term.startTime), | |
new Date(term.endTime) | |
); | |
this.regular = new Stages("レギュラー").setStagesFromRegular(term.regular); | |
this.ranked = new Stages(term.ranked["rulesJP"]).setStagesFromRanked(term.ranked); | |
this.label = "ピリオド"; | |
if (next != null) { | |
this.nextRegular = new Stages("レギュラー").setStagesFromRegular(next.regular); | |
this.nextRanked = new Stages(next.ranked["rulesJP"]).setStagesFromRanked(next.ranked); | |
} | |
return this; | |
}, | |
getStageLabel: function () { | |
var r = "<今>"; | |
if (this.fes != null)r += this.fes.getStageLabel(); | |
if (this.regular != null)r += this.regular.getStageLabel(); | |
if (this.ranked != null)r += " " + this.ranked.getStageLabel(); | |
return r; | |
}, | |
getNextStageLabel: function () { | |
var r = "<次>"; | |
if (this.nextRegular != null)r += "" + this.nextRegular.getStageLabel(); | |
if (this.nextRanked != null)r += " " + this.nextRanked.getStageLabel(); | |
return r; | |
}, | |
getProgress: function (now) { | |
return this.period.getProgress(now); | |
}, | |
getEndLabel: function (now) { | |
return this.period.getEndLabel(now, this.label); | |
}, | |
isEnd: function (now) { | |
return this.period.getState(now) < 0; | |
} | |
}; | |
var Ui = function () { | |
}; | |
Ui.prototype = { | |
getCard: function (easyrtcid) { | |
if (easyrtcid == easyrtc.myEasyrtcid) return $("div.card:first"); | |
return $(".card:not(:first)>div.content>div:contains('" + easyrtc.idToName(id) + "')").parent().parent(); | |
}, | |
getHeader: function ($card) { | |
var $header = $card.children(".content").children(".header"); | |
if ($header.children(".plus_team").length == 0) { | |
$header.append($("<div></div>", {class: "plus_team ui label", css: {display: "none"}})); | |
} | |
if ($header.children(".popopo").length == 0) { | |
$header.append($("<div></div>", {class: "popopo ui label red", css: {display: "none"}})); | |
} | |
return $header; | |
}, | |
updateIcon: function (easyrtcid, message, color) { | |
var $card = this.getCard(easyrtcid); | |
if ($card == null) return; | |
var $header = this.getHeader($card); | |
var $label = $header.children(".popopo"); | |
if (message == null || message == "") { | |
$label.removeClass().addClass("popopo ui label ").css("display", "none").text(""); | |
} else { | |
$label.removeClass().addClass("popopo ui label " + color).css("display", "inline-block").text(message); | |
} | |
}, | |
updateTeam: function (easyrtcid, team) { | |
var $card = this.getCard(easyrtcid); | |
if ($card == null) return; | |
var $header = this.getHeader($card); | |
var $label = $header.children(".plus_team"); | |
switch (team) { | |
case "alpha": | |
$label.removeClass("violet").addClass("orange").css("display", "inline-block").text("Alpha"); | |
break; | |
case "bravo": | |
$label.removeClass("orange").addClass("violet").css("display", "inline-block").text("Bravo"); | |
break; | |
case "neutral": | |
$label.removeClass("violet").removeClass("orange").css("display", "none"); | |
break; | |
} | |
}, | |
muteByTeam: function (myTeam) { | |
if (myTeam == "neutral") { | |
$(".card:not(:first)").children("div.buttons").children("button.green:enabled").click(); | |
return; | |
} | |
var friend = myTeam == "alpha" ? "orange" : "violet"; | |
var enemy = myTeam == "alpha" ? "violet" : "orange"; | |
$(".card:not(:first):has(.plus_team):has(." + enemy + ")").children("div.buttons").children("button.red:enabled").click(); | |
$(".card:not(:first):has(.plus_team):has(." + friend + ")").children("div.buttons").children("button.green:enabled").click(); | |
} | |
}; | |
var ui = new Ui(); | |
var Plus = function () { | |
}; | |
Plus.prototype = { | |
getEasyrtcIdList: function () { | |
return $("audio[id^='stream_']").map(function () { | |
return $(this).attr("id").replace("stream_", ""); | |
}); | |
}, | |
sendUpdateTeam: function (team) { | |
var idList = this.getEasyrtcIdList(); | |
for (var i = 0; i < idList.length; i++) { | |
easyrtc.sendData(idList[i], "plus_update_team", {team: team}); | |
} | |
}, | |
sendIcon: function (message, color) { | |
var idList = this.getEasyrtcIdList(); | |
for (var i = 0; i < idList.length; i++) { | |
easyrtc.sendData(idList[i], "po_icon", {message: message, color: color}); | |
} | |
}, | |
sendNeutralAll: function () { | |
var idList = this.getEasyrtcIdList(); | |
for (var i = 0; i < idList.length; i++) { | |
easyrtc.sendData(idList[i], "plus_neutral_all", {}); | |
} | |
}, | |
recvUpdateTeam: function (id, team) { | |
ui.updateTeam(id, team); | |
}, | |
recvNeutralAll: function (id) { | |
this.recvUpdateTeam(id, "neutral"); | |
ui.muteByTeam("neutral"); | |
}, | |
recvIcon: function (id, message, color) { | |
ui.updateIcon(id, message, color); | |
}, | |
sendChatMessage: function (msg) { | |
if (msg.length == 0) return; | |
var idList = this.getEasyrtcIdList(); | |
for (var i = 0; i < idList.length; i++) { | |
easyrtc.sendData(idList[i], "plus_chat_msg", {name: easyrtc.username, msg: msg}); | |
} | |
this.recvChatMessage(easyrtc.username, msg); | |
}, | |
recvChatMessage: function (name, msg) { | |
var nowDate = new Date(); | |
var comment = $("<div></div>", {class: "comment"}).append( | |
$("<div></div>", {class: "content"}).append( | |
$("<span></span>", {class: "auther"}).text(name)).append( | |
$("<div></div>", {class: "metadata"}).append( | |
$("<span></span>", {class: "date"}).text(nowDate.getHours() + ":" + nowDate.getMinutes()) | |
) | |
)).append( | |
$("<div></div>", {class: "text"}).text(msg) | |
); | |
var log = $("#plus_chat_log"); | |
var is_scroll = $("#plus_chat_log>div.comment").length > 0 && $("#plus_chat_log>div.comment:last").position().top - $(log).height() < 0; | |
log.append(comment); | |
if (is_scroll) { | |
$(log).scrollTop($(log).scrollTop() + $("#plus_chat_log>div.comment:last").position().top); | |
} | |
} | |
}; | |
var plus = new Plus(); | |
function plus_addController() { | |
$(".divider:first").after(uiController); | |
} | |
function plus_addControllerEvent() { | |
$("#plus_chat_input").keydown(function (e) { | |
if (e.which == 13) $("#plus_chat_submit").click(); | |
}); | |
$("#plus_chat_submit").click(function () { | |
plus.sendChatMessage($("#plus_chat_input").val()); | |
$("#plus_chat_input").val(""); | |
}); | |
$("#plus_select_alpha").click(function () { | |
ui.updateTeam(easyrtc.myEasyrtcid, "alpha"); | |
plus.sendUpdateTeam("alpha"); | |
ui.muteByTeam("alpha"); | |
}); | |
$("#plus_select_bravo").click(function () { | |
ui.updateTeam(easyrtc.myEasyrtcid, "bravo"); | |
plus.sendUpdateTeam("bravo"); | |
ui.muteByTeam("bravo"); | |
}); | |
$("#plus_select_neutral").click(function () { | |
ui.updateTeam(easyrtc.myEasyrtcid, "neutral"); | |
plus.sendNeutralAll(); | |
plus.sendUpdateTeam("neutral"); | |
ui.muteByTeam("neutral"); | |
}); | |
$("#po_po").click(function () { | |
ui.updateIcon(easyrtc.myEasyrtcid, "ポ", "green"); | |
plus.sendIcon("ポ", "green"); | |
}); | |
$("#po_ra").click(function () { | |
ui.updateIcon(easyrtc.myEasyrtcid, "ラ", "red"); | |
plus.sendIcon("ラ", "red"); | |
}); | |
$("#po_unpo").click(function () { | |
ui.updateIcon(easyrtc.myEasyrtcid, "", ""); | |
plus.sendIcon("", ""); | |
}); | |
$("#po_tpr").click(function () { | |
var q = "?" + parseInt((new Date) / 1000); | |
$.getJSON(Endpoints.fes + q, function (json) { | |
var now = new Date(); | |
var fes = new Info().setInfoFromFes(json); | |
if (fes.period.getState(now) == 1) { | |
var _info = fes; | |
plus.sendChatMessage( | |
(_info.getStageLabel()).replace(/\n/g, ', ') | |
); | |
return; | |
} | |
// Endpoints.term のAPIがフェス中は壊れるので別で取得 | |
$.getJSON(Endpoints.term + q, function (json) { | |
var _info = new Info().setInfoFromNormal(json); | |
plus.sendChatMessage( | |
(_info.getStageLabel() + ' (' + _info.getNextStageLabel() + ')').replace(/\n/g, ', ') | |
); | |
}); | |
}); | |
}); | |
} | |
function plus_addEasyrtcEvent() { | |
easyrtc.setPeerListener(function (easyrtcid, messageType, content) { | |
if (messageType == "plus_chat_msg") { | |
plus.recvChatMessage(content.name, content.msg); | |
} | |
}, "plus_chat_msg"); | |
easyrtc.setPeerListener(function (easyrtcid, messageType, content) { | |
if (messageType == "plus_update_team") { | |
plus.recvUpdateTeam(easyrtcid, content.team); | |
} | |
}, "plus_update_team"); | |
easyrtc.setPeerListener(function (easyrtcid, messageType, content) { | |
if (messageType == "plus_neutral_all") { | |
plus.recvNeutralAll(easyrtcid); | |
ui.updateTeam(easyrtc.myEasyrtcid, "neutral"); | |
plus.sendUpdateTeam("neutral"); | |
} | |
}, "plus_neutral_all"); | |
easyrtc.setPeerListener(function (easyrtcid, messageType, content) { | |
if (messageType == "po_po") { | |
plus.recvPo(easyrtcid, content.message); | |
} | |
}, "po_po"); | |
} | |
function plus_checkAndInit() { | |
if (typeof( easyrtc ) != "undefined" && Object.keys(easyrtc.getRoomsJoined()).length > 0) { | |
plus_addController(); | |
plus_addControllerEvent(); | |
plus_addEasyrtcEvent(); | |
return; | |
} | |
setTimeout(plus_checkAndInit, 1000); | |
} | |
setTimeout(plus_checkAndInit, 1000); | |
}; | |
script.innerHTML = "(" + code.toString() + ")()"; | |
document.head.appendChild(script); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment