ACGN-stock營利統計外掛

try to take over the world!

目前為 2017-10-28 提交的版本,檢視 最新版本

// ==UserScript==
// @name         ACGN-stock營利統計外掛
// @namespace    http://tampermonkey.net/
// @version      3.300
// @description  try to take over the world!
// @author       SoftwareSing
// @match        http://acgn-stock.com/*
// @match        https://acgn-stock.com/*
// @grant        none
// ==/UserScript==

//版本號為'主要版本號 + "." + 次要版本號 + 錯誤修正版本號(兩位),ex 1.801
//修復導致功能失效的錯誤或更新重大功能提升主要或次要版本號
//優化UI,優化效能,優化小錯誤更新錯誤版本號
//兩個錯誤修正版本號防止迫不得已進位到次要版本號
//本腳本修改自 "ACGN股票系統每股營利外掛 2.200 by papago89"


/*************************************/
/************GlobalVariable***********/

//會跨2區以上使用的全域變數放在這裡
//如從stockSummary跨到accountInfo用的變數


var myID = null;               //當前登入的使用者ID
var myHoldStock = [];   //當前登入的使用者持有的股票, 在股市總覽可以直接抓到全部
var myOrders = [];      //當前登入的使用者未完成交易的買賣單, 在股市總覽可以直接抓到全部

var othersScript = [];


/************GlobalVariable***********/
/*************************************/
/*************************************/
/*********ACGNListenerScript**********/

//本區監測事件搬運自"ACGN股票系統每股營利外掛 ver2.810"
//https://github.com/frozenmouse/acgn-stock-user-script/blob/master/acgn-stock.user.js


(function() {
    startEvent();

    observeLoadingOverlay();
  })();
  
// 觀察頁面是否進入或離開載入狀態(是否正在轉圈圈)
function observeLoadingOverlay() {
    // 頁面處於載入狀態時會出現的蓋版元素(俗稱「轉圈圈」)
    const loadingOverlay = $("#loading .loadingOverlay")[0];

    // 觀察 loadingOverlay 的 class attribute 是否變動
    new MutationObserver(mutations => {
        mutations.filter(m => m.attributeName === "class").forEach(m => {
        if (m.target.classList.contains("d-none")) {
            // 轉圈圈隱藏 => 已脫離載入狀態
            onPageLoaded();
        } else {
            // 顯示轉圈圈 => 正處於載入狀態
            onPageLoading();
        }
        });
    }).observe(loadingOverlay, { attributes: true });
}

// 頁面在載入狀態時進行此回呼
function onPageLoading() {
    console.log(`Page loading: ${document.location.href}`);
}

// 頁面離開載入狀態時進行此回呼
function onPageLoaded() {
    const currentUrl = document.location.href;
    console.log(`Page loaded: ${currentUrl}`);

    // 頁面 url 樣式的回呼表
    const urlPatternCallbackTable = [
        { pattern: /company\/[0-9]+/, callback: onStockSummaryPageLoaded },
        { pattern: /company\/detail/, callback: onCompanyDetailPageLoaded },
        { pattern: /accountInfo/, callback: onAccountInfoPageLoaded },
        { pattern: /foundation\/[0-9]+/, callback: onFoundationPlanPageLoaded },
    ];

    // 匹配當前頁面 url 的樣式並進行對應的回呼
    urlPatternCallbackTable.forEach(({ pattern, callback }) => {
        if (currentUrl.match(pattern)) {
        // loadingOverlay 消失後,需要給點時間讓頁面的載入全部跑完
        setTimeout(callback, 100);
        }
    });
}
  
// 當「股市總覽」頁面已載入時進行的回呼
function onStockSummaryPageLoaded() {
    setTimeout(stockSummaryEvent, 500);
}

// 當「公司資訊」頁面已載入時進行的回呼
function onCompanyDetailPageLoaded() {
    setTimeout(companyEvent, 500);
}

// 當「帳號資訊」頁面已載入時進行的回呼
function onAccountInfoPageLoaded() {
    setTimeout(checkUserInfo, 10);
    //checkUserInfo();
}

// 當「新創計劃」頁面已載入時進行的回呼
function onFoundationPlanPageLoaded() {
    
}


/*********ACGNListenerScript**********/
/*************************************/
/*************************************/
/*************StartScript*************/

//本區StartFunction   startEvent()


function startEvent()
{
    checkSeriousError();
    setTimeout(checkScriptEvent, 390);
    //前2項十分重要,需最優先執行

    setTimeout(checkDividendUpdateTime, 1000);
    setTimeout(addAD, 2000);
    setTimeout(checkOthersScript, 2500);
    setTimeout(checkUserID, 3900);

    setTimeout(checkOthersScript, 180000);
}


function checkUserID()
{
    myID = String(Meteor.connection._userId);
    console.log("userID:  " + myID);
    if (myID === null)
        setTimeout(checkUserID, 30000);
    else
        setTimeout(checkUserID, 1200000);
}


/*************StartScript*************/
/*************************************/
/*************************************/
/**********ResetLocalStorage**********/

//本區StartFunction   checkSeriousError()


function checkSeriousError()
{
    //這個function將會清空所有由本插件控制的localStorage
    //用於如果上一版發生嚴重錯誤導致localStorage錯亂,以致插件無法正常啟動時
    //或是用於當插件更新時,需要重設localStorage


    var seriousErrorVersion = 3.000;
    //seriousErrorVersion會輸入有問題的版本號,當發生問題時我會增加本數字,或是於更新需要時亦會增加
    //使用者本地的數字紀錄如果小於這個數字將會清空所有localStorage

    var lastErrorVersion = 0 !== window.localStorage.getItem ("lastErrorVersion") ? Number(JSON.parse(window.localStorage.getItem ("lastErrorVersion"))) : 0;
    //lastErrorVersion = 0;  //你如果覺得現在就有問題 可以把這行的註解取消掉來清空localStorage

    //console.log(Number.isInteger(lastErrorVersion));
    //console.log(lastErrorVersion);
    if (Number.isNaN(lastErrorVersion))
    {
        lastErrorVersion = 0;
        console.log("reset lastErrorVersion as 0");
    }
    else
    {
        console.log("localStorage of lastErrorVersion is work");
    }

    if (lastErrorVersion < seriousErrorVersion)
    {
        console.log("last version has serious error, start remove all localStorage");
        window.localStorage.removeItem ("Dividend_UpdateTime");
        window.localStorage.removeItem ("Dividend");
        window.localStorage.removeItem ("lastErrorVersion");
        lastErrorVersion = seriousErrorVersion;
        window.localStorage.setItem ("lastErrorVersion", JSON.stringify(lastErrorVersion));
    }
}


/**********ResetLocalStorage**********/
/*************************************/
/*************************************/
/************UpdateScript*************/

//本區StartFunction   checkScriptEvent()


function checkScriptEvent()
{
    var myVersion = GM_info.script.version;
    var oReq = new XMLHttpRequest();
    oReq.addEventListener("load", checkScriptVersion);
    oReq.open("GET", "https://gf.qytechs.cn/scripts/33542.json");
    oReq.send();
}

function checkScriptVersion()
{
    var obj = JSON.parse(this.responseText);
    var myVersion = GM_info.script.version;
    console.log(obj.version.substr(0, 3) + "," + myVersion.substr(0, 3) + "," + (obj.version.substr(0, 3) > myVersion.substr(0, 3)));
    if(obj.version.substr(0, 3) > myVersion.substr(0, 3))
        $('<li class="nav-item"><a class="nav-link btn btn-primary" href="https://gf.qytechs.cn/zh-TW/scripts/33542" id="UpdateDividendScript" target="Blank">' + Dict[lan].updateDividendScript + '</a></li>').insertAfter($('.nav-item')[$('.nav-item').length - 1]);
    else
		setTimeout(checkScriptEvent, 600000);
}


/************UpdateScript*************/
/*************************************/
/*************************************/
/**********CheckOthersScript**********/

//本區StartFunction   checkOthersScript()


//檢查是否有安裝其他腳本
function checkOthersScript()
{
    console.log("start checkOthersScript()");

    const papago89 = check_papago89_Script();
    if (papago89)
        addToScriptList("papago89");


    console.log("complete checkOthersScript()");
}

function addToScriptList(scriptName)
{
    const scriptIndex = othersScript.findIndex(n => n == scriptName);
    if (scriptIndex === -1)
        othersScript.push(scriptName);
}


//檢查是否有安裝papago89的腳本
function check_papago89_Script() 
{
    const papago89_Script = $('#about-script').length;
    if (papago89_Script > 0)
    {
        console.log("-----found papago89 script");
        return true;
    }
    else
        return false;
}


/**********CheckOthersScript**********/
/*************************************/
/*************************************/
/***********GetDataBaseData***********/

//所有外連DB的function都寫在這裡


//所有可以用網頁呈現的DB都用這個去call
function getWebData(url)
{
    let webObjCache = null;

    const webUrl = String(url);
    const request = new XMLHttpRequest();
    request.open("GET", webUrl); // 非同步 GET
    request.addEventListener("load", () => {
        console.log("got webData");
        try {
            webObjCache = JSON.parse(request.responseText);
        }
        catch(err) {
            webObjCache = request.responseText;
        }
    });
    request.send();

    return (callback) => {
        // 若快取資料存在,則直接回傳快取
        if (webObjCache !== null) 
        {
            callback(webObjCache);
            return;
        }
    
        // 若無快取資料,則加入事件監聽,等載入後再回傳資料
        request.addEventListener("load", function() {
            callback(webObjCache);
        });
    };
}

//連上web來取得資料
/**
 * 以非同步方式取得另外整理過的公司資料 json
 *
 * 考慮資料更新週期極長,若是已經取得過資料,就將之前取得的資料快取回傳
 *
 * 使用方法:
 * const getData = getWebData("https://www.google.com");  //這邊請把google換成你要連的網址
 * getData(a => {
 *   // 這裡的 a 即為該 json 物件
 *   console.log(a);
 * });
 * 
 * //有呼叫const的function請務必用setTimeout執行,以防錯誤,即使0秒也行
 * setTimeout(fun_a, 0);
 * function fun_a() {
 *      getData(a => {
 *          console.log(a);
 *      }
 * }
 */

const companies_jsonbin = "https://jsonbin.org/abcd1357/ACGNstock-company";
const companies_jsonbin_updatetime = "https://jsonbin.org/abcd1357/ACGNstock-company/updateTime";

const AD_jsonbin = "https://jsonbin.org/abcd1357/ACGNstock-AD";


/***********GetDataBaseData***********/
/*************************************/
/*************************************/
/**********UpdateDividendData*********/

//本區StartFunction   checkDividendUpdateTime()


function checkDividendUpdateTime()
{
    console.log("start check Dividend update time");
    //window.localStorage.removeItem ("Dividend_UpdateTime");

    var Dividend_UpdateTime = null !== window.localStorage.getItem ("Dividend_UpdateTime") ? JSON.parse(window.localStorage.getItem ("Dividend_UpdateTime")) : "null";

    const get_companies_jsonbin_updatetime = getWebData(companies_jsonbin_updatetime);
    get_companies_jsonbin_updatetime(json_updateTime => 
    {
        console.log("json_updateTime === Dividend_UpdateTime :  " + (json_updateTime === Dividend_UpdateTime));
        if (json_updateTime === Dividend_UpdateTime)
        {
            console.log("dont need update    " + Dividend_UpdateTime);
        }
        else
        {
            console.log("server update time:  " + json_updateTime);
            console.log("local update time:  " + Dividend_UpdateTime);

            console.log("start update data");
            setTimeout(updateDividendData, 1);
        }
    });

    console.log("complete check Dividend update time");
}

function updateDividendData()
{
    console.log("start update Dividend data");

    var Dividends = [];

    const get_companies_jsonbin = getWebData(companies_jsonbin);
    get_companies_jsonbin(jsonData =>
    {
        
        for (let n = 0 ; n < jsonData.companys.length ; n++)
        {
            Dividends.push({"companyID": String(jsonData.companys[n].companyID),
                "companyDividend": String(jsonData.companys[n].companyDividend),
                "companyPrice": String(jsonData.companys[n].companyPrice),
                "companyStock": String(jsonData.companys[n].companyStock) });
            //console.log("push success");
        }
        window.localStorage.setItem ("Dividend", JSON.stringify(Dividends));
        if (jsonData.updateTime === null || jsonData.updateTime === undefined)
        {
            window.localStorage.setItem ("Dividend_UpdateTime", JSON.stringify("no data"));
        }
        else
        {
            window.localStorage.setItem ("Dividend_UpdateTime", JSON.stringify(jsonData.updateTime));
        }
    });

    console.log("complete update Dividend data");
}


/**********UpdateDividendData*********/
/*************************************/
/*************************************/
/**************scriptAD***************/

//本區StartFunction   addAD()


function addAD()
{
    console.log("start add script AD");

    var data, adNumber, link, linkNumber = 0, linkType;
    $('<a class="scriptAD float-left" id="scriptAD-0">&nbsp;&nbsp;</a>').insertAfter($('.text-danger.float-left'));

    const get_AD_jsonbin = getWebData(AD_jsonbin);
    get_AD_jsonbin(jsonData => 
    {
        console.log("ADnumber:" + jsonData.adFormat.length);
        for (let adF = 0 ; adF < jsonData.adFormat.length ; ++adF)
        {
            console.log("adding AD");
            adNumber = Number($('.scriptAD').length);
            data = jsonData.adData[adF];

            if (jsonData.adFormat[adF] == "a")
            {
                $('<a class="scriptAD float-left" id="scriptAD-' + adNumber + '">' + data + '</a>').insertAfter($('#scriptAD-' + (adNumber - 1)));
            }
            else if (jsonData.adFormat[adF] == "aLink")
            {
                link = jsonData.adLink[linkNumber];
                linkType = jsonData.adLinkType[linkNumber];
                //console.log(linkType);
                //console.log((linkType != "_blank"));
                if ((linkType != "_blank") && (linkType != "_parent") && (linkType != "_top"))
                    linkType = "";
                //linkType = "";
                $('<a class="scriptAD float-left" id="scriptAD-' + adNumber + '" href="' + link + '" target="' + linkType + '">' + data + '</a>').insertAfter($('#scriptAD-' + (adNumber - 1)));
                linkNumber += 1;
            }
        }
    });


    console.log("success add script AD");
}


/**************scriptAD***************/
/*************************************/
/*************************************/
/************stockSummary*************/

//本區StartFunction   stockSummaryEvent()


function stockSummaryEvent()
{
    setTimeout(getBasicUserData, 500, 0);
    setTimeout(useCompaniesDatasEvent, 600);
}


function getBasicUserData(runNumber)
{
    var restart = false;
    if (runNumber < 10)
    {
        runNumber += 1;

        if (Meteor.connection._mongo_livedata_collections.directors.find().fetch().length > 0)
            myHoldStock = Meteor.connection._mongo_livedata_collections.directors.find().fetch();
        else
            restart = true;
        
        if (Meteor.connection._mongo_livedata_collections.orders.find().fetch() > 0)
            myOrders = Meteor.connection._mongo_livedata_collections.orders.find().fetch();
        else
            restart = true;
    }

    if (restart)
        setTimeout(getBasicUserData, 1000, runNumber);
}


function useCompaniesDatasEvent()
{
    var companiesDatas = Meteor.connection._mongo_livedata_collections.companies.find().fetch();
    
    if (companiesDatas.length > 0)
    {
        console.log("start useCompaniesDatasEvent()");
        var profit, price, ID, release, earnPerShare, manager, hold;

        //如果執行的function需要存值,放在這裡
        var value_computeProfit = 0;
        var value_BatchAddDividendLocalStorage_1 = null !== window.localStorage.getItem ("Dividend") ? JSON.parse(window.localStorage.getItem ("Dividend")) : [];
        var value_BatchAddDividendLocalStorage_2 = false;
        var value_BatchAddDividendLocalStorage = [value_BatchAddDividendLocalStorage_1, value_BatchAddDividendLocalStorage_2];
        var value_isEnd = false;

        for (let i = 0; i < companiesDatas.length; ++i)
        {
            let thisCompany = companiesDatas[i];

            profit = Number(thisCompany.profit);
            price = Number(thisCompany.listPrice);
            ID = String(thisCompany._id);
            release = Number(thisCompany.totalRelease);
            earnPerShare = (Number(thisCompany.profit) * 0.8075 / Number(thisCompany.totalRelease));
            manager = String(thisCompany.manager);

            const MHSindex = myHoldStock.findIndex(a => a.companyId == ID);
            if (MHSindex === -1)
                hold = 0;
            else
                hold = Number(myHoldStock[MHSindex].stocks);

            console.log(ID + "---" + price + "---" + release + "---" + profit + "---" + earnPerShare + "---" + manager + "---" + hold);


            //需要執行的function放在這
            value_computeProfit = computeProfit(ID, earnPerShare, hold, value_computeProfit);

            value_isEnd = (i + 1 >= companiesDatas.length);
            value_BatchAddDividendLocalStorage = BatchAddDividendLocalStorage(ID, earnPerShare, price, release, value_BatchAddDividendLocalStorage, value_isEnd);

            const papago89_Script = othersScript.findIndex(n => n == "papago89");
            if (papago89_Script === -1)
                SSAddSomeInfo(ID, earnPerShare, price, hold, manager, profit);



            console.log("");
        }

        console.log("complete computeProfit()");
    }
    else
    {
        console.log("companiesDatas not ready, restart useCompaniesDatasEvent() after 2s");
        setTimeout(useCompaniesDatasEvent, 2000);
    }
}

//總獲利計算--加入分紅計算
function computeProfit(ID, earnPerShare, hold, sumProfit) 
{
    console.log("-----start computeProfit()");

    var classProfit;


    sumProfit += earnPerShare * hold;
    
    console.log("預計分紅: " + sumProfit);

    classProfit = $("#totalProfitNumber");
    if (classProfit.length === 0)
    {
        $('<div class="media company-summary-item border-grid-body" id = "totalProfit"><div class="col-6 text-right border-grid" id = "totalProfitTitle"><h2>' + Dict[lan].totalProfitInThisPage + '</h2></div></div>').insertAfter($('.card-title.mb-1')[0]);
        $('<div class="col-6 text-right border-grid" id = "totalProfitNumber"><h2>$ ' + sumProfit.toFixed() + '</h2></div>').insertAfter($('#totalProfitTitle')[0]);
    }
    else
    {
        $("#totalProfitNumber")[0].innerHTML = "<h2>$ " + sumProfit.toFixed() + "</h2>";
    }

    console.log("-----complete computeProfit()");
    return sumProfit;
}


//批量將公司資料加入localStorage
function BatchAddDividendLocalStorage(ID, earnPerShare, price, release, inputValue, isEnd)
{
    console.log("-----start BatchAddDividendLocalStorage()");
    var Dividends = inputValue[0];
    var isChange = inputValue[1];

    //Dividends規格
    //{"companyID": A, "companyDividend": B, "companyPrice": C, "companyStock": D}
    let index = Dividends.findIndex(x => x.companyID == ID);
    if (index != -1)
    {
        if ((Dividends[index].companyDividend == earnPerShare) &&
            (Dividends[index].companyPrice == price) &&
            (Dividends[index].companyStock == release))
        {
            console.log("dont need update LocalStorage");
        }
        else
        {
            isChange = true;
            Dividends.splice(index, 1);
            console.log("AddDividendLocalStorage---splice");

            Dividends.push({"companyID": ID, "companyDividend": earnPerShare, "companyPrice": price, "companyStock": release});
            console.log("Add Dividend LocalStorage!!");
        }
    }
    else
    {
        isChange = true;
        Dividends.push({"companyID": ID, "companyDividend": earnPerShare, "companyPrice": price, "companyStock": release});
        console.log("AddDividendLocalStorage!!");
    }

    //console.log("-----BatchAddDividendLocalStorage()---isChange: " + isChange + "---isEnd: " + isEnd + "---");
    if (isChange && isEnd)
    {
        window.localStorage.setItem ("Dividend", JSON.stringify(Dividends));
        console.log("setItem---Dividend");
    }

    outputValue = [Dividends, isChange];
    console.log("-----complete BatchAddDividendLocalStorage()");
    return outputValue;
}


function SSAddSomeInfo(ID, earnPerShare, price, hold, manager, profit)
{
    if($(".col-12.col-md-6.col-lg-4.col-xl-3").length > 0)
    {
        //會加入 本益比 股價總值 現金股利 經理薪水
        console.log("-----start SSAddSomeInfo()");

        var classInfo;
        var PE, stockWorth, stockProfit, managerSalary;

        PE = price / earnPerShare;
        PE = PE.toFixed(3);

        stockWorth = price * hold;
        stockProfit = (earnPerShare * hold).toFixed();
        managerSalary = (profit * 0.05).toFixed();

        let i = 0;
        for (i = 0 ; i < $('.title a').length ; i++)
        {
            if (ID == String($('.title a')[i].href.match(/\/company\/detail\/([^]+)/)[1]))
                break;
        }

        console.log("-----SSAddSomeInfo()---" + ID + "---" + i + "---" + PE + "---" + stockWorth + "---" + stockProfit + "---" + managerSalary + "---");

        classInfo = $("#stockPEInfo_" + i);
        if (classInfo.length === 0)
        {
            if (myID == manager)
                $('<div name="stockPEInfo" class="row row-info d-flex justify-content-between" id="stockManagerSalaryInfo_' + i + '"><p>' + Dict[lan].stockManagerSalaryInfo + '</p><p>' + managerSalary + '</p></div>').insertAfter($('.company-card')[i].children[6]);
            $('<div name="stockPEInfo" class="row row-info d-flex justify-content-between" id="stockProfitInfo_' + i + '"><p>' + Dict[lan].stockProfitInfo + '</p><p>' + stockProfit + '</p></div>').insertAfter($('.company-card')[i].children[6]);
            $('<div name="stockPEInfo" class="row row-info d-flex justify-content-between" id="stockWorthInfo_' + i + '"><p>' + Dict[lan].stockWorthInfo + '</p><p>' + stockWorth + '</p></div>').insertAfter($('.company-card')[i].children[6]);
            $('<div name="stockPEInfo" class="row row-info d-flex justify-content-between" id="stockPEInfo_' + i + '"><p>' + Dict[lan].stockPEInfo + '</p><p>' + PE + '</p></div>').insertAfter($('.company-card')[i].children[6]);
        }


        console.log("-----complete SSAddSomeInfo()");
    }
}


/************stockSummary*************/
/*************************************/
/*************************************/
/**************company****************/

//本區StartFunction   companyEvent()


function companyEvent()
{
    setTimeout(company_AddDividendLocalStorage, 1000);
}


function company_AddDividendLocalStorage()
{
    var companiesDatas = Meteor.connection._mongo_livedata_collections.companies.find().fetch();
    
    if (companiesDatas.length > 0)
    {
        console.log("start company_AddDividendLocalStorage()");
        var profit, price, ID, release, earnPerShare, manager, hold;

        let thisCompany = companiesDatas[0];

        profit = Number(thisCompany.profit);
        price = Number(thisCompany.listPrice);
        ID = String(thisCompany._id);
        release = Number(thisCompany.totalRelease);
        earnPerShare = (Number(thisCompany.profit) * 0.8075 / Number(thisCompany.totalRelease));
        manager = String(thisCompany.manager);
        console.log(ID + "---" + price + "---" + release + "---" + profit + "---" + earnPerShare + "---" + manager + "---");

        var Dividends = null !== window.localStorage.getItem ("Dividend") ? JSON.parse(window.localStorage.getItem ("Dividend")) : [];

        //如果先前紀錄過該公司,則刪除重記
        const index = Dividends.findIndex(x => x.companyID == ID);
        if (index != -1)
        {
            if ((Dividends[index].companyDividend == earnPerShare) &&
                (Dividends[index].companyPrice == price) &&
                (Dividends[index].companyStock == release))
            {
                console.log("dont need update cookie");
            }
            else
            {
                Dividends.splice(index, 1);
                console.log("AddDividendCookie---splice");

                Dividends.push({"companyID": ID, "companyDividend": earnPerShare, "companyPrice": price, "companyStock": release});
                window.localStorage.setItem ("Dividend", JSON.stringify(Dividends));

                console.log("Add Dividend localStorage!!");
            }
        }
        else
        {
            Dividends.push({"companyID": ID, "companyDividend": earnPerShare, "companyPrice": price, "companyStock": release});
            window.localStorage.setItem ("Dividend", JSON.stringify(Dividends));

            console.log("AddDividendlocalStorage!!");
        }

        console.log("complete company_AddDividendLocalStorage()");
    }
    else
    {
        console.log("companiesDatas not ready, restart company_AddDividendLocalStorage() after 2s");
        setTimeout(company_AddDividendLocalStorage, 2000);
    }
}


/**************company****************/
/*************************************/
/*************************************/
/*************accountInfo*************/

//本區StartFunction   checkUserInfo()


function checkUserInfo()
{
    const userID = String(document.location.href.match(/accountInfo\/([0-z]+)/)[1]);
    var userStockInfo = null !== window.sessionStorage.getItem ("userStockInfo") ? JSON.parse(window.sessionStorage.getItem ("userStockInfo")) : [];
    //userStcokInfo的格式:
    //{"userID": CWgfhqxbrJMxsknrb, "userCompany": [{"companyID": aaa, "userHold": number}, {}]}
    var userIndex = userStockInfo.findIndex(a => a.userID == userID);
    if (userIndex == -1)
    {
        userStockInfo.push({"userID": userID, "userCompany": []});
        userIndex = userStockInfo.findIndex(a => a.userID == userID);
    }
    window.sessionStorage.setItem ("userStockInfo", JSON.stringify(userStockInfo));

    if ($('.card-title.mb-1').length > 0)
    {
        var managerSalary = Number(computeManagerSalary());

        if ((userID == myID) && (myHoldStock.length > 0))
        {
            checkMyHoldStock();
            addUserProfitInfo(userID, managerSalary);
        }
        
        checkUserHoldStock(userID, 0, managerSalary);
        setTimeout(addUserProfitInfo, 10, userID, managerSalary);
        //addUserProfitInfo(userID, managerSalary);
        
    }
    else
    {
        console.log("users not ready, restart checkUserInfo() after 2s");
        setTimeout(checkUserInfo, 2000);
    }
}


function computeManagerSalary()
{
    console.log("---start company_AddDividendLocalStorage()");
    var Dividends = null !== window.localStorage.getItem ("Dividend") ? JSON.parse(window.localStorage.getItem ("Dividend")) : [];
    //Dividends規格
    //{"companyID": A, "companyDividend": B, "companyPrice": C, "companyStock": D}
    var companiesDatas = Meteor.connection._mongo_livedata_collections.companies.find().fetch();
    var earnPerShare, release, managerSalary = 0;

    for (let i = 0 ; i < companiesDatas.length ; i++)
    {
        const ID = companiesDatas[i]._id;
        const companyIndex = Dividends.findIndex(a => a.companyID == ID);
        if (companyIndex === -1)
        {
            console.log("not found company  " + ID);
        }
        else
        {
            earnPerShare = Number(Dividends[companyIndex].companyDividend);
            release = Number(Dividends[companyIndex].companyStock);
            console.log("---computeManagerSalary()-----" + ID + "-----" + earnPerShare + "-----" + release + "-----");
            managerSalary += ((earnPerShare * release / 0.8075) * 0.05);
            console.log("---computeManagerSalary()-----" + managerSalary);
        }
    }

    //完成後自動開始新增資訊
    //但如果沒有經理薪水就不會新增
    if (managerSalary > 0)
        addManagerSalaryInfo(managerSalary);
    console.log("---complete company_AddDividendLocalStorage()");
    return managerSalary;
}

function addManagerSalaryInfo(managerSalary)
{
    console.log("start---addManagerSalaryInfo()");
    managerSalary = Number(managerSalary);
    var classManagerSalaryInfo = $("#managerSalaryInfoNumber");
    if(classManagerSalaryInfo.length === 0)
    {
        $('<div class="media account-info-item border-grid-body" id = "managerSalaryInfo"><div class="col-6 text-right border-grid" id = "managerSalaryInfoTitle"><h2>' + Dict[lan].managerTotalSalary + '</h2></div></div>').insertAfter($('.card-title.mb-1')[0]);
        $('<div class="col-6 text-right border-grid" id = "managerSalaryInfoNumber"><h2>$ ' + managerSalary.toFixed() + '</h2></div>').insertAfter($('#managerSalaryInfoTitle')[0]);
    }
    else
    {
        $("#managerSalaryInfoNumber")[0].innerHTML = "<h2>$ " + managerSalary.toFixed() + "</h2>";
    }
    console.log("complete---addManagerSalaryInfo()");
}


function checkUserHoldStock(userID, CUHS_runNumber, managerSalary)
{
    const directors = Meteor.connection._mongo_livedata_collections.directors.find().fetch();
    if (directors.length > 0)
    {
        console.log("start checkUserHoldStock()");
        if ($("[data-toggle-panel=stock]").parent().next().children().last().length > 0)
            addNotCompleteMessage();
        console.log("userID: " + userID + "   CUHS_runNumber: " + CUHS_runNumber + "   managerSalary: " + managerSalary);
        var userStockInfo = null !== window.sessionStorage.getItem ("userStockInfo") ? JSON.parse(window.sessionStorage.getItem ("userStockInfo")) : [];
        //userStcokInfo的格式:
        //{"userID": CWgfhqxbrJMxsknrb, "userCompany": [{"companyID": aaa, "userHold": number}, {}]}
        var userIndex = userStockInfo.findIndex(a => a.userID == userID);
        if (userIndex == -1)
        {
            userStockInfo.push({"userID": userID, "userCompany": []});
            userIndex = userStockInfo.findIndex(a => a.userID == userID);
        }

        var ID, hold;

        var isChange = false;
        
        for (let i = 0 ; i < directors.length ; i++)
        {
            ID = String(directors[i].companyId);
            hold = Number(directors[i].stocks);
            console.log("-----" + ID + "-----" + hold + "-----");

            const companyIndex = userStockInfo[userIndex].userCompany.findIndex(b => b.companyID == ID);
            if (companyIndex != -1)
            {
                if (Number(userStockInfo[userIndex].userCompany[companyIndex].userHold) == hold)
                {
                    //console.log("dont need update this company");
                }
                else
                {
                    isChange = true;
                    userStockInfo[userIndex].userCompany.splice(companyIndex, 1);
                    userStockInfo[userIndex].userCompany.push({"companyID": ID, "userHold": hold});
                }
            }
            else
            {
                isChange = true;
                userStockInfo[userIndex].userCompany.push({"companyID": ID, "userHold": hold});
            }
        }


        //怕是資料還沒更新完成就開始執行,如果完全沒有變化會再次執行,共確認3次
        if (isChange)
        {
            window.sessionStorage.setItem ("userStockInfo", JSON.stringify(userStockInfo));
            addCompleteMessage();
            setTimeout(addUserProfitInfo, 10, userID, managerSalary);
        }
        else
        {
            if (CUHS_runNumber < 3)
                setTimeout(checkUserHoldStock, 100, userID, CUHS_runNumber+1, managerSalary);
            else
            {
                addCompleteMessage();
                setTimeout(addUserProfitInfo, 10, userID, managerSalary);
            }
        }
    }
}

function addCompleteMessage()
{
    var pageNum = "1";
    if (($(".page-item.active")[0] !== undefined) && ($(".page-item.active")[0] !== null))
        pageNum = $(".page-item.active")[0].textContent;
    
    if ($("#CompleteMessage").length === 0) {
        $(`<button class="btn btn-danger btn-sm" type="button" disabled="disabled" id="CompleteMessage">第${pageNum}頁統計完成</button>`)
          .insertAfter($("[data-toggle-panel=stock]").parent().next().children().last());
    }
    else
    {
        $("#CompleteMessage")[0].innerHTML = `第${pageNum}頁統計完成`;
    }
}

function addNotCompleteMessage()
{
    //const pageNum = $(".page-item.active").text();
    if ($("#CompleteMessage").length === 0) {
        $(`<button class="btn btn-danger btn-sm" type="button" disabled="disabled" id="CompleteMessage">還沒有統計完成</button>`)
          .insertAfter($("[data-toggle-panel=stock]").parent().next().children().last());

        if ($("#clear-asset-message-btn").length > 0)       //為了將訊息移動到正確的位置
        {
            $("#clear-asset-message-btn").click();
            if ($("#compute-btn").length > 0)
                $("#compute-btn").click();
        }
    }
    else
    {
        $("#CompleteMessage")[0].innerHTML = `還沒有統計完成`;
    } 
}

function checkMyHoldStock()
{
    var userStockInfo = null !== window.sessionStorage.getItem ("userStockInfo") ? JSON.parse(window.sessionStorage.getItem ("userStockInfo")) : [];
    //userStcokInfo的格式:
    //{"userID": CWgfhqxbrJMxsknrb, "userCompany": [{"companyID": aaa, "userHold": number}, {}]}
    const userID = myID;
    var userIndex = userStockInfo.findIndex(a => a.userID == userID);
    if (userIndex == -1)
    {
        userStockInfo.push({"userID": userID, "userCompany": []});
        userIndex = userStockInfo.findIndex(a => a.userID == userID);
    }

    var ID, hold;
    const directors = myHoldStock;

    //避免重複不斷的更新
    if (directors.length != userStockInfo[userIndex].userCompany.length)
    {
        
        for (let i = 0 ; i < directors.length ; i++)
        {
            ID = String(directors[i].companyId);
            hold = Number(directors[i].stocks);
            console.log("-----" + ID + "-----" + hold + "-----");

            const companyIndex = userStockInfo[userIndex].userCompany.findIndex(b => b.companyID == ID);
            if (companyIndex != -1)
            {
                if (Number(userStockInfo[userIndex].userCompany[companyIndex].userHold) == hold)
                {
                    //console.log("dont need update this company");
                }
                else
                {
                    userStockInfo[userIndex].userCompany.splice(companyIndex, 1);
                    userStockInfo[userIndex].userCompany.push({"companyID": ID, "userHold": hold});
                }
            }
            else
            {
                userStockInfo[userIndex].userCompany.push({"companyID": ID, "userHold": hold});
            }
        }
        window.sessionStorage.setItem ("userStockInfo", JSON.stringify(userStockInfo));
    }
}


function addUserProfitInfo(userID, managerSalary)
{
    const userStockInfo = null !== window.sessionStorage.getItem ("userStockInfo") ? JSON.parse(window.sessionStorage.getItem ("userStockInfo")) : [];
    //userStcokInfo的格式:
    //{"userID": CWgfhqxbrJMxsknrb, "userCompany": [{"companyID": aaa, "userHold": number}, {}]}
    const userIndex = userStockInfo.findIndex(a => a.userID == userID);
    //理論上到這邊userIndex就不可能是-1了啦.....

    const users = Meteor.connection._mongo_livedata_collections.users.find().fetch();
    //console.log("for debug");
    //console.log("userID:  " + userID);
    //console.log(users);
    const users_i = users.findIndex(u => u._id == String(userID));
    console.log("user_i:  " + users_i);     //for debug

    const Dividends = null !== window.localStorage.getItem ("Dividend") ? JSON.parse(window.localStorage.getItem ("Dividend")) : [];
    //Dividends規格
    //{"companyID": A, "companyDividend": B, "companyPrice": C, "companyStock": D}
    const cash = Number(users[users_i].profile.money);

    var classUserProfitInfo, userAssets = 0, userProfit = 0, userCompanyNumber = 0;
    var price, earnPerShare;

    
    for (let k = 0 ; k < userStockInfo[userIndex].userCompany.length ; k++)
    {
        price = 0;
        earnPerShare = 0;
        const dividendIndex = Dividends.findIndex(b => b.companyID == userStockInfo[userIndex].userCompany[k].companyID);
        if (dividendIndex != -1)
        {
            price = Number(Dividends[dividendIndex].companyPrice);
            earnPerShare = Number(Dividends[dividendIndex].companyDividend);
        }
        userAssets += price * userStockInfo[userIndex].userCompany[k].userHold;
        userProfit += earnPerShare * userStockInfo[userIndex].userCompany[k].userHold;
        userCompanyNumber += 1;
    }
    //console.log("compute complete");

    var usingCash = 0;                  //正在用於買單的錢
    var sellingStockWorth = 0;          //正在賣的股票價值,以參考價計算
    if (userID == myID)
    {
        const orders = myOrders;
        const orderType_buy = "購入";
        const orderType_sell = "賣出";
        
        for (let j = 0 ; j < orders.length ; j++)
        {
            const amount = Number(orders[j].amount);
            const done = Number(orders[j].done);
            if (orders[j].orderType === orderType_buy)
            {
                const unitPrice = Number(orders[j].unitPrice);
                usingCash += (unitPrice * (amount - done));
            }
            else if (orders[j].orderType === orderType_sell)
            {
                const dividendIndex = Dividends.findIndex(b => b.companyID == String(orders[j].companyId));
                if (dividendIndex === -1)
                    price = 0;
                else
                    price = Number(Dividends[dividendIndex].companyPrice);
                sellingStockWorth += (price * (amount - done));
            }
            else
            {
                console.log("不是買單也不是賣單,你怎麼做到的......");
            }
        }
        console.log("usingCash:  " + usingCash);
        console.log("sellingStockWorth" + sellingStockWorth);
    }



    console.log("start compute tax");
    const tax = computeTax((userAssets + userProfit + managerSalary + cash + usingCash + sellingStockWorth));
    console.log("compute complete");
    var classUserTaxInfo = $("#userTaxInfoNumber");
    if(classUserTaxInfo.length === 0)
    {
        $('<div class="media account-info-item border-grid-body" id = "userTaxInfo"><div class="col-6 text-right border-grid" id = "userTaxInfoTitle"><h2>' + Dict[lan].userTotalTax + '</h2></div></div>').insertAfter($('.card-title.mb-1')[0]);
        $('<div class="col-6 text-right border-grid" id = "userTaxInfoNumber"><h2>$ ' + tax + '</h2></div>').insertAfter($('#userTaxInfoTitle')[0]);
    }
    else
    {
        console.log("start update info");
        $("#userTaxInfoNumber")[0].innerHTML = "<h2>$ " + tax + "</h2>";
    }


    classUserProfitInfo = $("#userProfitInfoNumber");
    if(classUserProfitInfo.length === 0)
    {
        console.log("start add info");

        $('<div class="media account-info-item border-grid-body" id = "userProfitInfo"><div class="col-6 text-right border-grid" id = "userProfitInfoTitle"><h2>' + Dict[lan].userTotalProfit + '</h2></div></div>').insertAfter($('.card-title.mb-1')[0]);
        $('<div class="col-6 text-right border-grid" id = "userProfitInfoNumber"><h2>$ ' + userProfit.toFixed() + '</h2></div>').insertAfter($('#userProfitInfoTitle')[0]);

        $('<div class="media account-info-item border-grid-body" id = "userAssetsInfo"><div class="col-6 text-right border-grid" id = "userAssetsInfoTitle"><h2>' + Dict[lan].userTotalAssets + '</h2></div></div>').insertAfter($('.card-title.mb-1')[0]);
        $('<div class="col-6 text-right border-grid" id = "userAssetsInfoNumber"><h2>$ ' + userAssets + '</h2></div>').insertAfter($('#userAssetsInfoTitle')[0]);

        $('<div class="media account-info-item border-grid-body" id = "userCompanyNumberInfo"><div class="col-6 text-right border-grid" id = "userCompanyNumberInfoTitle"><h2>' + Dict[lan].userTotalCompanyNumber + '</h2></div></div>').insertAfter($('.card-title.mb-1')[0]);
        $('<div class="col-6 text-right border-grid" id = "userCompanyNumberInfoNumber"><h2> ' + userCompanyNumber + '</h2></div>').insertAfter($('#userCompanyNumberInfoTitle')[0]);
    }
    else
    {
        console.log("start update info");
        $("#userProfitInfoNumber")[0].innerHTML = "<h2>$ " + userProfit.toFixed() + "</h2>";
        $("#userAssetsInfoNumber")[0].innerHTML = "<h2>$ " + userAssets + "</h2>";
        $("#userCompanyNumberInfoNumber")[0].innerHTML = "<h2> " + userCompanyNumber + "</h2>";
    }

}



// 稅率表:資產上限、稅率、累進差額
function computeTax(input)
{
    const taxRateTable = [
        { asset: 10000, rate: 0.00, adjustment: 0 },
        { asset: 100000, rate: 0.03, adjustment: 300 },
        { asset: 500000, rate: 0.06, adjustment: 3300 },
        { asset: 1000000, rate: 0.09, adjustment: 18300 },
        { asset: 2000000, rate: 0.12, adjustment: 48300 },
        { asset: 3000000, rate: 0.15, adjustment: 108300 },
        { asset: 4000000, rate: 0.18, adjustment: 198300 },
        { asset: 5000000, rate: 0.21, adjustment: 318300 },
        { asset: 6000000, rate: 0.24, adjustment: 468300 },
        { asset: 7000000, rate: 0.27, adjustment: 648300 },
        { asset: 8000000, rate: 0.30, adjustment: 858300 },
        { asset: 9000000, rate: 0.33, adjustment: 1098300 },
        { asset: 10000000, rate: 0.36, adjustment: 1368300 },
        { asset: 11000000, rate: 0.39, adjustment: 1668300 },
        { asset: 12000000, rate: 0.42, adjustment: 1998300 },
        { asset: 13000000, rate: 0.45, adjustment: 2358300 },
        { asset: 14000000, rate: 0.48, adjustment: 2748300 },
        { asset: 15000000, rate: 0.51, adjustment: 3168300 },
        { asset: 16000000, rate: 0.54, adjustment: 3618300 },
        { asset: 17000000, rate: 0.57, adjustment: 4098300 },
        { asset: Infinity, rate: 0.60, adjustment: 4608300 },
      ];
    const { rate, adjustment } = taxRateTable.find(e => input < e.asset);
    const output = Math.ceil(input * rate - adjustment);
    return output;
}


/*************accountInfo*************/
/*************************************/
/*************************************/
/**************Language***************/


var lan =  "";
lan = null !== window.localStorage.getItem ("PM_language") ? window.localStorage.getItem ("PM_language") : "tw";
/*function ChangeLanguage(l){
    if(lan === l)return;
    lan = l;
    window.localStorage.setItem ("PM_language",l);
    window.location.reload();
}*/
var Dict = {
    tw:
    {
        totalProfitInThisPage: "本頁預計分紅:",
        updateDividendScript: "更新預估分紅腳本",
        userTotalAssets: "使用者股票總值:",
        userTotalProfit: "預估股票分紅:",
        userTotalCompanyNumber: "持有公司總數:",
        managerTotalSalary: "預估經理薪水:",
        userTotalTax: "預估本季稅金:",
        PEratio: "本益比排行",
        stockPEInfo: "本益比",
        stockManagerSalaryInfo: "經理薪水", 
        stockProfitInfo: "現金股利", 
        stockWorthInfo: "股票總值", 
    },
    en:
    {
        totalProfitInThisPage: "Total profit in this page :",
        updateDividendScript: "Update Dividend Script",
        userTotalAssets: "User stock worth:",
        userTotalProfit: "Estimated stock dividends:",
        userTotalCompanyNumber: "Hold the total number of companies:",
        managerTotalSalary: "Estimated manager salary:",
        userTotalTax: "Estimated tax for this season:",
        PEratio: "PE ratio",
        stockPEInfo: "PE",
        stockManagerSalaryInfo: "Manager salary", 
        stockProfitInfo: "Dividend", 
        stockWorthInfo: "Stock worth", 
    },
    jp:
    {
        totalProfitInThisPage: "本ページ利回り総額:",
        updateDividendScript: "更新預估分紅腳本",
        userTotalAssets: "使用者股票總值:",
        userTotalProfit: "預估股票分紅:",
        userTotalCompanyNumber: "持有公司總數:",
        managerTotalSalary: "預估經理薪水:",
        userTotalTax: "預估本季稅金:",
        PEratio: "本益比排行",
        stockPEInfo: "本益比",
        stockManagerSalaryInfo: "經理薪水", 
        stockProfitInfo: "現金股利", 
        stockWorthInfo: "股票總值", 
    },
    marstw:
    {
        totalProfitInThisPage: "這ㄘ可yee拿ㄉ$$:",
        updateDividendScript: "有★★★版",
        userTotalAssets: "股票ㄉ$$:",
        userTotalProfit: "這ㄘ會拿ㄉ$$:",
        userTotalCompanyNumber: "偶ㄐ間公ㄙ:",
        managerTotalSalary: "雞李ㄉ西水:",
        userTotalTax: "ㄋ要交ㄉ茄:",
        PEratio: "ㄅyee逼排行",
        stockPEInfo: "ㄅyee逼",
        stockManagerSalaryInfo: "ㄐ李溪水", 
        stockProfitInfo: "會給ㄉ前", 
        stockWorthInfo: "股票ㄓˊ", 
    }
};


/**************Language***************/
/*************************************/

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址