Pokémon Trading Card Game Pocket 始めた
https://www.pokemontcgpocket.com/ja/
多分ポケモンカード世代ではあるんだけど、金払ってカード集めるの好きではないので全くやってこなかったしゲームボーイのは出た頃にやったことあったような気がするくらいで、今回のは課金しないでもできるっぽいので始めてみました。割と早めに飽きる気もするが…。
ブログです oq.la/++
https://www.pokemontcgpocket.com/ja/
多分ポケモンカード世代ではあるんだけど、金払ってカード集めるの好きではないので全くやってこなかったしゲームボーイのは出た頃にやったことあったような気がするくらいで、今回のは課金しないでもできるっぽいので始めてみました。割と早めに飽きる気もするが…。
https://oquno.com/log/eid4210.html
この靴がまたぼろぼろになりがちだったので、今週くらいから、買ってあった同タイプの革靴に履き替えてみている。そしたら当然のごとく靴擦れが発生し、踵に痛み&皮の破れが。仕組み的にはぴったりでない靴を履いてるのが悪いってことなんだろうか。でも本当にぴったりだと履くのも脱ぐのも困難だしただ硬いのが悪いんじゃないかと思ってるけど、靴替える度に靴擦れにやられたくない…。ということでスニーカーが人気な理由にようやく気付いた。
前から欲しかったのだけど、JavaScript書きたくなさすぎて遠のいていたのをChatGPTに厳しく指導をすることで実現できた。
https://x.oq.la/js/flickrembed.js
WriteFreelyはヘッダに投稿ボタンとかあってこのツールの位置固定しづらいので、(ボタンだけ)ドラッグできるようにしたのがわからせポイントです。まだいじる気がするけど、これをロードすればすべてのテキストエリアにFlickr埋め込み放題になる(はず)。サムネイルクリックするとembedコードとかがテキストエリアに入る。パクリ元ははてなブログのFlickr埋め込み機能です。Flickr無料プランの使い勝手悪くなってるので現在はあんま使われてなさそうな気はしている。あと合わせてGyazo埋め込みグリモンも書かせてみた
https://gist.github.com/oquno/2419d0ad137b8db208a8da232cf5f567
正直あんまり興味はないのだけれど、後年読み返したときにこんな時期だったなと思い出せる方が良いので何でも書いておこうという気持ちで書く。とはいっても特に感想というほどのものもなく。大体投票日前に見える時代になったので特に驚きもなく、京都はさらに驚きのないエリアでしたね。京都でいうと今回もバランスよく各党がバラけて議席を獲得しているものの特に接戦もなくおもしろみはなかった。市長選とか府知事選は開票時に事務所に行く気にもなるのだけれど、国政選挙だとあんまノらないですね。
BalatroのPlayストア版1500円ということで、SteamゲームはそのままAndroidで遊べるわけではなく別なので、モバイル課金の習慣のない自分としては渋っていたのけれど、定額課金とかで貯まったPlayポイントをPlayストアクレジットに変換して体感数百円に圧縮してごまかして買った。
というのも週末に電車移動の時間を潰したいという気持ちが高まったため。モバイル版は欲を言えば縦画面で遊びたいけど、ドラッグ?スワイプ?の選択UIが実装されててタッチで十分遊べるようになってた。というかモバイル版あればSteam版もSwitch版もいらない気がする(Switch版は買ってないけど)。
というのをGoogle Apps Scriptでやってみた。 これを定期的に実行すればGoogle Calendarで録画済番組が見れて便利かもしれないという試み。予約のカレンダーもあると便利かもしれない。
function updateEpgstation() {
var baseUrl = "https://epgstation.example.com";
var calId = "YOUR_CALENDAR_ID";
// BASIC 認証の場合
var account = "dankogai:kogaidan";
var calendar = CalendarApp.getCalendarById(calId);
var apiUrl = baseUrl + '/api/recorded?isHalfWidth=true';
var res = UrlFetchApp.fetch(apiUrl, {
'method': 'get',
'headers': {
'Authorization': Utilities.base64Encode(account),
}}
);
var reserves = JSON.parse(res.getContentText());
var events = [];
reserves.records.forEach(function(record) {
var event = {};
event.title = record.name;
event.start = new Date(record.startAt);
event.end = new Date(record.endAt);
event.description = record.description + "\n" + record.extended +
"\n" + baseUrl + "/#/recorded/detail/" + record.id;
events.push(event);
});
mergeAndUpdate(calendar, events);
}
// カレンダーの既存の予定にマージ
function mergeAndUpdate(calendar, newSchedules) {
var range = getScheduleRange(newSchedules)
Logger.log("range: "+ range[0] + "~" + range[1])
var currentEvents = calendar.getEvents(range[0], range[1])
var dontAdd = []
var done = []
currentEvents.forEach(function(event){
var line = event.getStartTime().getTime() + event.getTitle()
if (done.indexOf(line) > -1)
{
Logger.log("delete duplicate event" + event.getTitle())
event.deleteEvent()
return
}
done.push(line)
var exists = false
newSchedules.forEach(function(schedule){
if (
schedule.start.getTime() < new Date(2010, 1, 1).getTime() ||
schedule.title == event.getTitle() &&
schedule.start.getTime() == event.getStartTime().getTime() &&
schedule.end.getTime() == event.getEndTime().getTime() &&
schedule.description.length == event.getDescription().length/* &&
schedule.location == event.getLocation()*/)
{
if (dontAdd.indexOf(schedule) > -1)
{
Logger.log("duplicate " + schedule.title)
event.deleteEvent()
}
else
{
dontAdd.push(schedule)
Logger.log("already created " + schedule.title)
}
exists = true
return
}
})
if (!exists && event.getStartTime().getTime() > range[0].getTime())
{
Logger.log("delete " + event.getTitle())
event.deleteEvent()
}
});
// 新しいスケジュールを追加
newSchedules.forEach(function(schedule){
if (schedule != null && dontAdd.indexOf(schedule) < 0)
{
Logger.log("create " + schedule.title)
if ("allDay" in schedule && schedule.allDay)
{
var createAllDay = calendar.createAllDayEvent(schedule.title, schedule.start,
{ description: schedule.description, location: schedule.location})
}
else
{
var created = calendar.createEvent(schedule.title,
schedule.start, schedule.end, { description: schedule.description, location: schedule.location})
}
Utilities.sleep(100)
}
});
}
// どの期間のカレンダー予定を取得すればいいかを判定
function getScheduleRange(schedules) {
var start
var end
schedules.forEach(function(schedule){
if (start == null || schedule.start < start)
{
start = schedule.start
}
if (end == null || end < schedule.end)
{
end = schedule.end
}
})
return [start, end]
}