TMVN Club Finance CN

Trophymanager: TrophyManager: 使用这个脚本来估算这个赛季的财政预算。它帮助我回答这样的问题: 我可以用多少钱买明星球员?应维持多少工资?需要买卖多少球员才能负担得起建设设施?它不能完全准确,但足以给俱乐部的财务状况一个大致的看法。

// ==UserScript==
// @name         TMVN Club Finance CN
// @namespace    https://trophymanager.com
// @version      1.2024060801
// @author       Xpand 修复:提瓦特元素反应(ID:4731723),汉化:太原龙城(ID:246770)
// @description  Trophymanager: TrophyManager: 使用这个脚本来估算这个赛季的财政预算。它帮助我回答这样的问题: 我可以用多少钱买明星球员?应维持多少工资?需要买卖多少球员才能负担得起建设设施?它不能完全准确,但足以给俱乐部的财务状况一个大致的看法。
// @match      https://trophymanager.com/club/*
// @match      https://trophymanager.com/club/*/
// @exclude      https://trophymanager.com/club/*/squad/
// @grant        none
// ==/UserScript==
 
(function () {
	'use strict';
 
	const NOTE = "如果有杯赛、国际比赛,或者经常对阵大俱乐部,推荐球场容量应该更大一些。";
 
	const COLOR = {
		DEFAULT: "color:White;",
		SPECTATOR: "color:Orange;",
		COMMERCE: "color:Aqua;",
		SEAT: "color:Yellow;",
		INJURY: "color:GreenYellow;",
		YATG: "color:Yellow;",
		IN: "color:Blue;",
		OUT: "color:Black;",
		FINAL: "color:Darkred;",
		NOTE: "color:Darkgray"
	}
 
	const COMMERCE_PRICE = {
		FAST_FOOD_PLACE: 4,
		MERCHANDISE_STAND: 10,
		MERCHANDISE_STORE: 20,
		RESTAURANT: 5,
		SAUSAGE_STAND: 2.5
	}
 
	const COMMERCE_INCOME_FACTOR = {
		FAST_FOOD_PLACE: 17,
		MERCHANDISE_STAND: 17,
		MERCHANDISE_STORE: 12,
		RESTAURANT: 17,
		SAUSAGE_STAND: 17
	}
 
	const CALCULATE_EXTRA_MATCH = {
		FAST_FOOD_PLACE: 1,
		MERCHANDISE_STAND: 1,
		MERCHANDISE_STORE: 0,
		RESTAURANT: 1,
		SAUSAGE_STAND: 1
	}
 
	const COMMERCE_MAINTAIN = {
		FAST_FOOD_PLACE: 45000,
		MERCHANDISE_STAND: 112500,
		RESTAURANT: 56250,
		SAUSAGE_STAND: 28125
	}
 
	const TICKET_PRICE = 200;
	const SEAT_MAINTAIN = 35;
 
	const MERCHANDISE_STORE_MAINTAIN = [0, 50000, 150000, 250000, 350000, 450000, 550000, 650000, 750000, 850000, 950000];
	const PARKING_MAINTAIN = [0, 10000, 50000, 100000, 150000, 250000, 375000, 500000, 625000, 800000, 1000000];
	const TOILETS_MAINTAIN = [0, 10000, 50000, 100000, 150000, 250000, 375000, 500000, 625000, 800000, 1000000];
	const PHYSIO_MAINTAIN = [0, 10000, 50000, 100000, 150000, 250000, 375000, 500000, 625000, 800000, 1000000];
 
	const TRAINING_GROUNDS_MAINTAIN = [0, 30000, 185000, 612500, 1250000, 2150000, 3650000, 5350000, 7650000, 10250000, 13500000];
	const YOUTH_ACADEMY_MAINTAIN = [0, 25000, 150000, 500000, 1000000, 1750000, 3000000, 4350000, 6250000, 8350000, 11000000];
	const MEDICAL_CENTER_MAINTAIN = [0, 50000, 250000, 625000, 1250000, 2000000, 3000000, 4500000, 6000000, 8000000, 10000000];
 
	const FLOODLIGHTS_MAINTAIN = [0, 100000, 500000];
	const PITCH_DRAINING_MAINTAIN = [0, 50000];
	const PITCH_COVER_MAINTAIN = [0, 50000];
	const SPRINKLERS_MAINTAIN = [0, 50000];
	const HEATING_MAINTAIN = [0, 350000];
 
	const TV_MONEY = [0, 11000000, 10000000, 9500000, 9000000, 8500000, 8000000];
	const SPONSORS = [0, 25000000, 22500000, 20000000, 17500000, 15000000, 12500000];
 
	var physioLevel,
	pitchDrainingLevel,
	pitchCoverLevel,
	sprinklersLevel,
	heatingLevel,
	floodlightsLevel,
	parkingLevel,
	toiletsLevel,
	restaurantLevel,
	merchandiseStandLevel,
	fastFoodPlaceLevel,
	sausageStandLevel,
	merchandiseStoreLevel,
	medicalCenterLevel,
	youthAcademyLevel,
	trainingGroundsLevel;
 
	var estimateAttendance,
	averageAttendance,
	currentCapacity,
	recommendCapacity,
	ticketIncome,
	seatMantain,
	ticketProfit,
	commerceIncome,
	commerceMaintain,
	commerceProfit,
	tvMoney,
	sponsors,
	otherMaintain,
	totalProfit;
 
	var extraHomeMatch,
	tradePlayer,
	buyStar,
	playerWage,
	staffWage,
	building,
	adjust;
	extraHomeMatch = tradePlayer = buyStar = playerWage = staffWage = building = adjust = 0;
 
	var myClubId,
	clubId,
	division,
	fanBase = -1;
	var getHomeIdInterval = setInterval(getHomeId, 500);
	var mainInterval = setInterval(main, 500);
 
/**
 * 获取home ID。
 * 该函数首先检查变量myClubId是否已定义,如果已定义,则清除定时器getHomeIdInterval。
 * 如果myClubId未定义,尝试从页面元素中获取俱乐部ID,并赋值给myClubId。
 *
 * @returns {void} 该函数没有返回值。
 */
function getHomeId() {
    // 检查myClubId是否已定义,若已定义则清除定时器
    if (myClubId != undefined) {
        clearInterval(getHomeIdInterval);
    } else {
        // 尝试捕获异常,从页面中获取俱乐部ID
        try {
            myClubId = $('.club.faux_link').attr('club');
        } catch (e) {}
    }
}
 
	/**
 * 主函数,用于获取并处理与足球俱乐部相关的信息。
 * 无参数。
 * 无显式返回值,但可能在执行过程中修改全局变量或执行其他副作用。
 */
function main() {
    // 检查是否有设置的myClubId,若无则不执行后续逻辑
    if (myClubId != '') {
        // 清除可能存在的定时器
        clearInterval(mainInterval);
        // 从当前页面URL中提取clubId
        clubId = $('a.selected.none').attr('href').split('/')[2];
        // 获取页面中指定元素的division属性值
        division = $('.box_sub_header.align_center a')[$('.box_sub_header.align_center a').length - 1].getAttribute('division');
        // 从页面元素中提取俱乐部信息,并查找球迷基数
        var clubInfoArr = $('#club_info div')[0].innerText.split('\n');
        for (var i = clubInfoArr.length - 1; i >= 0; i--) {
            if (clubInfoArr[i].trim().startsWith('球迷协会: ')) {
                fanBase = clubInfoArr[i].trim().split(' ')[1].replace(/,/g, ''); // 移除逗号并转换为数字
                // 检查fanBase是否为数字,若不是则设为0
                if (isNaN(fanBase)) {
                    fanBase = 0; // 在实时比赛时间时,可能无法获取准确的球迷基数
                } else {
                    fanBase = Number(fanBase);
                }
                break;
            }
        }
        console.log(clubInfoArr);
        // 若fanBase为-1,则表示这是B队,不进行后续操作
        if (fanBase == -1) {
            return;
        }
        console.log("check");
        // 检查是否自己的俱乐部,是则获取薪资信息
        if (myClubId == clubId) {
            let playerWeekWage = -1, // 球员周薪
                staffWeekWage = -1; // 工作人员周薪
            // 设置jQuery ajax请求为同步
            $.ajaxSetup({
                async: false
            });
 
            // 请求球员薪资信息
            $.ajax('https://trophymanager.com/finances/wages/', {
                type: "GET",
                dataType: 'html',
                crossDomain: true,
                success: function (response) {
                    try {
                        // 提取并处理最后一名球员的周薪信息
                        let playerWageTr = $('#tab0 tr', response)[$('#tab0 tr', response).length - 1];
                        playerWeekWage = Number($('td', playerWageTr)[1].innerText.replace(/,/g, ''));
                    } catch (e) {}
 
                    try {
                        // 提取并处理最后一名工作人员的周薪信息
                        let staffWageTr = $('#tab1 tr', response)[$('#tab1 tr', response).length - 1];
                        staffWeekWage = Number($('td', staffWageTr)[2].innerText.replace(/,/g, ''));
                    } catch (e) {}
                },
                error: function (e) {}
            });
 
            // 恢复jQuery ajax请求为异步
            $.ajaxSetup({
                async: true
            });
            // 更新全局变量
            if (playerWeekWage != -1) {
                playerWage = playerWeekWage;
            }
            if (staffWeekWage != -1) {
                staffWage = staffWeekWage;
            }
        }
 
        // 准备数据并呈现
        parepareData();
        presentation();
    }
}
	function parepareData() {
		$.ajaxSetup({
			async: false
		});
 
		$.ajax('https://trophymanager.com/stadium/' + clubId, {
			type: "GET",
			dataType: 'html',
			crossDomain: true,
			success: function (response) {
				let facility = $('map[name="facility_map"]', response)[0];
 
				let stadium = facility.children[0];
 
				let floodlights = facility.children[2];
				let parking = facility.children[6];
				let toilets = facility.children[9];
 
				let restaurant = facility.children[7];
				let merchandiseStand = facility.children[4];
				let fastFoodPlace = facility.children[1];
				let sausageStand = facility.children[8];
				let merchandiseStore = facility.children[5];
 
				let medicalCenter = facility.children[3];
 
				let youthAcademy = facility.children[11];
				let trainingGrounds = facility.children[10];
 
				let stadiumElementArr = $('p', new DOMParser().parseFromString(stadium.getAttribute('tooltip'), 'text/html'));
 
				currentCapacity = Number(stadiumElementArr[1].innerText.split(' ')[1].replace(/,/g, ''));
 
				let physioText = stadiumElementArr[2].innerText.trim();
				if (physioText == '理疗师 ') {
					physioLevel = 0;
				} else {
               physioLevel = Number(physioText.substr(5, physioText.length - 5 - 1)); //'Physio [' = 8 || '理疗师 [' = 5
 }

				$('img', stadiumElementArr[4])[0].src.endsWith("small_red_x.png") ? pitchDrainingLevel = 0 : pitchDrainingLevel = 1;
				$('img', stadiumElementArr[5])[0].src.endsWith("small_red_x.png") ? pitchCoverLevel = 0 : pitchCoverLevel = 1;
				$('img', stadiumElementArr[6])[0].src.endsWith("small_red_x.png") ? sprinklersLevel = 0 : sprinklersLevel = 1;
				$('img', stadiumElementArr[7])[0].src.endsWith("small_red_x.png") ? heatingLevel = 0 : heatingLevel = 1;
 
				floodlightsLevel = identifyFacilityLevel(floodlights);
				parkingLevel = identifyFacilityLevel(parking);
				toiletsLevel = identifyFacilityLevel(toilets);
 
				restaurantLevel = identifyFacilityLevel(restaurant);
				merchandiseStandLevel = identifyFacilityLevel(merchandiseStand);
				fastFoodPlaceLevel = identifyFacilityLevel(fastFoodPlace);
				sausageStandLevel = identifyFacilityLevel(sausageStand);
				merchandiseStoreLevel = identifyFacilityLevel(merchandiseStore);
 
				medicalCenterLevel = identifyFacilityLevel(medicalCenter);
 
				youthAcademyLevel = identifyFacilityLevel(youthAcademy);
				trainingGroundsLevel = identifyFacilityLevel(trainingGrounds);
 
				averageAttendance = calculateAverageAttendance(parkingLevel, toiletsLevel, floodlightsLevel, fanBase, currentCapacity);
				estimateAttendance = calculateEstimateAttendance(parkingLevel, toiletsLevel, floodlightsLevel, fanBase, currentCapacity);
				recommendCapacity = calculateRecommendCapacity(parkingLevel, toiletsLevel, floodlightsLevel, fanBase);
 
				ticketIncome = calculateTicketIncome(extraHomeMatch, averageAttendance);
				seatMantain = calculateSeatMaintain(currentCapacity);
				ticketProfit = ticketIncome - seatMantain;
 
				commerceIncome = calculateCommerceIncome(extraHomeMatch, averageAttendance, restaurantLevel, merchandiseStandLevel, fastFoodPlaceLevel, sausageStandLevel, merchandiseStoreLevel);
				commerceMaintain = calculateCommerceMaintain(restaurantLevel, merchandiseStandLevel, fastFoodPlaceLevel, sausageStandLevel, merchandiseStoreLevel);
				commerceProfit = commerceIncome - commerceMaintain;
 
				tvMoney = calculateTVMoney(division);
				sponsors = calculateSponsors(division);
				otherMaintain = calculateOtherMaintain(physioLevel, pitchDrainingLevel, pitchCoverLevel, sprinklersLevel, heatingLevel, floodlightsLevel, parkingLevel, toiletsLevel, medicalCenterLevel, youthAcademyLevel, trainingGroundsLevel);
 
				try {
					if (playerWage == 0) { //not home club
						playerWage = JSON.parse(localStorage.getItem(clubId + "_SQUAD_VALUE")).Wage; //TMVN Squad Value script
					}
				} catch (e) {}
 
				totalProfit = ticketProfit + commerceProfit + tvMoney + sponsors + tradePlayer - otherMaintain - playerWage * 12 - staffWage * 12 - building - buyStar + adjust;
 
			},
			error: function (e) {}
		});
 
		$.ajaxSetup({
			async: true
		});
	}
 
	function presentation() {
		let stadiumArea =
			'<div class="box">' +
			'<div class="box_head"><h2 class="std">财政预算</h2></div>' +
			'<div class="box_body">' +
			'<div class="box_shadow"></div>' +
			'<div id="tm_script_club_stadium_area_id" class="content_menu"></div>' +
			'<div class="box_footer"><div></div></div>' +
			'</div>';
 
		$(".column1").append(stadiumArea);
 
		let stadiumArea_content = "<table>";
		stadiumArea_content += '<tr><td style=' + COLOR.DEFAULT + '>球迷数量: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_fanbase" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.SPECTATOR + '>球场容量: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_current_capacity" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
 
		stadiumArea_content += '<tr><td style=' + COLOR.SPECTATOR + '>灯光: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_floodlights" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.SPECTATOR + '>停车场: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_parking" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.SPECTATOR + '>厕所: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_toilets" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
 
		stadiumArea_content += '<tr><td style=' + COLOR.INJURY + '>理疗师: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_physio" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.INJURY + '>排水系统: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_pitch_draining" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.INJURY + '>草皮覆盖: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_pitch_cover" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.INJURY + '>喷淋系统: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_sprinklers" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.INJURY + '>地热系统: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_heating" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.INJURY + '>医疗中心: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_medical_center" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
 
		stadiumArea_content += '<tr><td style=' + COLOR.COMMERCE + '>餐厅: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_restaurant" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.COMMERCE + '>纪念品摊: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_merchandise_stand" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.COMMERCE + '>快餐店: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_fast_food_place" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.COMMERCE + '>热狗摊: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_sausage_stand" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.COMMERCE + '>纪念品商店: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_merchandise_store" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
 
		stadiumArea_content += '<tr><td style=' + COLOR.YATG + '>青训学校: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_youth_academy" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.YATG + '>训练基地: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_training_grounds" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
 
		stadiumArea_content += '<tr><td style=' + COLOR.IN + '>额外的主场比赛: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_extra_home_match" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.IN + '>级别: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_division" type="text" class="embossed" style="width: 50px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += "</table>";
 
		stadiumArea_content += "<table>";
		stadiumArea_content += '<tr><td style=' + COLOR.IN + '>转会收支: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_trade_player" type="text" class="embossed" style="width: 80px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.OUT + '>引援预算: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_buy_star" type="text" class="embossed" style="width: 80px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.OUT + '>球员周薪: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_player_wage" type="text" class="embossed" style="width: 80px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.OUT + '>职员周薪: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_staff_wage" type="text" class="embossed" style="width: 80px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.OUT + '>工程花费: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_building" type="text" class="embossed" style="width: 80px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
		stadiumArea_content += '<tr><td style=' + COLOR.DEFAULT + '>其他调节项: </td><td style="text-align: right"><span style="display: inline-block;"><input id="tm_script_input_adjust" type="text" class="embossed" style="width: 80px; min-width: 50px; line-height: 100%; padding: 3px 3px 4px 3px; text-align: right;"></span></td></tr>';
 
		stadiumArea_content += '<tr><td colspan="2" style="text-align: center;"><span id="tm_script_button_calculate" class="button" style="margin-left: 3px;"><span class="button_border">计算</span></span></td></tr>';
		stadiumArea_content += "</table>";
 
		stadiumArea_content += "<table>";
		stadiumArea_content += '<tr><td><table><tr style=' + COLOR.SEAT + '><td>平均上座:</td><td style="text-align: right;"><span id="tm_script_span_average_attendance"></span></td></tr></table></td></tr>';
		stadiumArea_content += '<tr><td><table><tr style=' + COLOR.SEAT + '><td>推荐球场容量:</td><td style="text-align: right;"><span id="tm_script_span_recommend_capacity"></span></td></tr></table></td></tr>';
 
		stadiumArea_content += '<tr><td><table><tr style=' + COLOR.SPECTATOR + '><td>球票收入:</td><td style="text-align: right;"><span id="tm_script_span_ticket_income"></span></td></tr></table></td></tr>';
		stadiumArea_content += '<tr><td><table><tr style=' + COLOR.SPECTATOR + '><td>座位维护:</td><td style="text-align: right;"><span id="tm_script_span_seat_maintain"></span></td></tr></table></td></tr>';
		stadiumArea_content += '<tr><td><table><tr style=' + COLOR.SPECTATOR + '><td>球票利润:</td><td style="text-align: right;"><span id="tm_script_span_ticket_profit"></span></td></tr></table></td></tr>';
 
		stadiumArea_content += '<tr><td><table><tr style=' + COLOR.COMMERCE + '><td>商业收入:</td><td style="text-align: right;"><span id="tm_script_span_commerce_income"></span></td></tr></table></td></tr>';
		stadiumArea_content += '<tr><td><table><tr style=' + COLOR.COMMERCE + '><td>商业维护:</td><td style="text-align: right;"><span id="tm_script_span_commerce_maintain"></span></td></tr></table></td></tr>';
		stadiumArea_content += '<tr><td><table><tr style=' + COLOR.COMMERCE + '><td>商业利润:</td><td style="text-align: right;"><span id="tm_script_span_commerce_profit"></span></td></tr></table></td></tr>';
 
		stadiumArea_content += '<tr><td><table><tr style=' + COLOR.IN + '><td>转播收入:</td><td style="text-align: right;"><span id="tm_script_span_tv_money"></span></td></tr></table></td></tr>';
		stadiumArea_content += '<tr><td><table><tr style=' + COLOR.IN + '><td>赞助收入:</td><td style="text-align: right;"><span id="tm_script_span_sponsors"></span></td></tr></table></td></tr>';
		stadiumArea_content += '<tr><td><table><tr style=' + COLOR.OUT + '><td>非盈利维护:</td><td style="text-align: right;"><span id="tm_script_span_other_maintain"></span></td></tr></table></td></tr>';
		stadiumArea_content += '<tr><td><table><tr style=' + COLOR.FINAL + '><td>总收支:</td><td style="text-align: right;"><span id="tm_script_span_total_profit"></span></td></tr></table></td></tr>';
		stadiumArea_content += '<tr><td style="color:Darkgray; font-size:smaller; font-style:italic">' + NOTE + '</td></tr>';
		stadiumArea_content += "</table>";
 
		$("#tm_script_club_stadium_area_id").append(stadiumArea_content);
 
		$('#tm_script_input_fanbase').val(fanBase);
		$('#tm_script_input_current_capacity').val(currentCapacity);
 
		$('#tm_script_input_floodlights').val(floodlightsLevel);
		$('#tm_script_input_parking').val(parkingLevel);
		$('#tm_script_input_toilets').val(toiletsLevel);
 
		$('#tm_script_input_physio').val(physioLevel);
		$('#tm_script_input_pitch_draining').val(pitchDrainingLevel);
		$('#tm_script_input_pitch_cover').val(pitchCoverLevel);
		$('#tm_script_input_sprinklers').val(sprinklersLevel);
		$('#tm_script_input_heating').val(heatingLevel);
		$('#tm_script_input_medical_center').val(medicalCenterLevel);
 
		$('#tm_script_input_restaurant').val(restaurantLevel);
		$('#tm_script_input_merchandise_stand').val(merchandiseStandLevel);
		$('#tm_script_input_fast_food_place').val(fastFoodPlaceLevel);
		$('#tm_script_input_sausage_stand').val(sausageStandLevel);
		$('#tm_script_input_merchandise_store').val(merchandiseStoreLevel);
 
		$('#tm_script_input_youth_academy').val(youthAcademyLevel);
		$('#tm_script_input_training_grounds').val(trainingGroundsLevel);
 
		$('#tm_script_input_extra_home_match').val(extraHomeMatch);
		$('#tm_script_input_division').val(division);
		$('#tm_script_input_trade_player').val(tradePlayer);
		$('#tm_script_input_buy_star').val(buyStar);
		$('#tm_script_input_player_wage').val(playerWage);
		$('#tm_script_input_staff_wage').val(staffWage);
		$('#tm_script_input_building').val(building);
		$('#tm_script_input_adjust').val(adjust);
 
		$('#tm_script_span_average_attendance')[0].innerText = averageAttendance.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_recommend_capacity')[0].innerText = recommendCapacity.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
 
		$('#tm_script_span_ticket_income')[0].innerText = ticketIncome.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_seat_maintain')[0].innerText = seatMantain.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_ticket_profit')[0].innerText = ticketProfit.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
 
		$('#tm_script_span_commerce_income')[0].innerText = commerceIncome.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_commerce_maintain')[0].innerText = commerceMaintain.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_commerce_profit')[0].innerText = commerceProfit.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
 
		$('#tm_script_span_tv_money')[0].innerText = tvMoney.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_sponsors')[0].innerText = sponsors.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_other_maintain')[0].innerText = otherMaintain.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_total_profit')[0].innerText = totalProfit.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
 
		document.getElementById('tm_script_button_calculate').addEventListener('click', (e) => {
			calculate();
		});
	}
 
	function calculate() {
		let fanBaseCal = $('#tm_script_input_fanbase')[0].value.trim();
		let currentCapacityCal = $('#tm_script_input_current_capacity')[0].value.trim();
 
		let floodlightsLevelCal = $('#tm_script_input_floodlights')[0].value.trim();
		let parkingLevelCal = $('#tm_script_input_parking')[0].value.trim();
		let toiletsLevelCal = $('#tm_script_input_toilets')[0].value.trim();
 
		let physioLevelCal = $('#tm_script_input_physio')[0].value.trim();
		let pitchDrainingLevelCal = $('#tm_script_input_pitch_draining')[0].value.trim();
		let pitchCoverLevelCal = $('#tm_script_input_pitch_cover')[0].value.trim();
		let sprinklersLevelCal = $('#tm_script_input_sprinklers')[0].value.trim();
		let heatingLevelCal = $('#tm_script_input_heating')[0].value.trim();
		let medicalCenterLevelCal = $('#tm_script_input_medical_center')[0].value.trim();
 
		let restaurantLevelCal = $('#tm_script_input_restaurant')[0].value.trim();
		let merchandiseStandLevelCal = $('#tm_script_input_merchandise_stand')[0].value.trim();
		let fastFoodPlaceLevelCal = $('#tm_script_input_fast_food_place')[0].value.trim();
		let sausageStandLevelCal = $('#tm_script_input_sausage_stand')[0].value.trim();
		let merchandiseStoreLevelCal = $('#tm_script_input_merchandise_store')[0].value.trim();
 
		let youthAcademyLevelCal = $('#tm_script_input_youth_academy')[0].value.trim();
		let trainingGroundsLevelCal = $('#tm_script_input_training_grounds')[0].value.trim();
 
		let extraHomeMatchCal = $('#tm_script_input_extra_home_match')[0].value.trim();
		let divisionCal = $('#tm_script_input_division')[0].value.trim();
		let tradePlayerCal = $('#tm_script_input_trade_player')[0].value.trim();
		let buyStarCal = $('#tm_script_input_buy_star')[0].value.trim();
		let playerWageCal = $('#tm_script_input_player_wage')[0].value.trim();
		let staffWageCal = $('#tm_script_input_staff_wage')[0].value.trim();
		let buildingCal = $('#tm_script_input_building')[0].value.trim();
		let adjustCal = $('#tm_script_input_adjust')[0].value.trim();
 
		if (fanBaseCal == '' || currentCapacityCal == '' || floodlightsLevelCal == '' || parkingLevelCal == '' || toiletsLevelCal == '' || physioLevelCal == '' || pitchDrainingLevelCal == '' || pitchCoverLevelCal == '' || sprinklersLevelCal == '' || heatingLevelCal == '' || medicalCenterLevelCal == '' || restaurantLevelCal == '' || merchandiseStandLevelCal == '' || fastFoodPlaceLevelCal == '' || sausageStandLevelCal == '' || merchandiseStoreLevelCal == '' || youthAcademyLevelCal == '' || trainingGroundsLevelCal == '' || extraHomeMatchCal == '' || divisionCal == '' || tradePlayerCal == '' || buyStarCal == '' || playerWageCal == '' || staffWageCal == '' || buildingCal == '' || adjustCal == '') {
			alert('Enter value for all textboxs');
			return;
		}
 
		if (isNaN(fanBaseCal) || isNaN(currentCapacityCal) || isNaN(floodlightsLevelCal) || isNaN(parkingLevelCal) || isNaN(toiletsLevelCal) || isNaN(physioLevelCal) || isNaN(pitchDrainingLevelCal) || isNaN(pitchCoverLevelCal) || isNaN(sprinklersLevelCal) || isNaN(heatingLevelCal) || isNaN(medicalCenterLevelCal) || isNaN(restaurantLevelCal) || isNaN(merchandiseStandLevelCal) || isNaN(fastFoodPlaceLevelCal) || isNaN(sausageStandLevelCal) || isNaN(merchandiseStoreLevelCal) || isNaN(youthAcademyLevelCal) || isNaN(trainingGroundsLevelCal) || isNaN(extraHomeMatchCal) || isNaN(divisionCal) || isNaN(tradePlayerCal) || isNaN(buyStarCal) || isNaN(playerWageCal) || isNaN(staffWageCal) || isNaN(buildingCal) || isNaN(adjustCal)) {
			alert('Values must be a integer');
			return;
		}
 
		if (!(isInt(fanBaseCal) && isInt(currentCapacityCal) && isInt(floodlightsLevelCal) && isInt(parkingLevelCal) && isInt(toiletsLevelCal) && isInt(physioLevelCal) && isInt(pitchDrainingLevelCal) && isInt(pitchCoverLevelCal) && isInt(sprinklersLevelCal) && isInt(heatingLevelCal) && isInt(medicalCenterLevelCal) && isInt(restaurantLevelCal) && isInt(merchandiseStandLevelCal) && isInt(fastFoodPlaceLevelCal) && isInt(sausageStandLevelCal) && isInt(merchandiseStoreLevelCal) && isInt(youthAcademyLevelCal) && isInt(trainingGroundsLevelCal) && isInt(extraHomeMatchCal) && isInt(divisionCal) && isInt(tradePlayerCal) && isInt(buyStarCal) && isInt(playerWageCal) && isInt(staffWageCal) && isInt(buildingCal) && isInt(adjustCal))) {
			alert('Values must be a integer');
			return;
		}
 
		if (fanBaseCal < 0 || fanBaseCal > 100000) {
			alert('Fanbase value is between 0 - 100000');
			return;
		}
		if (currentCapacityCal < 0 || currentCapacityCal > 200000) {
			alert('Current stadium capacity value is between 0 - 200000');
			return;
		}
		if (floodlightsLevelCal < 0 || floodlightsLevelCal > 2) {
			alert('Floodlights level value is between 0 - 2');
			return;
		}
		if (parkingLevelCal < 0 || parkingLevelCal > 10) {
			alert('Parking level value is between 0 - 10');
			return;
		}
		if (toiletsLevelCal < 0 || toiletsLevelCal > 10) {
			alert('Toilets level value is between 0 - 10');
			return;
		}
		if (physioLevelCal < 0 || physioLevelCal > 10) {
			alert('Physio level value is between 0 - 10');
			return;
		}
		if (pitchDrainingLevelCal < 0 || pitchDrainingLevelCal > 1) {
			alert('Pitch draining level value is between 0 - 1');
			return;
		}
		if (pitchCoverLevelCal < 0 || pitchCoverLevelCal > 1) {
			alert('Pitch cover level value is between 0 - 1');
			return;
		}
		if (sprinklersLevelCal < 0 || sprinklersLevelCal > 1) {
			alert('Sprinklers level value is between 0 - 1');
			return;
		}
		if (heatingLevelCal < 0 || heatingLevelCal > 1) {
			alert('Heating level value is between 0 - 1');
			return;
		}
		if (medicalCenterLevelCal < 0 || medicalCenterLevelCal > 10) {
			alert('Medical center level value is between 0 - 10');
			return;
		}
		if (restaurantLevelCal < 0 || restaurantLevelCal > 10) {
			alert('Restaurant level value is between 0 - 10');
			return;
		}
		if (merchandiseStandLevelCal < 0 || merchandiseStandLevelCal > 10) {
			alert('Merchandise stand level value is between 0 - 10');
			return;
		}
		if (fastFoodPlaceLevelCal < 0 || fastFoodPlaceLevelCal > 10) {
			alert('Fast food place level value is between 0 - 10');
			return;
		}
		if (sausageStandLevelCal < 0 || sausageStandLevelCal > 10) {
			alert('Sausage stand level value is between 0 - 10');
			return;
		}
		if (merchandiseStoreLevelCal < 0 || merchandiseStoreLevelCal > 10) {
			alert('Merchandise store level value is between 0 - 10');
			return;
		}
		if (youthAcademyLevelCal < 0 || youthAcademyLevelCal > 10) {
			alert('Youth academy level value is between 0 - 10');
			return;
		}
		if (trainingGroundsLevelCal < 0 || trainingGroundsLevelCal > 10) {
			alert('Training grounds level value is between 0 - 10');
			return;
		}
		if (extraHomeMatchCal < 0 || extraHomeMatchCal > 50) {
			alert('Extra home match value is between 0 - 50');
			return;
		}
		if (divisionCal < 1 || divisionCal > 6) {
			alert('Division value is between 1 - 6');
			return;
		}
		if (playerWageCal < 0) {
			alert('Player wage value must be >= 0');
			return;
		}
		if (staffWageCal < 0) {
			alert('Staff wage value must be >= 0');
			return;
		}
		if (buildingCal < 0) {
			alert('Building value must be >= 0');
			return;
		}
 
		let averageAttendanceCal = calculateAverageAttendance(parkingLevelCal, toiletsLevelCal, floodlightsLevelCal, fanBaseCal, currentCapacityCal);
		let estimateAttendanceCal = calculateEstimateAttendance(parkingLevelCal, toiletsLevelCal, floodlightsLevelCal, fanBaseCal, currentCapacityCal);
		let recommendCapacityCal = calculateRecommendCapacity(parkingLevelCal, toiletsLevelCal, floodlightsLevelCal, fanBaseCal);
 
		let ticketIncomeCal = calculateTicketIncome(extraHomeMatchCal, averageAttendanceCal);
		let seatMantainCal = calculateSeatMaintain(currentCapacityCal);
		let ticketProfitCal = ticketIncomeCal - seatMantainCal;
 
		let commerceIncomeCal = calculateCommerceIncome(extraHomeMatchCal, averageAttendanceCal, restaurantLevelCal, merchandiseStandLevelCal, fastFoodPlaceLevelCal, sausageStandLevelCal, merchandiseStoreLevelCal);
		let commerceMaintainCal = calculateCommerceMaintain(restaurantLevelCal, merchandiseStandLevelCal, fastFoodPlaceLevelCal, sausageStandLevelCal, merchandiseStoreLevelCal);
		let commerceProfitCal = commerceIncomeCal - commerceMaintainCal;
 
		let tvMoneyCal = calculateTVMoney(divisionCal);
		let sponsorsCal = calculateSponsors(divisionCal);
 
		let otherMaintainCal = calculateOtherMaintain(physioLevelCal, pitchDrainingLevelCal, pitchCoverLevelCal, sprinklersLevelCal, heatingLevelCal, floodlightsLevelCal, parkingLevelCal, toiletsLevelCal, medicalCenterLevelCal, youthAcademyLevelCal, trainingGroundsLevelCal);
		let totalProfitCal = ticketProfitCal + commerceProfitCal + tvMoneyCal + sponsorsCal + Number(tradePlayerCal) - otherMaintainCal - playerWageCal * 12 - staffWageCal * 12 - buildingCal - buyStarCal + Number(adjustCal);
 
		$('#tm_script_span_average_attendance')[0].innerText = averageAttendanceCal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_recommend_capacity')[0].innerText = recommendCapacityCal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
 
		$('#tm_script_span_ticket_income')[0].innerText = ticketIncomeCal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_seat_maintain')[0].innerText = seatMantainCal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_ticket_profit')[0].innerText = ticketProfitCal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
 
		$('#tm_script_span_commerce_income')[0].innerText = commerceIncomeCal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_commerce_maintain')[0].innerText = commerceMaintainCal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_commerce_profit')[0].innerText = commerceProfitCal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
 
		$('#tm_script_span_tv_money')[0].innerText = tvMoneyCal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_sponsors')[0].innerText = sponsorsCal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_other_maintain')[0].innerText = otherMaintainCal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		$('#tm_script_span_total_profit')[0].innerText = totalProfitCal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
	}
 
	function identifyFacilityLevel(facility) {
		let tooltip = facility.getAttribute('tooltip');
		let fromIndex = tooltip.search('等级:');
		let toIndex = tooltip.search(']</p>');
		let strLength = '等级:'.length + 1;
		return Number(tooltip.substr(fromIndex + strLength, toIndex - fromIndex - strLength).replace(/,/g, ''));
	}
 
	function calculateEstimateAttendance(parking, toilets, floodlights, fan, capacity) {
		let factor = (1 + parking / 100) * (1 + toilets / 100) * (1 + floodlights / 100) * (fan * 2.2);
		return Math.round((capacity < factor ? capacity : factor) * (1 - 0.05 / 100));
	}
 
	function calculateAverageAttendance(parking, toilets, floodlights, fan, capacity) {
		let factor = (1 + parking / 100) * (1 + toilets / 100) * (1 + floodlights / 100) * (fan * 2.244) * (1 - 7.5 / 100);
		return Math.round((capacity < factor ? capacity : factor) * (1 - 0.05 / 100));
	}
 
	function calculateRecommendCapacity(parking, toilets, floodlights, fan) {
		return Math.round((1 + parking / 100) * (1 + toilets / 100) * (1 + floodlights / 100) * (fan * 2.25));
	}
 
	function calculateOtherMaintain(physioLevel, pitchDrainingLevel, pitchCoverLevel, sprinklersLevel, heatingLevel, floodlightsLevel, parkingLevel, toiletsLevel, medicalCenterLevel, youthAcademyLevel, trainingGroundsLevel) {
		return 12 * (
			PHYSIO_MAINTAIN[physioLevel] +
			PITCH_DRAINING_MAINTAIN[pitchDrainingLevel] +
			PITCH_COVER_MAINTAIN[pitchCoverLevel] +
			SPRINKLERS_MAINTAIN[sprinklersLevel] +
			HEATING_MAINTAIN[heatingLevel] +
			FLOODLIGHTS_MAINTAIN[floodlightsLevel] +
			PARKING_MAINTAIN[parkingLevel] +
			TOILETS_MAINTAIN[toiletsLevel] +
			MEDICAL_CENTER_MAINTAIN[medicalCenterLevel] +
			YOUTH_ACADEMY_MAINTAIN[youthAcademyLevel] +
			TRAINING_GROUNDS_MAINTAIN[trainingGroundsLevel]);
	}
 
	function calculateCommerceIncome(extra = 0, attendance, restaurant, merchandiseStand, fastFoodPlace, sausageStand, merchandiseStore) {
		return Math.round(attendance * (
				restaurant * COMMERCE_PRICE.RESTAURANT * (COMMERCE_INCOME_FACTOR.RESTAURANT + CALCULATE_EXTRA_MATCH.RESTAURANT * extra) +
				merchandiseStand * COMMERCE_PRICE.MERCHANDISE_STAND * (COMMERCE_INCOME_FACTOR.MERCHANDISE_STAND + CALCULATE_EXTRA_MATCH.MERCHANDISE_STAND * extra) +
				fastFoodPlace * COMMERCE_PRICE.FAST_FOOD_PLACE * (COMMERCE_INCOME_FACTOR.FAST_FOOD_PLACE + CALCULATE_EXTRA_MATCH.FAST_FOOD_PLACE * extra) +
				sausageStand * COMMERCE_PRICE.SAUSAGE_STAND * (COMMERCE_INCOME_FACTOR.SAUSAGE_STAND + CALCULATE_EXTRA_MATCH.SAUSAGE_STAND * extra) +
				merchandiseStore * COMMERCE_PRICE.MERCHANDISE_STORE * (COMMERCE_INCOME_FACTOR.MERCHANDISE_STORE + CALCULATE_EXTRA_MATCH.MERCHANDISE_STORE * extra)));
	}
 
	function calculateCommerceMaintain(restaurant, merchandiseStand, fastFoodPlace, sausageStand, merchandiseStore) {
		return 12 * (
			restaurant * COMMERCE_MAINTAIN.RESTAURANT +
			merchandiseStand * COMMERCE_MAINTAIN.MERCHANDISE_STAND +
			fastFoodPlace * COMMERCE_MAINTAIN.FAST_FOOD_PLACE +
			sausageStand * COMMERCE_MAINTAIN.SAUSAGE_STAND +
			MERCHANDISE_STORE_MAINTAIN[merchandiseStore]);
	}
 
	function calculateTicketIncome(extra = 0, attendance) {
		return attendance * TICKET_PRICE * (17 + Number(extra)); //17 home match in league, extra is home match in cup, national cup...
	}
 
	function calculateSeatMaintain(seat) {
		return seat * SEAT_MAINTAIN * 12; //12 month
	}
 
	function calculateTVMoney(div) {
		return TV_MONEY[div] * 12;
	}
 
	function calculateSponsors(div) {
		return Math.round(SPONSORS[div] * 12 * 7 / 10);
	}
 
	function isInt(n) {
		return n % 1 === 0;
	}
})();