Last active
February 3, 2024 14:15
-
-
Save derianpt/42a954131ca6f1d6d3f29436d1b5c847 to your computer and use it in GitHub Desktop.
activesg badminton booking scripts
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
// ==UserScript== | |
// @name activesg - single court for 2 hrs | |
// @namespace blah | |
// @version 0.6.5 | |
// @description activesg court booking | |
// @match https://members.myactivesg.com/* | |
// @copyright 2017+, naresh,Gavin,Kent | |
// @require http://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js | |
// ==/UserScript== | |
//StartTime: in 24H format and must >= 10 | |
//CourtPrecedence: higher index has higher precedence | |
//var cfg = {Venue:"Bukit Gombak Sports Hall", StartTime:11, MaxStartTime:11}; | |
var cfg = { Venue: "Delta Sports Hall", StartTime: 18, MaxStartTime: 19 }; | |
//var cfg = {Venue:"Jurong East Sports Hall", StartTime:18, MaxStartTime:18}; | |
//var cfg = {Venue:"Bukit View Secondary School Hall", StartTime:12, MaxStartTime:20}; | |
var venuePrefs = {}; | |
venuePrefs['Delta Sports Hall'] = { CourtPrecedence: [1, 5, 6, 4, 2, 3], GoodEnoughIndex: 5 }; | |
venuePrefs['Delta Sports Hall'] = { CourtPrecedence: [1, 2, 3, 4], GoodEnoughIndex: 3 }; | |
venuePrefs['Delta Sports Hall'] = { CourtPrecedence: [1, 6, 7, 5, 2, 3, 4], GoodEnoughIndex: 1 }; | |
$(document).ready(function () { | |
var form = $("form#formTimeslots"); | |
if (form.length > 0) { | |
//check venue id | |
var selectedVenue = $("#facVenueSelection > option[selected='selected']"); | |
if (selectedVenue.length === 0) { | |
selectedVenue = $("p.item-desc-subtitle"); | |
} | |
if (selectedVenue.length > 0 && selectedVenue.text() !== cfg.Venue) { | |
var newName = selectedVenue.text(); | |
console.log(selectedVenue.val() + ":" + newName); | |
cfg.VenuePref = getVenuePref(newName); | |
if (typeof cfg.VenuePref !== "undefined") { | |
cfg.Venue = newName; | |
} | |
} | |
if (typeof cfg.VenuePref === "undefined") { | |
console.log("VenueName:" + cfg.Venue); | |
cfg.VenuePref = getVenuePref(cfg.Venue); | |
} | |
if (!book_2hrs(form)) { | |
if ($(".logged-in-red").length > 0) { | |
if (confirm("Failed to find courts for two consecutive hours, try again?")) { | |
window.location.pathname = "/facilities"; | |
} | |
} | |
else { | |
//session expired, need relogin | |
window.location.pathname = "/auth"; | |
} | |
} | |
return; | |
} | |
form = $("form"); | |
var formId = form.attr("id"); | |
if (formId === "formFacFilter" || formId === "formQuickBookSearch") { | |
setValue(); | |
return; | |
} | |
else if (formId === "formCartPayment") { | |
console.log("Booked " + $(".facility-cart-entry").length + " Courts"); | |
return; | |
} | |
console.log("pathname='" + window.location.pathname + "'"); | |
console.log("formId='" + formId + "'"); | |
if (window.location.pathname === "/cart") { | |
//no court is added to cart, redirect to facilities bookings | |
window.location.pathname = "/facilities"; | |
} | |
if (window.location.pathname.indexOf("process") > 0) { | |
//https://members.myactivesg.com/facilities/processStandardBooking/59265c62ffaa599cde44ea3d0f11e53a | |
try { | |
eval("var result = " + $("pre").html() + ";"); | |
//{"message":"Your bookings have been saved.","method":"confirm","confirm":"Your items are added to cart. Would you like to go to shopping cart?","redirect":"https:\/\/members.myactivesg.com\/cart"} | |
if (typeof result.redirect !== 'undefined') { | |
console.log("Redirecting to :" + result.redirect); | |
} | |
//{"code":7208,"message":"Sorry, you have exceeded your booking limit.","method":"alert"} | |
else { | |
eval(result.method + "('[" + result.code + "]" + result.message + "')"); | |
} | |
} | |
catch (err) { | |
} | |
window.location.pathname = "/cart"; | |
} | |
if (window.location.pathname === "/profile") { | |
window.location.pathname = "/facilities"; | |
} | |
}); | |
function setValue() { | |
var days = { "Mon": "1", "Tue": "2", "Wed": "3", "Thu": "4", "Fri": "5", "Sat": "6", "Sun": "7" }; | |
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; | |
//choose activity type | |
var activityTypeSelector = $("select#activity_filter"); | |
var activityType = "18"; | |
//set value | |
activityTypeSelector.val(activityType); | |
//set display value | |
var activityTypeName = activityTypeSelector.find("option").filter(function (index) { return $(this).val() === activityType; }).text(); | |
$("#activity_filter_chosen > a > span").html(activityTypeName); | |
var venueSelector = $("select#venue_filter"); | |
var venueOption = venueSelector.find("option").filter(function (index) { return $(this).text() === cfg.Venue; }); | |
if (venueOption.length > 0) { | |
var venueId = venueOption.val(); | |
//set value | |
venueSelector.val(venueId); | |
//set display value | |
$("#venue_filter_chosen > a > span").html(cfg.Venue); | |
} | |
else { | |
window.alert("Invalid Venue Name!!"); | |
} | |
var book_on = new Date(new Date().setDate(new Date().getDate() + 15)); | |
var date = ("" + book_on).slice(0, 15).replace(' ', ", "); | |
if ($("select#day_filter").length > 0) { | |
$("select#day_filter").val(days[date.split(",")[0]]); | |
} | |
var date_str = date.split(", ")[0] + ", " + book_on.getDate() + " " + months[book_on.getMonth()] + " " + book_on.getFullYear(); | |
$("input#date_filter").val(date_str); | |
} | |
function getVenuePref(venueName) { | |
var venuePref = venuePrefs[venueName]; | |
if ((typeof venuePref === "undefined")) { | |
console.log("returns default venue pref"); | |
venuePref = { CourtPrecedence: [], GoodEnoughIndex: 999 }; | |
} | |
return venuePref; | |
} | |
function searchCourt(form, startTime, endTime) { | |
//format is "Court <Number>;<venueId?>;<slotId>;<startTime>;<endTime>" | |
//e.g. "Court 01;50;128450;15:00:00;16:00:00" | |
//the value should ends($=) with ";<endTime>" | |
//console.log("Searching for " + startTime + ":00:00 - "+ endTime + ":00:00"); | |
var slots = form.find("div.row.timeslot-grid input[type='checkbox'][value$=';" + endTime + ":00:00']"); | |
if (slots.length > 1 && cfg.VenuePref.CourtPrecedence.length > 0) { | |
var topCourt = null; | |
var topPrecedence = -1; | |
$.each(slots, function (i, item) { | |
var courtNumber = parseInt(item.value.substring(7, 9)); | |
var p = cfg.VenuePref.CourtPrecedence.lastIndexOf(courtNumber); | |
//console.log("Court "+courtNumber + " Pref = " + p); | |
if (p > topPrecedence) { | |
//console.log("BetterChoice:Time=" + startTime + ":00:00" + " Court " + item.CourtNumber); | |
topCourt = item; | |
topPrecedence = p; | |
if (topPrecedence >= cfg.VenuePref.GoodEnoughIndex) return false; | |
} | |
}); | |
return $(topCourt); | |
} | |
else if (slots.length > 0) { | |
return $(slots[0]); | |
} | |
else { | |
return null; | |
} | |
} | |
//book one court for two consecutive hours | |
function book_2hrs(form) { | |
var time0 = cfg.StartTime; | |
cfg.MaxStartTime = cfg.MaxStartTime < cfg.StartTime ? cfg.StartTime : cfg.MaxStartTime; | |
while (time0 <= cfg.MaxStartTime) { | |
var time1 = time0 + 1; | |
var time2 = time0 + 2; | |
var court1 = searchCourt(form, time1, time2); | |
if (court1 === null) { | |
//no court available for the second hour, move start time 2 hrs after | |
time0 = time2; | |
continue; | |
} | |
var court2 = searchCourt(form, time0, time1); | |
if (court2 === null) { | |
var time3 = time0 + 3; | |
//no court available for the first hour, try search the third hour | |
court2 = searchCourt(form, time2, time3); | |
if (court2 === null) { | |
time0 = time3; | |
continue; | |
} | |
} | |
//select court and submit | |
court1.prop("checked", true); | |
court2.prop("checked", true); | |
form.submit(); | |
//console.log("Selected:"+court1.val()); | |
//console.log("Selected:"+court2.val()); | |
return true; | |
} | |
return false; | |
} |
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
// ==UserScript== | |
// @name activesg - single court for 2 hrs | |
// @namespace blah | |
// @version 0.6.5 | |
// @description activesg court booking | |
// @match https://members.myactivesg.com/* | |
// @copyright 2017+, naresh,Gavin,Kent | |
// @require http://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js | |
// ==/UserScript== | |
//StartTime: in 24H format and must >= 10 | |
//CourtPrecedence: higher index has higher precedence | |
//var cfg = {Venue:"Bukit Gombak Sports Hall", StartTime:11, MaxStartTime:11}; | |
var cfg = { Venue: "Zhangde Primary School Hall", StartTime: 18, MaxStartTime: 18 }; | |
//var cfg = {Venue:"Jurong East Sports Hall", StartTime:18, MaxStartTime:18}; | |
//var cfg = {Venue:"Bukit View Secondary School Hall", StartTime:12, MaxStartTime:20}; | |
var venuePrefs = {}; | |
venuePrefs['Zhangde Primary School Hall'] = { CourtPrecedence: [3, 1, 4, 2], GoodEnoughIndex: 3 }; | |
venuePrefs['Gan Eng Seng Secondary School Hall'] = { CourtPrecedence: [3, 1, 4, 2], GoodEnoughIndex: 3 }; | |
venuePrefs['Delta Sports Hall'] = { CourtPrecedence: [3, 1, 4, 2], GoodEnoughIndex: 3 }; | |
$(document).ready(function () { | |
var form = $("form#formTimeslots"); | |
if (form.length > 0) { | |
//check venue id | |
var selectedVenue = $("#facVenueSelection > option[selected='selected']"); | |
if (selectedVenue.length === 0) { | |
selectedVenue = $("p.item-desc-subtitle"); | |
} | |
if (selectedVenue.length > 0 && selectedVenue.text() !== cfg.Venue) { | |
var newName = selectedVenue.text(); | |
console.log(selectedVenue.val() + ":" + newName); | |
cfg.VenuePref = getVenuePref(newName); | |
if (typeof cfg.VenuePref !== "undefined") { | |
cfg.Venue = newName; | |
} | |
} | |
if (typeof cfg.VenuePref === "undefined") { | |
console.log("VenueName:" + cfg.Venue); | |
cfg.VenuePref = getVenuePref(cfg.Venue); | |
} | |
if (!book_2hrs(form)) { | |
if ($(".logged-in-red").length > 0) { | |
if (confirm("Failed to find courts for two consecutive hours, try again?")) { | |
window.location.pathname = "/facilities"; | |
} | |
} | |
else { | |
//session expired, need relogin | |
window.location.pathname = "/auth"; | |
} | |
} | |
return; | |
} | |
form = $("form"); | |
var formId = form.attr("id"); | |
if (formId === "formFacFilter" || formId === "formQuickBookSearch") { | |
setValue(); | |
return; | |
} | |
else if (formId === "formCartPayment") { | |
console.log("Booked " + $(".facility-cart-entry").length + " Courts"); | |
return; | |
} | |
console.log("pathname='" + window.location.pathname + "'"); | |
console.log("formId='" + formId + "'"); | |
if (window.location.pathname === "/cart") { | |
//no court is added to cart, redirect to facilities bookings | |
window.location.pathname = "/facilities"; | |
} | |
if (window.location.pathname.indexOf("process") > 0) { | |
//https://members.myactivesg.com/facilities/processStandardBooking/59265c62ffaa599cde44ea3d0f11e53a | |
try { | |
eval("var result = " + $("pre").html() + ";"); | |
//{"message":"Your bookings have been saved.","method":"confirm","confirm":"Your items are added to cart. Would you like to go to shopping cart?","redirect":"https:\/\/members.myactivesg.com\/cart"} | |
if (typeof result.redirect !== 'undefined') { | |
console.log("Redirecting to :" + result.redirect); | |
} | |
//{"code":7208,"message":"Sorry, you have exceeded your booking limit.","method":"alert"} | |
else { | |
eval(result.method + "('[" + result.code + "]" + result.message + "')"); | |
} | |
} | |
catch (err) { | |
} | |
window.location.pathname = "/cart"; | |
} | |
if (window.location.pathname === "/profile") { | |
window.location.pathname = "/facilities"; | |
} | |
}); | |
function setValue() { | |
var days = { "Mon": "1", "Tue": "2", "Wed": "3", "Thu": "4", "Fri": "5", "Sat": "6", "Sun": "7" }; | |
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; | |
//choose activity type | |
var activityTypeSelector = $("select#activity_filter"); | |
var activityType = "18"; | |
//set value | |
activityTypeSelector.val(activityType); | |
//set display value | |
var activityTypeName = activityTypeSelector.find("option").filter(function (index) { return $(this).val() === activityType; }).text(); | |
$("#activity_filter_chosen > a > span").html(activityTypeName); | |
var venueSelector = $("select#venue_filter"); | |
var venueOption = venueSelector.find("option").filter(function (index) { return $(this).text() === cfg.Venue; }); | |
if (venueOption.length > 0) { | |
var venueId = venueOption.val(); | |
//set value | |
venueSelector.val(venueId); | |
//set display value | |
$("#venue_filter_chosen > a > span").html(cfg.Venue); | |
} | |
else { | |
window.alert("Invalid Venue Name!!"); | |
} | |
var book_on = new Date(new Date().setDate(new Date().getDate() + 15)); | |
var date = ("" + book_on).slice(0, 15).replace(' ', ", "); | |
if ($("select#day_filter").length > 0) { | |
$("select#day_filter").val(days[date.split(",")[0]]); | |
} | |
var date_str = date.split(", ")[0] + ", " + book_on.getDate() + " " + months[book_on.getMonth()] + " " + book_on.getFullYear(); | |
$("input#date_filter").val(date_str); | |
} | |
function getVenuePref(venueName) { | |
var venuePref = venuePrefs[venueName]; | |
if ((typeof venuePref === "undefined")) { | |
console.log("returns default venue pref"); | |
venuePref = { CourtPrecedence: [], GoodEnoughIndex: 999 }; | |
} | |
return venuePref; | |
} | |
function searchCourt(form, startTime, endTime) { | |
//format is "Court <Number>;<venueId?>;<slotId>;<startTime>;<endTime>" | |
//e.g. "Court 01;50;128450;15:00:00;16:00:00" | |
//the value should ends($=) with ";<endTime>" | |
//console.log("Searching for " + startTime + ":00:00 - "+ endTime + ":00:00"); | |
var slots = form.find("div.row.timeslot-grid input[type='checkbox'][value$=';" + endTime + ":00:00']"); | |
if (slots.length > 1 && cfg.VenuePref.CourtPrecedence.length > 0) { | |
var topCourt = null; | |
var topPrecedence = -1; | |
$.each(slots, function (i, item) { | |
var courtNumber = parseInt(item.value.substring(7, 9)); | |
var p = cfg.VenuePref.CourtPrecedence.lastIndexOf(courtNumber); | |
//console.log("Court "+courtNumber + " Pref = " + p); | |
if (p > topPrecedence) { | |
//console.log("BetterChoice:Time=" + startTime + ":00:00" + " Court " + item.CourtNumber); | |
topCourt = item; | |
topPrecedence = p; | |
if (topPrecedence >= cfg.VenuePref.GoodEnoughIndex) return false; | |
} | |
}); | |
return $(topCourt); | |
} | |
else if (slots.length > 0) { | |
return $(slots[0]); | |
} | |
else { | |
return null; | |
} | |
} | |
//book one court for two consecutive hours | |
function book_2hrs(form) { | |
var time0 = cfg.StartTime; | |
cfg.MaxStartTime = cfg.MaxStartTime < cfg.StartTime ? cfg.StartTime : cfg.MaxStartTime; | |
while (time0 <= cfg.MaxStartTime) { | |
var time1 = time0 + 1; | |
var time2 = time0 + 2; | |
var court1 = searchCourt(form, time1, time2); | |
if (court1 === null) { | |
//no court available for the second hour, move start time 2 hrs after | |
time0 = time2; | |
continue; | |
} | |
var court2 = searchCourt(form, time0, time1); | |
if (court2 === null) { | |
var time3 = time0 + 3; | |
//no court available for the first hour, try search the third hour | |
court2 = searchCourt(form, time2, time3); | |
if (court2 === null) { | |
time0 = time3; | |
continue; | |
} | |
} | |
//select court and submit | |
court1.prop("checked", true); | |
court2.prop("checked", true); | |
form.submit(); | |
//console.log("Selected:"+court1.val()); | |
//console.log("Selected:"+court2.val()); | |
return true; | |
} | |
return false; | |
} |
Hi Derian,
Thanks for the amazing script. I have emailed you to get in touch with you, wish you hear from you soon.
Wait this script is usable?
what a script. just bumped into this. may I know how to setup this to my pc ?
Can this be detected by activesg?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
Good job.
May I know how can I use this script?
Thank you.