-
-
Save liuliqiang/ec60818cba75d521337e45b4cecf69b6 to your computer and use it in GitHub Desktop.
activesg badminton booking scripts
This file contains 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 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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment