HDB Flat Availability

try to take over the world

当前为 2023-10-20 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         HDB Flat Availability
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world
// @author       You
// @match        https://homes.hdb.gov.sg/home/bto/details/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=undefined.
// @grant        none
// @license      MIT
// ==/UserScript==
(function () {
   'use strict';
   //console.debug("Init Script");


   // Create a start button to begin program
   setTimeout(() => {
      main();
   }, 2000)

   function main() {
      //console.debug("Appending Button n text area");
      // Your code here...
      let unit_type;
      let message;
      let data = {};
      let blocks = [];


      // Create a text area on screen
      let container_div = document.evaluate("/html/body/app-root/div[2]/app-bto-details/section/div/div[5]/div/div[1]/div", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
      const text_area = document.createElement("textarea");
      const text_area2 = document.createElement("textarea");
      const start_btn = document.createElement("button");
      const status = document.createElement("p");
      let room_type = document.getElementById("choose-room-type").options[1].text;
      let project = document.getElementsByClassName("col-12 col-sm-8 col-md-8 mb-5 mb-md-0")[0].getElementsByTagName("h4")[0].innerHTML
      start_btn.innerHTML = "Start"
      start_btn.onclick = function () {
         runner()
      };

       //{ 46b: {unit_info:{} , quota:{} } }


      container_div.appendChild(text_area);
      container_div.appendChild(start_btn);
      container_div.appendChild(text_area2);
      container_div.appendChild(status);
      function formatMsg(json){
           let msg = `${project}\n${room_type}\n`
           msg += `Generated on ${new Date().toLocaleString()}\n\n`

           for (const [block, blk_details] of Object.entries(json)) {
               let floors = blk_details['unit_info'];
               let quota = blk_details['quota'];
               msg += `\n${block}\n`;
               let seen_units = {};

               for (const [floor, units] of Object.entries(floors)) {
                   msg+= floor
                   let first_floor_flag = floor == Object.keys(floors)[Object.keys(floors).length - 1];
                   //console.debug(`first_floor flag ${first_floor_flag} curr_floor ${floor} first floor ${Object.keys(floors)[Object.keys(floors).length - 1]} `)
                   for (const [unit, unit_details] of Object.entries(units)) {
                       if (unit_details.avail){ msg += "  🟢  "  }else{  msg += "  🔴  " }
                       //if (first_floor_flag){ msg += ` ${unit} `; }
                       if (unit in seen_units){ seen_units[unit] += 1 }else {seen_units[unit] = 1}
                   }
                   msg += "\n"
               }
               msg += '   '
               for (let unit of Object.keys(seen_units)){
                   msg += ` ${unit}  `
               }
               msg += "\n"
               for ( let [race, qty] of Object.entries(quota) ){

                   msg += `   ${race}:${qty}`

               }
               msg += "\n"
               console.debug(seen_units);

           }
          console.debug(msg);
          return msg;
       }

      function runner() {
          console.debug("Running Script");

         // Get the list of different blocks
         var select_block = document.querySelector('[aria-label="Block"]');
         for (let i = 0; i < select_block.options.length; i++) {
            var option = select_block.options[i];
            if (option.innerHTML != "Choose Block No.") {
               let block_info = option.innerHTML
               blocks.push(block_info);
               data[block_info] = {};
            }
         }
         // Get the grid element

         for (let k = 0; k < blocks.length; k ++ ){
             console.debug("Inside " + blocks[k]);
             status.innerHTML = `Processing for ${blocks[k]}`
             const grid = document.getElementById("available-grid");
             let floors = grid.getElementsByClassName("row level");
             select_block.value = k;
             var event = new Event('change');
             select_block.dispatchEvent(event);

             let curr_block = blocks[k]

             // get quota
             let quota_elems = document.getElementById("available-sidebar").getElementsByClassName("col-12 col-md-auto");
             let quota_obj = {}
             for ( let quota of quota_elems ){

                 let quota_split = quota.innerHTML.trim().split(": ")
                 quota_obj[quota_split[0]] = quota_split[1];
             }
             data[curr_block]["quota"] = quota_obj
             data[curr_block]["unit_info"] = {}


             // Iterate through each row in the grid
             for (let i = 0; i < floors.length; i++) {
                 let curr_floor = floors[i];
                 let labels_curr_floor = curr_floor.getElementsByTagName("label");
                 let curr_floor_text = labels_curr_floor[0].innerHTML;
                 if (data[curr_block]["unit_info"][curr_floor_text] == undefined) {
                     data[curr_block]["unit_info"][curr_floor_text] = {}
                 }
                 for (let j = 1; j < labels_curr_floor.length; j++) {
                     let curr_unit_label = labels_curr_floor[j]; // should have length of 0 = unit , 2 = sqm, 4 = price
                     let curr_unit_nodes = curr_unit_label.childNodes; // should have length of 0 = unit , 2 = sqm, 4 = price
                     let curr_p1 = curr_unit_nodes[0].data;
                     let curr_p2 = curr_unit_nodes[2].data;
                     let curr_p3 = curr_unit_nodes[4].data;
                     let curr_p4 = curr_unit_label.parentElement.hasAttribute("disabled");


                     data[curr_block]["unit_info"][curr_floor_text][curr_p1] = {
                         "sqm": curr_p2,
                         "price": curr_p3,
                         "avail": !curr_p4
                     };
                 }

             }
         }
         text_area.value = JSON.stringify(data);
         text_area2.value = formatMsg(data);
      }




      // Once complete click the next select element and wait
      // return a message
   }

})();