From 402ed2e6a90a785d2fce3eca23cd324f350d54c5 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期四, 31 十月 2024 11:42:16 +0800
Subject: [PATCH] 10162 后台优化(增加全服报表)
---
Common/CommFunc.php | 4
db/struct.php | 77 ++
Common/PayOrder.php | 28
db/DBOper.php | 20
js/common.js | 84 ++
eventreport/eventreport.php | 60 +
index.php | 7
Server/eventdata/QueryAccountLoginOut.py | 124 +++
serverrep/ltv.php | 161 ++++
Account/User.php | 16
Server/eventdata/CommFunc.py | 9
serverrep/keeplogin.php | 164 ++++
serverrep/report.php | 785 +++++++++++++++++++++
task/minuteLoop.php | 2
serverrep/ImportAccountLoginpay.php | 444 ++++++++++++
serverrep/dailyuser.php | 97 ++
serverrep/allview.php | 136 +++
17 files changed, 2,209 insertions(+), 9 deletions(-)
diff --git a/Account/User.php b/Account/User.php
index 97e8965..2e2b501 100644
--- a/Account/User.php
+++ b/Account/User.php
@@ -19,6 +19,16 @@
if (!isset($PermissionModules)) {
$PermissionModules = array(
array(
+ "ModuleID" => "ServerRep",
+ "Name" => \Lang\gettext("鎶ヨ〃"),
+ "PList" => array(
+ Permission::P_REP_AllView => array("Name" => \Lang\gettext("鍏ㄦ湇鎬昏")),
+ Permission::P_REP_DailyUser => array("Name" => \Lang\gettext("鍏ㄦ湇姣忔棩鐢ㄦ埛")),
+ Permission::P_REP_KeepLogin => array("Name" => \Lang\gettext("鍏ㄦ湇鐣欏瓨")),
+ Permission::P_REP_LTV => array("Name" => \Lang\gettext("鍏ㄦ湇LTV")),
+ )
+ ),
+ array(
"ModuleID" => "ServerInfo",
"Name" => \Lang\gettext("鏈嶅姟鍣�"),
"PList" => array(
@@ -197,6 +207,12 @@
const GroupAdmin = "admin";
const P_System = "P_System";
+ //鎶ヨ〃
+ const P_REP_AllView = "P_REP_AllView";
+ const P_REP_DailyUser = "P_REP_DailyUser";
+ const P_REP_KeepLogin = "P_REP_KeepLogin";
+ const P_REP_LTV = "P_REP_LTV";
+
//鏈嶅姟鍣�
const P_Online = "P_Online";
const P_PlayerLV = "P_PlayerLV";
diff --git a/Common/CommFunc.php b/Common/CommFunc.php
index cfe2af9..d921f11 100644
--- a/Common/CommFunc.php
+++ b/Common/CommFunc.php
@@ -730,7 +730,7 @@
}
#杩涜post璇锋眰
-function DoPost($url, $post, $passSession = false)
+function DoPost($url, $post, $passSession = false, $timeout=30)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
@@ -739,7 +739,7 @@
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
- curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+ curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
if ($passSession) {
curl_setopt($ch, CURLOPT_COOKIE, 'PHPSESSID=' . $_COOKIE['PHPSESSID']);
}
diff --git a/Common/PayOrder.php b/Common/PayOrder.php
index 9f34b56..3e21b83 100644
--- a/Common/PayOrder.php
+++ b/Common/PayOrder.php
@@ -196,9 +196,37 @@
} else {
\Logging\LogInfo("setDBOrderData:" . print_r($setDBOrderData, true));
}
+ AddAccountFirstPay($appID, $AccountID, $setDBOrderData);
return $returnArr;
}
+/**娣诲姞骞冲彴璐﹀彿棣栧厖 */
+function AddAccountFirstPay($appID, $AccountID, $payOrderInfo)
+{
+ $find = array("Channel" => $appID, "AccountID" => $AccountID);
+ if (!\DBOper\FindOne("AccountFirstPay", $find, $findData, null, false)) {
+ return;
+ }
+ if (isset($findData)) {
+ // 宸插瓨鍦紝涓嶅啀閲嶅娣诲姞
+ return;
+ }
+ $insArray = array(
+ "Channel" => $appID,
+ "AccountID" => $AccountID,
+ "OrderID" => $payOrderInfo["OrderID"],
+ "OrderIDSDK" => $payOrderInfo["OrderIDSDK"],
+ "ServerID" => $payOrderInfo["ServerID"],
+ "OrderInfo" => $payOrderInfo["OrderInfo"],
+ "OrderAmount" => $payOrderInfo["OrderAmount"], // 涓績鐨勮繖涓瓧娈垫槸瀹為檯鏀粯閲戦
+ "OriginalAmount" => $payOrderInfo["OriginalAmount"],
+ "PayTime" => $payOrderInfo["PayTime"],
+ "PayYMD" => substr($payOrderInfo["PayTime"], 0, 10),
+ "Extras" => $payOrderInfo["Extras"],
+ );
+ \DBOper\Insert("AccountFirstPay", $insArray);
+}
+
/**
* 鍙戦�佹笭閬撳洖璋冨厖鍊煎埌娓告垙鏈嶅姟鍣�
* @param string $spid 娓犻亾
diff --git a/Server/eventdata/CommFunc.py b/Server/eventdata/CommFunc.py
index 0b86239..2bcc04e 100644
--- a/Server/eventdata/CommFunc.py
+++ b/Server/eventdata/CommFunc.py
@@ -315,8 +315,9 @@
@return: 鏄惁鎴愬姛
'''
logging.info("loopCenterbakRarDR %s" % str(argvDict))
+ allServer = argvDict.get("allServer", 0)
mixServerIDInfo = argvDict.get("mixServerIDInfo", "")
- if not mixServerIDInfo:
+ if not allServer and not mixServerIDInfo:
queryBackupCenterError("can not found mixServerIDInfo!")
return
@@ -334,7 +335,7 @@
serverIDList = [OnlyServerID] if OnlyServerID else parseMixServerIDInfo(mixServerIDInfo)
spfileFormat = "Event_%s-s" % spID
- logging.info("serverIDList=%s,spfileFormat=%s" % (serverIDList, spfileFormat))
+ logging.info("allServer=%s,serverIDList=%s,spfileFormat=%s" % (allServer, serverIDList, spfileFormat))
# 澶囦唤鏃ユ湡鏂囦欢澶�
for backupDateFile in os.listdir(backupPath):
backupDateStr = backupDateFile[len("Event_"):]
@@ -351,7 +352,7 @@
if not backupServer.startswith(spfileFormat):
continue
serverInfo = backupServer[len(spfileFormat):]
- if not checkIsBackupServerFolder(serverIDList, serverInfo):
+ if not allServer and not checkIsBackupServerFolder(serverIDList, serverInfo):
continue
logging.info("loop %s" % os.path.join(backupPath, backupDateFile, backupServer))
@@ -404,7 +405,7 @@
if not backupServer.startswith(spfileFormat):
continue
serverInfo = backupServer[len(spfileFormat):-4]
- if not checkIsBackupServerFolder(serverIDList, serverInfo):
+ if not allServer and not checkIsBackupServerFolder(serverIDList, serverInfo):
continue
#logging.info("backupServer:%s" % backupServer)
#rarfile.namelist() # 鍒楄〃锛宺ar鏂囦欢涓墍鏈夊瓙鏂囦欢鐨刾ath锛堢浉瀵逛簬rar鏂囦欢鍖呰�岃█鐨勶級
diff --git a/Server/eventdata/QueryAccountLoginOut.py b/Server/eventdata/QueryAccountLoginOut.py
new file mode 100644
index 0000000..6df9eda
--- /dev/null
+++ b/Server/eventdata/QueryAccountLoginOut.py
@@ -0,0 +1,124 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import CommFunc
+import ConfigParser
+import mylog
+import logging
+import json
+
+cfg = ConfigParser.ConfigParser()
+cfg.read("../../InterfaceConfig.php")
+ServerPath = cfg.get("ServerInfo", "ServerPath")
+# 闇�瑕佸鐞嗙殑娴佸悜鍚嶅強椤哄簭鍒楄〃
+DRNameList = ["LogInOut"]
+
+def queryAccountLoginoutInfo(argvDict):
+ logging.info("queryAccountLoginoutInfo %s" % str(argvDict))
+
+ startDate = argvDict.get("startDate", "")
+ endDate = argvDict.get("endDate", "")
+
+ # 鏌ヨ涓績澶囦唤鐨�
+ if CommFunc.isQueryCenterbak(argvDict):
+ queryCenterBak(startDate, endDate, argvDict)
+ return
+
+ loginoutDateAccIDInfo = {} # {"鏃ユ湡":{"AccID":[loginTime, logoutTime, IP], ...}, ...}
+
+ needQueryCenterbak = CommFunc.loopMainServerDR(cfg, startDate, endDate, argvDict, checkDrFileNeedParseFunc, parseLineFunc,
+ loginoutDateAccIDInfo, drNameList=DRNameList)
+ logging.info("needQueryCenterbak %s" % needQueryCenterbak)
+ if needQueryCenterbak:
+ bakDataInfo = CommFunc.queryBackupCenterDR(cfg, argvDict)
+ logging.info("queryBackupCenterDR OK")
+ if bakDataInfo == None:
+ return
+ loginoutDateAccIDInfoBak = bakDataInfo[0]
+ # 鍚堝苟鏁版嵁
+
+ for bakDate, accIDDictBak in loginoutDateAccIDInfoBak.items():
+ if bakDate not in loginoutDateAccIDInfo:
+ loginoutDateAccIDInfo[bakDate] = accIDDictBak
+ continue
+ accIDDict = loginoutDateAccIDInfo[bakDate]
+ for accID, loginoutListBak in accIDDictBak.items():
+ if accID not in accIDDict:
+ accIDDict[accID] = loginoutListBak
+ continue
+ # 澶囦唤鐨勬暟鎹竴瀹氭槸杈冩棫鐨勶紝濡傛灉娌℃湁鏁版嵁鍐嶇敤澶囦唤鏁版嵁鏇挎崲
+ loginoutList = accIDDict[accID]
+ if not loginoutList[0]:
+ loginoutList[0] = loginoutListBak[0]
+ if not loginoutList[1]:
+ loginoutList[1] = loginoutListBak[1]
+ if not loginoutList[2]:
+ loginoutList[2] = loginoutListBak[2]
+
+ logging.info("query all data OK")
+ ret = {"OK": 1, "loginoutDateAccIDInfo": loginoutDateAccIDInfo}
+ print json.dumps(ret, ensure_ascii=False, default=lambda obj: obj.__dict__)
+ return
+
+def queryCenterBak(startDate, endDate, argvDict):
+ loginoutDateAccIDInfoBak = {}
+ if not CommFunc.loopCenterbakRarDR(cfg, startDate, endDate, argvDict, checkDrFileNeedParseFunc, parseLineFunc,
+ loginoutDateAccIDInfoBak, drNameList=DRNameList):
+ return
+
+ return CommFunc.queryBackupCenterOK([loginoutDateAccIDInfoBak])
+
+def checkDrFileNeedParseFunc(drFileName, *parseArgs, **kv):
+ ''' 妫�鏌ユ祦鍚戞槸鍚﹂渶瑕佸鐞�
+ @param drFileName: 娴佸悜鏂囦欢鍚� xxx_鏃ユ湡.txt
+ @param *parseArgs: 鑷畾涔夊弬鏁�
+ @return: isNeed, checkNeedParseRetInfo
+ '''
+ return True, None
+
+def parseLineFunc(drName, dateStr, checkNeedParseRetInfo, line, *parseArgs, **kv):
+ ''' 瑙f瀽娴佸悜琛屽唴瀹�
+ @param drName: 娴佸悜鍚�
+ @param dateStr: 瀵瑰簲鏃ユ湡瀛楃涓�
+ @param checkNeedParseRetInfo: checkDrFileNeedParseFunc 杩斿洖鐨勫唴瀹�
+ @param line: 鏈鍐呭
+ @param *parseArgs: 鑷畾涔夊弬鏁�
+ '''
+
+ loginoutDateAccIDInfo = parseArgs[0]
+ # 缁熻鐧诲綍
+ if drName == "LogInOut":
+ if "127.0.0.1" in line:
+ #logging.info(" 鑴辨満鐧诲綍锛屼笉澶勭悊")
+ return
+
+ drDict = eval(line)
+ accID = drDict["AccID"]
+
+ if dateStr not in loginoutDateAccIDInfo:
+ loginoutDateAccIDInfo[dateStr] = {}
+ accIDDict = loginoutDateAccIDInfo[dateStr]
+ if accID not in accIDDict:
+ accIDDict[accID] = ["", "", ""]
+ loginoutList = accIDDict[accID]
+
+ if drDict["Type"] == "login":
+ loginoutList[0] = drDict["LoginTime"]
+ else:
+ loginoutList[1] = drDict["LogoutTime"]
+ loginoutList[2] = drDict["IP"]
+
+ return
+
+def main():
+ CommFunc.setdefaultencoding()
+ argvDict = CommFunc.parse_args()
+ mylog.InitMyLog(argvDict.get("eventType", ""))
+ queryAccountLoginoutInfo(argvDict)
+ return
+
+if __name__ == "__main__":
+ try:
+ main()
+ except:
+ CommFunc.printExceptionError()
diff --git a/db/DBOper.php b/db/DBOper.php
index bdd6c42..f399e7f 100644
--- a/db/DBOper.php
+++ b/db/DBOper.php
@@ -302,7 +302,7 @@
if (isset($ret) && $ret["ok"] == 1) {
$retArray = $ret["result"];
}
- \Logging\LogInfo('Mongo Aggregate: $ret=' . $ret);
+ // \Logging\LogInfo('Mongo Aggregate: $ret=' . $ret);
MongoDBPool::Close($conn);
return true;
}
@@ -362,6 +362,24 @@
return true;
}
+function FindOneSort($collectionName, $find, &$retArray, $fields = null, $sortArray = null)
+{
+ $dbName = GetDBName();
+ if (!$dbName) {
+ return false;
+ }
+ if (!MongoDBOper::Find($collectionName, $find, $retFindArray, $fields, $sortArray, 1)) {
+ return false;
+ }
+ if (isset($retFindArray)) {
+ foreach ($retFindArray as $value) {
+ $retArray = $value;
+ break;
+ }
+ }
+ return true;
+}
+
function Find(
$collectionName,
$find,
diff --git a/db/struct.php b/db/struct.php
index e95f6e9..b304cd8 100644
--- a/db/struct.php
+++ b/db/struct.php
@@ -20,14 +20,14 @@
"GameRoles" => array(
array(
array("Channel" => 1, "AccountID" => 1),
- array("鈥榰nique" => true),
+ array("unique" => true),
)
),
"GameServerInfo" => array(
array(
array("Channel" => 1, "ServerID" => 1),
- array("鈥榰nique" => true),
+ array("unique" => true),
)
),
@@ -64,8 +64,81 @@
array(
array("Channel" => 1, "State" => 1, "PayTime" => -1),
array(),
+ ),
+ array(
+ array("PayTime" => 1),
+ array(),
+ ),
+ ),
+
+ "ServerEvent" => array(
+ array(
+ array("Key" => 1),
+ array("unique" => true),
)
),
+
+ "AccountFirstLogin" => array(
+ array(
+ array("Channel" => 1, "CreateYMD" => 1),
+ array(),
+ ),
+ array(
+ array("Channel" => 1, "AccountID" => 1),
+ array("unique" => true),
+ ),
+ ),
+
+ "AccountFirstLoginReport" => array(
+ array(
+ array("Channel" => 1, "CreateYMD" => 1),
+ array(),
+ ),
+ array(
+ array("Channel" => 1, "ReportYMD" => -1),
+ array(),
+ ),
+ ),
+
+ "AccountFirstPay" => array(
+ array(
+ array("Channel" => 1, "PayYMD" => 1),
+ array(),
+ ),
+ array(
+ array("Channel" => 1, "AccountID" => 1),
+ array("unique" => true),
+ ),
+ ),
+
+ "AccountFirstPayReport" => array(
+ array(
+ array("Channel" => 1, "FirstPayYMD" => 1),
+ array(),
+ ),
+ array(
+ array("Channel" => 1, "ReportYMD" => -1),
+ array(),
+ ),
+ ),
+
+ "AccountDayActive" => array(
+ array(
+ array("Channel" => 1, "ActiveYMD" => 1),
+ array(),
+ ),
+ array(
+ array("Channel" => 1, "AccountID" => 1, "ActiveYMD" => 1),
+ array("unique" => true),
+ ),
+ ),
+
+ "DailyReport" => array(
+ array(
+ array("Channel" => 1, "YMD" => -1),
+ array("unique" => true),
+ ),
+ )
);
foreach ($structInfo as $collectionName => $indexList) {
diff --git a/eventreport/eventreport.php b/eventreport/eventreport.php
index e632e97..80715bf 100644
--- a/eventreport/eventreport.php
+++ b/eventreport/eventreport.php
@@ -153,6 +153,9 @@
return;
}
}
+ $ServerID = \CommFunc\GetServerIDBySid($RegionName);
+ AddAccountFirstLogin($ServerID, $roleInfo);
+ AddAccountDayActive($ServerID, $roleInfo);
return true;
}
@@ -193,3 +196,60 @@
}
return true;
}
+
+/**娣诲姞骞冲彴璐﹀彿棣栫櫥 */
+function AddAccountFirstLogin($ServerID, $roleInfo)
+{
+ global $Channel, $Time;
+ $AccountID = $_GET["AccountID"];
+
+ $find = array("Channel" => $Channel, "AccountID" => $AccountID);
+ if (!\DBOper\FindOne("AccountFirstLogin", $find, $findData, null, false)) {
+ return;
+ }
+ if (isset($findData)) {
+ // 宸插瓨鍦紝涓嶅啀閲嶅娣诲姞
+ return;
+ }
+ $CreateRoleTime = $Time;
+ if (array_key_exists("CreateRoleTime", $roleInfo)) {
+ $CreateRoleTime = $roleInfo["CreateRoleTime"];
+ }
+ $insArray = array(
+ "Channel" => $Channel,
+ "AccountID" => $AccountID,
+ "CreateYMD" => substr($CreateRoleTime, 0, 10),
+ "CreateTime" => $CreateRoleTime,
+ "ServerID" => $ServerID,
+ "PlayerID" => $roleInfo["PlayerID"],
+ "PlayerName" => $roleInfo["PlayerName"],
+ "Job" => $roleInfo["Job"],
+ "IP" => $roleInfo["IP"],
+ );
+ \DBOper\Insert("AccountFirstLogin", $insArray);
+}
+
+/**娣诲姞骞冲彴璐﹀彿鏃ユ椿 */
+function AddAccountDayActive($ServerID, $roleInfo)
+{
+ global $Channel, $Time;
+ $AccountID = $_GET["AccountID"];
+ $curYMD = substr($Time, 0, 10);
+ $find = array("Channel" => $Channel, "AccountID" => $AccountID, "ActiveYMD" => $curYMD);
+ $roleInfo["ServerID"] = $ServerID;
+ // 鐩存帴鏇存柊
+ $actInfo = array(
+ "Channel" => $Channel,
+ "AccountID" => $AccountID,
+ "ActiveYMD" => $curYMD,
+ "ServerID" => $ServerID,
+ "IP" => $roleInfo["IP"],
+ );
+ if (array_key_exists("LoginTime", $roleInfo)) {
+ $actInfo["LoginTime"] = $roleInfo["LoginTime"];
+ }
+ if (array_key_exists("LogoffTime", $roleInfo)) {
+ $actInfo["LogoffTime"] = $roleInfo["LogoffTime"];
+ }
+ \DBOper\Update("AccountDayActive", $find, $actInfo, false, true);
+}
diff --git a/index.php b/index.php
index c718882..42c8ed4 100644
--- a/index.php
+++ b/index.php
@@ -37,6 +37,13 @@
\Logging\LogInfo("鏉冮檺琛�: " . print_r($permissions, true));
$gmtMenu = array(
+ \Lang\gettext("鎶ヨ〃") => array(
+ array(\User\Permission::P_REP_AllView, "serverrep/allview.php", \Lang\gettext("鍏ㄦ湇鎬昏")),
+ array(\User\Permission::P_REP_DailyUser, "serverrep/dailyuser.php", \Lang\gettext("鍏ㄦ湇姣忔棩鐢ㄦ埛")),
+ array(\User\Permission::P_REP_KeepLogin, "serverrep/keeplogin.php", \Lang\gettext("鍏ㄦ湇鐣欏瓨")),
+ array(\User\Permission::P_REP_LTV, "serverrep/ltv.php", \Lang\gettext("鍏ㄦ湇LTV")),
+ ),
+
\Lang\gettext("鏈嶅姟鍣�") => array(
array(\User\Permission::P_Online, "serverinfo/online.php", \Lang\gettext("鍦ㄧ嚎浜烘暟")),
array(\User\Permission::P_PlayerLV, "serverinfo/playerlv.php", \Lang\gettext("绛夌骇鍒嗗竷")),
diff --git a/js/common.js b/js/common.js
index f1d9ea2..16c5160 100644
--- a/js/common.js
+++ b/js/common.js
@@ -135,4 +135,88 @@
isQuerying = true;
document.getElementById(key).value = gt.gettext("鏌ヨ涓�...");
return true;
+}
+
+/**
+ * 缁樺埗鏇茬嚎鍥�
+ * @param {*} chartID 鍥捐〃ID锛屽叧鑱攈tml涓殑鍏冪礌ID
+ * @param {*} chartText 鍥捐〃鎬绘爣棰�
+ * @param {*} xText x杞存枃鏈紝 濡傜瓑绾�
+ * @param {*} yText y杞存枃鏈紝 濡備汉鏁�
+ * @param {*} labels x杞村埢搴︽枃鏈垪琛紝 濡� 绛夌骇鍒楄〃
+ * @param {*} datasetDataList 鏁版嵁琛ㄦ暟鎹垪琛紝鍗虫瘡鏉$嚎鐨勬暟鎹紝绾跨殑鏁版嵁闀垮害蹇呴』涓巟杞村埢搴︽枃鏈垪琛ㄩ暱搴︿竴鑷�
+ * @param {*} datasetLabList 鏁版嵁琛ㄦ爣棰樺垪琛紝鍗虫瘡鏉$嚎鐨勬爣棰橈紝鏈夊嚑鏉$嚎鐨勬暟鎹嵆鏈夊嚑涓爣棰�
+ */
+ function drawChart_Line(chartID, chartText, xText, yText, labels, datasetDataList, datasetLabList = []) {
+ var backgroundColors = [
+ 'rgba(79, 66, 255, 0.2)',
+ 'rgba(255, 99, 132, 0.2)',
+ 'rgba(255, 206, 86, 0.2)',
+ 'rgba(54, 162, 235, 0.2)',
+ 'rgba(75, 192, 192, 0.2)',
+ 'rgba(153, 102, 255, 0.2)',
+ 'rgba(255, 159, 64, 0.2)'
+ ];
+
+ var borderColors = [
+ 'rgba(79, 66, 255, 1)',
+ 'rgba(255, 99, 132, 1)',
+ 'rgba(255, 206, 86, 1)',
+ 'rgba(54, 162, 235, 1)',
+ 'rgba(75, 192, 192, 1)',
+ 'rgba(153, 102, 255, 1)',
+ 'rgba(255, 159, 64, 1)'
+ ];
+
+ var colorIndex = 0;
+ var datasets = [];
+ for (let i = 0; i < datasetDataList.length; i++) {
+ datasets.push({
+ label: datasetLabList.length > i ? datasetLabList[i] : "",
+ data: datasetDataList[i],
+ backgroundColor: backgroundColors[colorIndex % backgroundColors.length],
+ borderColor: borderColors[colorIndex % borderColors.length],
+ borderWidth: 1,
+ lineTension: 0.5,
+ pointRadius: 1
+ });
+ colorIndex += 1;
+ }
+
+ var ctx = document.getElementById(chartID);
+ ctx.width = 400;
+ ctx.height = 100;
+ var myLineChart = new Chart(ctx, {
+ type: "line",
+ data: {
+ labels: labels,
+ datasets: datasets
+ },
+ options: {
+ plugins: {
+ title: {
+ display: true,
+ text: chartText
+ }
+ },
+ scales: {
+ x: {
+ title: {
+ display: true,
+ text: xText
+ }
+ },
+ y: {
+ title: {
+ display: true,
+ text: yText
+ },
+ beginAtZero: true,
+ ticks: {
+ stepSize: 1, // 鍒诲害闂撮殧1
+ }
+ }
+ }
+ }
+ });
}
\ No newline at end of file
diff --git a/serverrep/ImportAccountLoginpay.php b/serverrep/ImportAccountLoginpay.php
new file mode 100644
index 0000000..1b5d57d
--- /dev/null
+++ b/serverrep/ImportAccountLoginpay.php
@@ -0,0 +1,444 @@
+<?php
+set_time_limit(600); //鏆傛椂璁剧疆鏈剼鏈墽琛屾椂闂磝绉掞紝0涓嶉檺鍒�
+ini_set('memory_limit', '256M'); // 灏嗗唴瀛橀檺鍒惰缃负256MB
+
+include_once '/Common/CommFunc.php';
+include_once '/Common/Logging.php';
+include_once "/db/DBOper.php";
+include_once "/serverrep/report.php";
+
+header("Content-type: text/html; charset=utf-8");
+
+\Logging\CreateLogging("rep.ImportAccountLoginpay.php");
+
+$Channel = $_GET["appID"];
+$opt = $_GET["opt"];
+if (!$Channel) {
+ echo "no appID";
+ exit();
+}
+logweb("寮�濮嬪鍏�:" . $Channel);
+
+if (!$opt || $opt == "first") {
+ logweb("firstfirstfirst:" . $Channel);
+ impAccountFirstLogin();
+ impAccountFirstPay();
+}
+if (!$opt || $opt == "day") {
+ logweb("daydaydaydayday:" . $Channel);
+ impAccountDayActive();
+ // impAccountDayActiveTestData();
+}
+if (!$opt || $opt == "rep") {
+ logweb("repreprepreprep:" . $Channel);
+ \Report\CheckAndExportDailyReport($Channel);
+ \Report\CheckAndExportFirstKeepReport($Channel);
+}
+logweb("澶勭悊瀹屾瘯!");
+exit();
+
+function impAccountFirstLogin()
+{
+ global $Channel;
+ logweb("寮�濮嬪鍏ラ鐧昏处鍙�");
+ \DBOper\Find("AccountFirstLogin", array("Channel" => $Channel), $findFirstLoginDataList, array("AccountID" => 1));
+ $firstLoginAccountIDList = array();
+ foreach ($findFirstLoginDataList as $findData) {
+ $firstLoginAccountIDList[$findData["AccountID"]] = 1;
+ }
+ logweb("宸插瓨鍦ㄩ鐧昏处鍙锋暟:" . count($firstLoginAccountIDList));
+
+ $limit = 10000;
+ $skip = 0;
+ $succCountTotal = 0;
+
+ $gameRolesCount = \DBOper\Count("GameRoles", array("Channel" => $Channel));
+ logweb("GameRoles 鎬绘潯鏁�:" . $gameRolesCount);
+
+ while ($gameRolesCount > 0) {
+ $ret = \DBOper\Find("GameRoles", array("Channel" => $Channel), $rolesDataList, null, null, $limit, $skip);
+ logweb("鏌ヨGameRoles: limit:" . $limit . " skip:" . $skip . " ret:" . $ret . " findCount:" . count($rolesDataList));
+
+ $batchInsFirstLogin = array();
+ foreach ($rolesDataList as $findData) {
+ $AccountID = $findData["AccountID"];
+ if (isset($firstLoginAccountIDList[$AccountID])) {
+ continue;
+ }
+ $firstLoginAccountIDList[$AccountID] = 1;
+
+ $firstLoginInfo = null;
+ $firstLoginTime = "";
+ foreach ($findData as $field => $value) {
+ $ServerID = \CommFunc\GetServerIDBySid($field);
+ if ($ServerID <= 0) {
+ continue;
+ }
+ $roleInfo = $value;
+ $roleInfo["ServerID"] = $ServerID;
+ $CreateRoleTime = $roleInfo["CreateRoleTime"];
+ // $PlayerID = $roleInfo["PlayerID"];
+ // $PlayerName = $roleInfo["PlayerName"];
+ // $Job = $roleInfo["Job"];
+ // $IP = $roleInfo["IP"];
+ // $LoginTime = $roleInfo["LoginTime"];
+ // $LogoffTime = $roleInfo["LogoffTime"];
+
+ // 棣栨鍒涜
+ if ($CreateRoleTime < $firstLoginTime || $firstLoginTime == "") {
+ $firstLoginTime = $CreateRoleTime;
+ $firstLoginInfo = $roleInfo;
+ }
+ }
+
+ if (isset($firstLoginInfo)) {
+ $CreateRoleTime = $firstLoginInfo["CreateRoleTime"];
+ $CreateYMD = substr($CreateRoleTime, 0, 10);
+
+ if (!array_key_exists($CreateYMD, $batchInsFirstLogin)) {
+ $batchInsFirstLogin[$CreateYMD] = array();
+ }
+ $insArray = $batchInsFirstLogin[$CreateYMD];
+ array_push($insArray, array(
+ "Channel" => $Channel,
+ "AccountID" => $AccountID,
+ "CreateYMD" => $CreateYMD,
+ "CreateTime" => $CreateRoleTime,
+ "ServerID" => $firstLoginInfo["ServerID"],
+ "PlayerID" => $firstLoginInfo["PlayerID"],
+ "PlayerName" => $firstLoginInfo["PlayerName"],
+ "Job" => $firstLoginInfo["Job"],
+ "IP" => $firstLoginInfo["IP"],
+ ));
+ $batchInsFirstLogin[$CreateYMD] = $insArray;
+ }
+ }
+
+ logweb(" firstLoginAccountIDList:" . count($firstLoginAccountIDList));
+ $gameRolesCount -= $limit;
+ $skip += $limit;
+
+ if (count($batchInsFirstLogin)) {
+ ksort($batchInsFirstLogin);
+ $succCount = 0;
+ foreach ($batchInsFirstLogin as $CreateYMD => $insArray) {
+ if (DBOper\BatchInsert("AccountFirstLogin", $insArray)) {
+ // logweb("鎵归噺瀵煎叆棣栫櫥璐﹀彿鏁�: CreateYMD:" . $CreateYMD . " count:" . count($insArray));
+ $succCount += count($insArray);
+ } else {
+ logweb("###鎵归噺瀵煎叆棣栫櫥璐﹀彿鏁板紓甯�: CreateYMD:" . $CreateYMD . " count:" . count($insArray));
+ }
+ }
+ $succCountTotal += $succCount;
+ logweb("鏂板瀵煎叆棣栫櫥璐﹀彿鏁�: " . $succCount);
+ }
+ }
+
+ logweb("鏈鏂板瀵煎叆棣栫櫥璐﹀彿鎬绘暟: " . $succCountTotal);
+ \Logging\LogInfo("---------------------------------------------------------------");
+ echo "<hr/>";
+}
+
+function impAccountFirstPay()
+{
+ global $Channel;
+ logweb("寮�濮嬪鍏ラ鍏呰处鍙�");
+ \DBOper\Find("AccountFirstPay", array("Channel" => $Channel), $findFirstPayDataList, array("AccountID" => 1));
+ $firstPayAccountIDList = array();
+ foreach ($findFirstPayDataList as $findData) {
+ $firstPayAccountIDList[$findData["AccountID"]] = 1;
+ }
+ logweb("宸插瓨鍦ㄩ鍏呰处鍙锋暟:" . count($firstPayAccountIDList));
+
+ $payOrderCount = \DBOper\Count("PayOrder", array("Channel" => $Channel));
+ logweb("PayOrder 鎬绘潯鏁�:" . $payOrderCount);
+
+ $limit = 10000;
+ $skip = 0;
+ $succCountTotal = 0;
+
+ while ($payOrderCount > 0) {
+ $ret = \DBOper\Find("PayOrder", array("Channel" => $Channel), $payDataList, null, array("PayTime" => 1), $limit, $skip);
+ logweb("鏌ヨPayOrder: limit:" . $limit . " skip:" . $skip . " ret:" . $ret . " findCount:" . count($payDataList));
+
+ $batchInsFirstPay = array();
+ foreach ($payDataList as $payOrderInfo) {
+ $AccountID = $payOrderInfo["AccountID"];
+ if (isset($firstPayAccountIDList[$AccountID])) {
+ continue;
+ }
+ $firstPayAccountIDList[$AccountID] = 1;
+
+ $PayYMD = substr($payOrderInfo["PayTime"], 0, 10);
+
+ if (!array_key_exists($PayYMD, $batchInsFirstPay)) {
+ $batchInsFirstPay[$PayYMD] = array();
+ }
+ $insArray = $batchInsFirstPay[$PayYMD];
+
+ array_push($insArray, array(
+ "Channel" => $Channel,
+ "AccountID" => $AccountID,
+ "OrderID" => $payOrderInfo["OrderID"],
+ "OrderIDSDK" => $payOrderInfo["OrderIDSDK"],
+ "ServerID" => $payOrderInfo["ServerID"],
+ "OrderInfo" => $payOrderInfo["OrderInfo"],
+ "OrderAmount" => $payOrderInfo["OrderAmount"], // 涓績鐨勮繖涓瓧娈垫槸瀹為檯鏀粯閲戦
+ "OriginalAmount" => $payOrderInfo["OriginalAmount"],
+ "PayTime" => $payOrderInfo["PayTime"],
+ "PayYMD" => $PayYMD,
+ "Extras" => $payOrderInfo["Extras"],
+ ));
+
+ $batchInsFirstPay[$PayYMD] = $insArray;
+ }
+
+ logweb(" firstPayAccountIDList:" . count($firstPayAccountIDList));
+ $payOrderCount -= $limit;
+ $skip += $limit;
+
+ if (count($batchInsFirstPay)) {
+ ksort($batchInsFirstPay);
+ $succCount = 0;
+ foreach ($batchInsFirstPay as $PayTime => $insArray) {
+ if (DBOper\BatchInsert("AccountFirstPay", $insArray)) {
+ // logweb("鎵归噺瀵煎叆棣栧厖璐﹀彿鏁�: PayTime:" . $PayTime . " count:" . count($insArray));
+ $succCount += count($insArray);
+ } else {
+ logweb("###鎵归噺瀵煎叆棣栧厖璐﹀彿鏁板紓甯�: PayTime:" . $PayTime . " count:" . count($insArray));
+ }
+ }
+ $succCountTotal += $succCount;
+ logweb("鏂板瀵煎叆棣栧厖璐﹀彿鏁�: " . $succCount);
+ }
+ }
+
+ logweb("鏈鏂板瀵煎叆棣栧厖璐﹀彿鎬绘暟: " . $succCountTotal);
+ \Logging\LogInfo("---------------------------------------------------------------");
+ echo "<hr/>";
+}
+
+function impAccountDayActive()
+{
+ global $Channel;
+ $startDate = $_GET["startDate"];
+ if (!$startDate) {
+ $startDate = "2024-05-01";
+ }
+ logweb("寮�濮嬩粠涓績瀵煎叆澶囨。鏃ユ椿鏁版嵁! startDate:" . $startDate);
+
+ $allDateAccIDInfo = array(); // 鎵�鏈夎褰�
+ // 鏌ヨ澶囦唤娴佸悜
+ $pack_data = array();
+ $pack_data["spID"] = $Channel;
+ $pack_data["eventType"] = "QueryAccountLoginOut";
+ $pack_data["queryCenterbak"] = 1; # 璁剧疆鏌ヨ涓績鐨�
+ $pack_data["allServer"] = 1; # 璁剧疆妫�绱㈡墍鏈夋湇鍔″櫒娴佸悜
+ $pack_data["startDate"] = $startDate;
+ $pack_data["endDate"] = "";
+ $centerToolUrl = 'http://' . $_SERVER['HTTP_HOST'] . "/Server/eventdata/toolcenter.php";
+ logweb("centerToolUrl:" . $centerToolUrl);
+
+ $retStr = \CommFunc\DoPost($centerToolUrl, $pack_data, false, 300);
+ $ret = json_decode($retStr, true);
+ if (isset($ret)) {
+ $allDateAccIDInfo = $ret[0];
+ ksort($allDateAccIDInfo);
+ foreach ($allDateAccIDInfo as $dateStr => $accIDInfo) {
+ logweb("涓績娴佸悜澶囨。鏃ユ椿鏁伴噺:" . " dateStr:" . $dateStr . " count:" . count($accIDInfo));
+ // foreach ($accIDInfo as $accID => $loginoutInfo) {
+ // logweb(" accID:" . $accID. json_encode($loginoutInfo));
+ // }
+ }
+ } else {
+ logweb("query center backup error: " . $retStr);
+ return;
+ }
+
+ logweb("寮�濮嬩粠瀛愭湇瀵煎叆鏃ユ椿鏁版嵁! startDate:" . $startDate);
+ $pack_data = array();
+ $pack_data["spID"] = $Channel;
+ $pack_data["eventType"] = "QueryAccountLoginOut";
+ // $pack_data["queryAllData"] = "on"; // 璁剧疆鍙煡璇㈠浠芥暟鎹紝瀛愭湇涓嶆煡澶囦唤娴佸悜锛岄槻姝㈠悓鏃跺鏈嶈闂娆�
+ $pack_data["startDate"] = $startDate;
+ $pack_data["endDate"] = "";
+ $sendServers = array();
+ $serverPageInfos = \CommFunc\GetGameServerPageInfo($Channel);
+ // 澶氭湇鏌ヨ鐨�
+ foreach ($serverPageInfos as $mainServerID => $serverInfo) {
+ $sendServers[] = array($mainServerID, \CommFunc\GetQueryEventToolUrl($serverInfo['Page']), $pack_data);
+ }
+ \Logging\LogInfo("寰呭彂閫佺殑鏈嶅姟鍣ㄤ俊鎭�: " . count($sendServers) . " " . print_r($sendServers, true));
+
+ $retList = array();
+ $retMulti = \CommFunc\DoPostMulti($sendServers);
+ if ($retMulti && count($retMulti) == count($sendServers)) {
+ for ($i = 0; $i < count($sendServers); $i++) {
+ $ret = json_decode($retMulti[$i], true);
+ if (!isset($ret)) {
+ $retList[$sendServers[$i][0]] = $retMulti[$i];
+ } else {
+ $retList[$sendServers[$i][0]] = $ret;
+ }
+ }
+ }
+
+ $retCount = count($retList);
+ \Logging\LogInfo("杩斿洖鏌ヨ缁撴灉鏉℃暟: " . $retCount);
+ // \Logging\LogInfo("retList: " . print_r($retList, true));
+
+ // 鍏堝悎骞朵腑蹇冨浠� 鍙� 鍚勬湇鍔″櫒鏁版嵁
+ foreach ($retList as $serverName => $ret) {
+ logweb("-----");
+ if (is_array($ret) && $ret["OK"] == 1) {
+ ksort($ret["loginoutDateAccIDInfo"]);
+ foreach ($ret["loginoutDateAccIDInfo"] as $dateStr => $accIDInfo) {
+ logweb("鏈嶅姟鍣ㄨ繑鍥炴棩娲绘暟閲� serverName:" . $serverName . " dateStr:" . $dateStr . " count:" . count($accIDInfo));
+ if (!isset($allDateAccIDInfo[$dateStr])) {
+ $allDateAccIDInfo[$dateStr] = array();
+ }
+ $allAccIDInfo = $allDateAccIDInfo[$dateStr];
+ foreach ($accIDInfo as $accID => $loginoutInfo) {
+ $allAccIDInfo[$accID] = $loginoutInfo; // 鍚勫瓙鏈嶄竴瀹氭槸鏈�鏂扮殑锛岀洿鎺ユ浛鎹㈠浠芥祦鍚戞暟鎹�
+ }
+ $allDateAccIDInfo[$dateStr] = $allAccIDInfo;
+ }
+ } else {
+ logweb("###鏈嶅姟鍣ㄨ繑鍥炴棩娲绘暟鎹紓甯�! serverName:" . $serverName . " ret:" . $ret);
+ }
+ }
+
+ ksort($allDateAccIDInfo);
+ foreach ($allDateAccIDInfo as $dateStr => $accIDInfo) {
+ logweb("鏈�缁堟棩娲绘暟閲�:" . " dateStr:" . $dateStr . " count:" . count($accIDInfo));
+ $dateInsInfo = array();
+ foreach ($accIDInfo as $accID => $loginoutInfo) {
+ // logweb(" accID:" . $accID. json_encode($loginoutInfo));
+ $accIDParts = explode("@", $accID);
+ $AccountID = implode("@", array_slice($accIDParts, 0, count($accIDParts) - 2));
+ $ServerID = \CommFunc\GetServerIDBySid($accIDParts[count($accIDParts) - 1]);
+ $LoginTime = $loginoutInfo[0];
+ $LogoffTime = $loginoutInfo[1];
+ $IP = $loginoutInfo[2];
+ $ActiveYMD = "";
+ if ($LoginTime != "") {
+ $ActiveYMD = substr($LoginTime, 0, 10);
+ } else {
+ $ActiveYMD = substr($LogoffTime, 0, 10);
+ }
+
+ array_push($dateInsInfo, array(
+ "Channel" => $Channel,
+ "AccountID" => $AccountID,
+ "ActiveYMD" => $ActiveYMD,
+ "LoginTime" => $LoginTime,
+ "LogoffTime" => $LogoffTime,
+ "ServerID" => $ServerID,
+ "IP" => $IP,
+ ));
+ }
+
+ $actCount = DBOper\Count("AccountDayActive", array("Channel" => $Channel, "ActiveYMD" => $dateStr));
+ if ($actCount == count($dateInsInfo)) {
+ logweb("鏃ユ椿鏁版嵁鏁扮浉鍚岋紝涓嶉噸鏂版彃鍏�: " . $dateStr . " count:" . $actCount);
+ continue;
+ }
+ // 鏁版嵁閲忎笉鍚岋紝鍒欏垹闄ゅ悗閲嶆柊鎻掑叆
+ if ($actCount > 0) {
+ if (!DBOper\Remove("AccountDayActive", array("Channel" => $Channel, "ActiveYMD" => $dateStr), false)) {
+ logweb("###鏃ユ椿鏁版嵁鏁颁笉鍚岋紝绉婚櫎鏃跺け璐�!: " . $dateStr . " delCount:" . $actCount . " insCount:" . count($dateInsInfo));
+ continue;
+ }
+ }
+ if (DBOper\BatchInsert("AccountDayActive", $dateInsInfo)) {
+ logweb("鎵归噺瀵煎叆鏃ユ椿鏁�:" . $dateStr . " count:" . count($dateInsInfo));
+ } else {
+ logweb("###鎵归噺瀵煎叆鏃ユ椿鏁板け璐�:" . $dateStr . " count:" . count($dateInsInfo));
+ }
+ }
+
+ \Logging\LogInfo("---------------------------------------------------------------");
+ echo "<hr/>";
+}
+
+// 鎻掑叆灞卞鏃ユ椿鏁版嵁
+function impAccountDayActiveTestData()
+{
+ global $Channel;
+ DBOper\Remove("AccountDayActive", array(), false);
+ \DBOper\Find("AccountFirstLogin", array("Channel" => $Channel), $findFirstLoginDataList, array("CreateYMD" => 1, "AccountID" => 1));
+ $firstAccountIDInfo = array();
+ foreach ($findFirstLoginDataList as $findData) {
+ $CreateYMD = $findData["CreateYMD"];
+ $AccountID = $findData["AccountID"];
+ if (!isset($firstAccountIDInfo[$CreateYMD])) {
+ $firstAccountIDInfo[$CreateYMD] = array();
+ }
+ $accountIDList = $firstAccountIDInfo[$CreateYMD];
+ array_push($accountIDList, $AccountID);
+ $firstAccountIDInfo[$CreateYMD] = $accountIDList;
+ }
+
+ $keepPer = 100;
+ $keepPerSet = array(100, 50, 35, 30, 25, 15, 10);
+ ksort($firstAccountIDInfo);
+ foreach ($firstAccountIDInfo as $CreateYMD => $accountIDList) {
+ logweb("CreateYMD:" . $CreateYMD . " count:" . count($accountIDList));
+ if ($CreateYMD < "2024-05-23") {
+ continue;
+ }
+ $dateInsInfo = array();
+ $accountCount = count($accountIDList);
+ $onePerCount = $accountCount * 0.1;
+ for ($i = 0; $i < 30; $i++) {
+ // $randNum = mt_rand(1, 100);
+ if (count($keepPerSet) > $i) {
+ $keepPer = $keepPerSet[$i];
+ } else {
+ $keepPer = mt_rand(-1, 5);
+ }
+ if ($keepPer <= 0) {
+ continue;
+ }
+
+ $keepCount = $accountCount;
+ if ($keepPer < 100) {
+ $keepCount = intval($accountCount * $keepPer / 100.0);
+ $keepCount = mt_rand($keepCount - $onePerCount, $keepCount + $onePerCount);
+ }
+ if ($keepCount <= 0) {
+ continue;
+ }
+
+ $ActiveYMD = date("Y-m-d", strtotime("+" . $i . " day", strtotime($CreateYMD)));
+ logweb("CreateYMD:" . $CreateYMD . " i:" . $i . " ActiveYMD:" . $ActiveYMD . " keepPer:" . $keepPer . " keepCount:" . $keepCount);
+
+ for ($k = 0; $k < $keepCount; $k++) {
+ $AccountID = $accountIDList[$k];
+ array_push($dateInsInfo, array(
+ "Channel" => $Channel,
+ "AccountID" => $AccountID,
+ "ActiveYMD" => $ActiveYMD,
+ "LoginTime" => $ActiveYMD . " 00:00:00",
+ "LogoffTime" => $ActiveYMD . " 23:59:59",
+ "ServerID" => 999,
+ "IP" => "127.0.0.1",
+ ));
+ }
+ }
+
+ if (DBOper\BatchInsert("AccountDayActive", $dateInsInfo)) {
+ logweb("鎵归噺灞卞鏃ユ椿鏁帮紝 CreateYMD:" . $CreateYMD . " count:" . count($dateInsInfo));
+ } else {
+ logweb("###鎵归噺灞卞鏃ユ椿鏁板け璐ワ紝 CreateYMD:" . $CreateYMD . " count:" . count($dateInsInfo));
+ }
+ }
+}
+
+function logweb($msg, $showWeb = True)
+{
+ \Logging\LogInfo($msg);
+ if ($showWeb) {
+ echo date('Y-m-d H:i:s'), $msg, "<br/>";
+ }
+}
diff --git a/serverrep/allview.php b/serverrep/allview.php
new file mode 100644
index 0000000..8ad4566
--- /dev/null
+++ b/serverrep/allview.php
@@ -0,0 +1,136 @@
+<?php
+include_once "/Common/Logging.php";
+include_once "/Account/User.php";
+include_once "/language/lang.php";
+include_once "/serverrep/report.php";
+
+\Logging\CreateLogging("rep.allview.php");
+$Permission = \User\Permission::P_REP_DailyUser;
+
+$alertMsg = "";
+$channel = $_SESSION['spid'];
+$UserAccount = $_SESSION['UserAccount'];
+$user = new \User\User($UserAccount);
+if (!$user->HavePermission($Permission)) {
+ exit;
+}
+
+// 鍥哄畾鏄剧ず浠婃棩瀹炴椂鏁版嵁 + 鏄ㄦ棩鏁版嵁 + 棰濆鎸囧畾鏌ヨ鏃ユ湡鑼冨洿
+$todayDate = date("Y-m-d");
+$yesterdayDate = date("Y-m-d", strtotime("-1 days"));
+
+$reportDict = \Report\GetDailyReport($channel, $yesterdayDate, $todayDate, true);
+\Logging\LogInfo($yesterdayDate . " ~ " . $todayDate . " reportDict: " . print_r($reportDict, true));
+
+$statDataArray = array(
+ $todayDate => null,
+ $yesterdayDate => null,
+);
+
+foreach ($statDataArray as $key => $value) {
+ if (!isset($reportDict[$key])) {
+ continue;
+ }
+ $dataInfo = $reportDict[$key];
+ $statDataArray[$key] = array(
+ "AU" => $dataInfo["DAU"],
+ "NU" => $dataInfo["DNU"],
+ "PU" => $dataInfo["DPU"],
+ "NPU" => $dataInfo["DNPU"],
+ "RPU" => $dataInfo["DRPU"],
+ "RNPU" => $dataInfo["DRNPU"],
+ );
+}
+
+$startDate = $todayDate;
+$endDate = $todayDate;
+if (array_key_exists("startDate", $_POST) || array_key_exists("endDate", $_POST)) {
+ $startDate = array_key_exists("startDate", $_POST) ? $_POST["startDate"] : $todayDate;
+ $endDate = array_key_exists("endDate", $_POST) ? $_POST["endDate"] : $todayDate;
+ $statDataArray[$startDate . " ~ " . $endDate] = array(
+ "AU" => \Report\QueryActiveUserCount($channel, $startDate, $endDate),
+ "NU" => \Report\QueryNewUserCount($channel, $startDate, $endDate),
+ "PU" => \Report\QueryPayUserCount($channel, $startDate, $endDate),
+ "NPU" => \Report\QueryNewPayUserCount($channel, $startDate, $endDate),
+ "RPU" => \Report\QueryPayTotal($channel, $startDate, $endDate),
+ "RNPU" => "-", // 鍛ㄦ湡鏌ヨ鐨勮鍊兼殏涓嶇粺璁�
+ );
+}
+
+// 璁$畻鍏朵粬鍊�
+foreach ($statDataArray as $key => $dataInfo) {
+ $dataInfo["ARPU"] = $dataInfo["AU"] > 0 ? round($dataInfo["RPU"] / $dataInfo["AU"], 2) : 0;
+ $dataInfo["ARPPU"] = $dataInfo["PU"] > 0 ? round($dataInfo["RPU"] / $dataInfo["PU"], 2) : 0;
+ $statDataArray[$key] = $dataInfo;
+}
+\Logging\LogInfo("statDataArray: " . print_r($statDataArray, true));
+
+$lineArray = array(
+ "娲昏穬鐢ㄦ埛鏁伴噺" => array("AU", "缁熻鍛ㄦ湡鍐咃紝鐧诲綍杩囨父鎴忕殑鐢ㄦ埛鏁�"),
+ "鏂板鐢ㄦ埛鏁伴噺" => array("NU", "缁熻鍛ㄦ湡鍐咃紝鏂板鐨勯鐧荤敤鎴锋暟"),
+ "鍏呭�肩敤鎴锋暟閲�" => array("PU", "缁熻鍛ㄦ湡鍐咃紝鏈夊厖鍊肩殑鐢ㄦ埛鏁�"),
+ "鏂板鍏呭�肩敤鎴�" => array("NPU", "缁熻鍛ㄦ湡鍐咃紝鏂板鐨勯娆″厖鍊肩敤鎴锋暟"),
+ "绱鍏呭�兼�婚" => array("RPU", "缁熻鍛ㄦ湡鍐咃紝绱鍏呭�兼�婚"),
+ "鏂板鍏呭�肩敤鎴峰厖鍊�" => array("RNPU", "缁熻鍛ㄦ湡鍐咃紝鏂板鍏呭�肩敤鎴风疮璁″厖鍊兼�婚"),
+ "ARPU" => array("ARPU", "缁熻鍛ㄦ湡鍐咃紝姣忕敤鎴峰钩鍧囨敹鍏ワ紝绱鍏呭�兼�婚/娲昏穬鐢ㄦ埛鏁伴噺 璁$畻寰楀嚭銆�"),
+ "ARPPU" => array("ARPPU", "缁熻鍛ㄦ湡鍐咃紝姣忓厖鍊肩敤鎴峰钩鍧囨敹鍏ワ紝绱鍏呭�兼�婚/鍏呭�肩敤鎴锋暟閲� 璁$畻寰楀嚭銆�"),
+);
+?>
+
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><?php echo \Lang\gettext("鍏ㄦ湇鎬昏"); ?></title>
+ <link rel="stylesheet" type="text/css" href="/css/table.css">
+ <link rel="gettext" type="application/x-po" href="../language/<?php echo \Lang\getLang(); ?>/LC_MESSAGES/<?php echo \Lang\getjspodomain(); ?>.po" />
+</head>
+
+<body>
+ <center>
+ <p><b><?php echo \Lang\gettext("鍏ㄦ湇鎬昏"); ?></b></P>
+ </center>
+ <form method="post">
+ <?php echo \Lang\gettext("鏌ヨ鏃堕棿"); ?>:
+ <input type="text" name="startDate" id="startDate" onclick="new Calendar().show(this);" readonly value="<?php echo $startDate; ?>" size="8" />
+ ~
+ <input type="text" name="endDate" id="endDate" onclick="new Calendar().show(this);" readonly value="<?php echo $endDate; ?>" size="8" />
+ <input type="submit" value="<?php echo \Lang\gettext("鏌ヨ"); ?>" />
+ <hr />
+ <table width="50%">
+ <?php
+ echo "<thead><tr>";
+ echo "<th align='center' width='200'></th>";
+ foreach ($statDataArray as $key => $dataInfo) {
+ $title = $key;
+ if ($title == $todayDate) {
+ $title = "浠婂ぉ(" . $todayDate . ")";
+ } else if ($title == $yesterdayDate) {
+ $title = "鏄ㄥぉ(" . $yesterdayDate . ")";
+ }
+ echo "<th align='center' width='300'>" . $title . "</th>";
+ }
+ echo "</tr></thead>";
+ foreach ($lineArray as $key => $value) {
+ $dataKey = $value[0];
+ $spanTitle = $value[1];
+ echo "<tr class='trc'>";
+ echo "<td align='center'><span title='" . $spanTitle . "'>" . $key . "</span></td>";
+ foreach ($statDataArray as $key => $dataInfo) {
+ echo "<td align='center'>" . $dataInfo[$dataKey] . "</td>";
+ }
+ echo "</tr>";
+ }
+ ?>
+ </table>
+ <hr />
+ </form>
+</body>
+<script type='text/javascript' src='/language/gettext.js'></script>
+<script type='text/javascript' src="/js/calendar.js"></script>
+<script type='text/javascript' src="/js/common.js"></script>
+<script type="text/javascript">
+</script>
+
+</html>
\ No newline at end of file
diff --git a/serverrep/dailyuser.php b/serverrep/dailyuser.php
new file mode 100644
index 0000000..3a09388
--- /dev/null
+++ b/serverrep/dailyuser.php
@@ -0,0 +1,97 @@
+<?php
+include_once "/Common/Logging.php";
+include_once "/Account/User.php";
+include_once "/language/lang.php";
+include_once "/serverrep/report.php";
+
+\Logging\CreateLogging("rep.dailyuser.php");
+$Permission = \User\Permission::P_REP_DailyUser;
+
+$alertMsg = "";
+$channel = $_SESSION['spid'];
+$UserAccount = $_SESSION['UserAccount'];
+$user = new \User\User($UserAccount);
+if (!$user->HavePermission($Permission)) {
+ exit;
+}
+
+$startDate = array_key_exists("startDate", $_POST) ? $_POST["startDate"] : date("Y-m-d", strtotime("-30 days"));
+$endDate = array_key_exists("endDate", $_POST) ? $_POST["endDate"] : date("Y-m-d");
+
+$reportDict = \Report\GetDailyReport($channel, $startDate, $endDate, true);
+
+$showTime = strtotime($startDate);
+$endTime = strtotime($endDate);
+
+$showLabelInfo = array(
+ "娲昏穬鐢ㄦ埛DAU" => "DAU",
+ "鏂板鐢ㄦ埛DNU" => "DNU",
+ "鍏呭�肩敤鎴稤PU" => "DPU",
+ "鏂板鍏呭�肩敤鎴稤NPU" => "DNPU",
+);
+$xLabels = array(); // x杞翠负鏃ユ湡
+$dataArray = array();
+
+$doCount = 0;
+while ($showTime <= $endTime && $doCount < 1440) {
+ $doCount += 1;
+ $dateStr = date("Y-m-d", $showTime);
+ array_push($xLabels, $dateStr);
+ foreach ($showLabelInfo as $key => $value) {
+ if (!isset($dataArray[$key])) {
+ $dataArray[$key] = array();
+ }
+ $dataList = $dataArray[$key];
+ array_push($dataList, $reportDict[$dateStr] ? $reportDict[$dateStr][$value] : 0);
+ $dataArray[$key] = $dataList;
+ }
+ $showTime = strtotime("+1 day", $showTime);
+}
+?>
+
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><?php echo \Lang\gettext("鍏ㄦ湇姣忔棩鐢ㄦ埛"); ?></title>
+ <link rel="gettext" type="application/x-po" href="../language/<?php echo \Lang\getLang(); ?>/LC_MESSAGES/<?php echo \Lang\getjspodomain(); ?>.po" />
+</head>
+
+<body>
+ <center>
+ <p><b><?php echo \Lang\gettext("鍏ㄦ湇姣忔棩鐢ㄦ埛"); ?></b></P>
+ </center>
+ <form method="post">
+ <?php echo \Lang\gettext("鏌ヨ鏃堕棿"); ?>:
+ <input type="text" name="startDate" id="startDate" onclick="new Calendar().show(this);" readonly value="<?php echo $startDate; ?>" size="8" />
+ ~
+ <input type="text" name="endDate" id="endDate" onclick="new Calendar().show(this);" readonly value="<?php echo $endDate; ?>" size="8" />
+ <input type="submit" value="<?php echo \Lang\gettext("鏌ヨ"); ?>" />
+ <hr />
+ <div id="MyChart"></div>
+ <hr />
+ </form>
+</body>
+<script type='text/javascript' src='/language/gettext.js'></script>
+<script type='text/javascript' src="/js/calendar.js"></script>
+<script type='text/javascript' src="/js/common.js"></script>
+<script type='text/javascript' src="/js/chart.min.js"></script>
+<script type="text/javascript">
+ window.onload = function() {
+ let chartID = "myChart0";
+ let insHtml = "";
+ // insHtml += "<hr />";
+ insHtml += "<canvas id=\"" + chartID + "\" ></canvas>"; // 鎻掑叆鐢诲竷
+ document.getElementById("MyChart").insertAdjacentHTML("beforeEnd", insHtml);
+
+ var xLabels = JSON.parse('<?php echo json_encode($xLabels); ?>');
+ var dataArray = JSON.parse('<?php echo json_encode($dataArray); ?>');
+ const chartText = "姣忔棩鐢ㄦ埛鏁�";
+ const xText = "鏃ユ湡";
+ const yText = "浜烘暟";
+ drawChart_Line(chartID, chartText, xText, yText, xLabels, Object.values(dataArray), Object.keys(dataArray));
+ }
+</script>
+
+</html>
\ No newline at end of file
diff --git a/serverrep/keeplogin.php b/serverrep/keeplogin.php
new file mode 100644
index 0000000..1b04650
--- /dev/null
+++ b/serverrep/keeplogin.php
@@ -0,0 +1,164 @@
+<?php
+include_once "/Common/Logging.php";
+include_once "/Account/User.php";
+include_once "/language/lang.php";
+include_once "/serverrep/report.php";
+
+\Logging\CreateLogging("rep.keeplogin.php");
+$Permission = \User\Permission::P_REP_KeepLogin;
+
+$alertMsg = "";
+$channel = $_SESSION['spid'];
+$UserAccount = $_SESSION['UserAccount'];
+$user = new \User\User($UserAccount);
+if (!$user->HavePermission($Permission)) {
+ exit;
+}
+
+$startDate = array_key_exists("startDate", $_POST) ? $_POST["startDate"] : date("Y-m-d", strtotime("-7 days"));
+$endDate = array_key_exists("endDate", $_POST) ? $_POST["endDate"] : date("Y-m-d");
+$dayList = json_decode($_POST["dayList"], true);
+if (!isset($dayList)) {
+ $dayList = array(2, 3, 4, 5, 6, 7, 8, 10, 15);
+}
+$maxDay = max($dayList);
+if (!in_array(1, $dayList)) {
+ array_push($dayList, 1);
+}
+sort($dayList);
+\Logging\LogInfo("dayList: " . print_r($dayList, true) . " maxDay:" . $maxDay);
+
+\Report\GetAccountFirstLoginPayReport($channel, $startDate, $endDate, $fistLoginReportArray, $fistPayReportArray);
+
+
+?>
+
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><?php echo \Lang\gettext("鍏ㄦ湇鐣欏瓨"); ?></title>
+ <link rel="stylesheet" type="text/css" href="/css/table.css">
+ <link rel="gettext" type="application/x-po" href="../language/<?php echo \Lang\getLang(); ?>/LC_MESSAGES/<?php echo \Lang\getjspodomain(); ?>.po" />
+</head>
+
+<body>
+ <center>
+ <p><b><?php echo \Lang\gettext("鍏ㄦ湇鐣欏瓨"); ?></b></P>
+ </center>
+ <form method="post">
+ <?php echo \Lang\gettext("棣栫櫥鎴栭鍏呮椂闂�"); ?>:
+ <input type="text" name="startDate" id="startDate" onclick="new Calendar().show(this);" readonly value="<?php echo $startDate; ?>" size="8" />
+ ~
+ <input type="text" name="endDate" id="endDate" onclick="new Calendar().show(this);" readonly value="<?php echo $endDate; ?>" size="8" />
+ <input type="submit" value="<?php echo \Lang\gettext("鏌ヨ"); ?>" />
+ <p />
+ 鎸囧畾鏄剧ず鐣欏瓨澶�: <input type="text" name="dayList" id="dayList" value="<?php echo json_encode($dayList) ?>" size="50" />
+ <hr />
+ <table width="100%">
+ <?php
+ echo "<caption>銆愬垱瑙掔暀瀛樸��</caption>";
+ echo "<thead><tr>";
+ echo "<th align='center' width='70'>鍒涜鏃ユ湡</th>";
+ foreach ($dayList as $day) {
+ if ($day == 1) {
+ $title = "棣栫櫥浜烘暟";
+ } else if ($day == 1) {
+ $title = "娆℃棩鐣欏瓨";
+ } else {
+ $title = "绗�" . $day . "鏃ョ暀瀛�";
+ }
+ echo "<th align='center' width='70'>" . $title . "</th>";
+ }
+ echo "</tr></thead>";
+ foreach ($fistLoginReportArray as $firstYMD => $statYMDInfo) {
+ echo "<tr class='trc'>";
+ echo "<td align='center' width='70'>" . $firstYMD . "</td>";
+ $firstYMDTime = strtotime($firstYMD);
+ $firstCount = 0;
+ foreach ($dayList as $day) {
+ $statYMD = date("Y-m-d", strtotime("+" . ($day - 1) . " days", $firstYMDTime));
+ if ($day == 1) {
+ $statInfo = $statYMDInfo[$firstYMD] ? $statYMDInfo[$firstYMD] : array();
+ $firstCount = $statInfo["keepCount"] ? $statInfo["keepCount"] : 0;
+ $text = $firstCount;
+ } else {
+ $statInfo = $statYMDInfo[$statYMD] ? $statYMDInfo[$statYMD] : array();
+ $statCount = $statInfo["keepCount"] ? $statInfo["keepCount"] : 0;
+ if ($statCount == 0 || $firstCount == 0) {
+ $text = "";
+ } else {
+ $keepPer = round($statCount / $firstCount * 100, 2);
+ // $text = $keepPer . "%<br/>(" . $statCount . ")<br/>";
+ $text = $keepPer . "%";
+ }
+ }
+ echo "<td align='center' width='90'>" . $text . "</td>";
+ }
+ echo "</tr>";
+ }
+ if (count($fistLoginReportArray) == 0) {
+ echo "<tr class='trc'><td>鏃犳暟鎹�</td></tr>";
+ }
+ ?>
+ </table>
+ <hr />
+
+ <table width="100%">
+ <?php
+ echo "<caption>銆愰鍏呯暀瀛樸��</caption>";
+ echo "<thead><tr>";
+ echo "<th align='center' width='70'>棣栧厖鏃ユ湡</th>";
+ foreach ($dayList as $day) {
+ if ($day == 1) {
+ $title = "棣栧厖浜烘暟";
+ } else if ($day == 1) {
+ $title = "娆℃棩鐣欏瓨";
+ } else {
+ $title = "绗�" . $day . "鏃ョ暀瀛�";
+ }
+ echo "<th align='center' width='70'>" . $title . "</th>";
+ }
+ echo "</tr></thead>";
+ foreach ($fistPayReportArray as $firstYMD => $statYMDInfo) {
+ echo "<tr class='trc'>";
+ echo "<td align='center' width='70'>" . $firstYMD . "</td>";
+ $firstYMDTime = strtotime($firstYMD);
+ $firstCount = 0;
+ foreach ($dayList as $day) {
+ $statYMD = date("Y-m-d", strtotime("+" . $day . " days", $firstYMDTime));
+ if ($day == 1) {
+ $statInfo = $statYMDInfo[$firstYMD] ? $statYMDInfo[$firstYMD] : array();
+ $firstCount = $statInfo["keepCount"] ? $statInfo["keepCount"] : 0;
+ $text = $firstCount;
+ } else {
+ $statInfo = $statYMDInfo[$statYMD] ? $statYMDInfo[$statYMD] : array();
+ $statCount = $statInfo["keepCount"] ? $statInfo["keepCount"] : 0;
+ if ($statCount == 0 || $firstCount == 0) {
+ $text = "";
+ } else {
+ $keepPer = round($statCount / $firstCount * 100, 2);
+ // $text = $keepPer . "%<br/>(" . $statCount . ")<br/>";
+ $text = $keepPer . "%";
+ }
+ }
+ echo "<td align='center' width='90'>" . $text . "</td>";
+ }
+ echo "</tr>";
+ }
+ if (count($fistPayReportArray) == 0) {
+ echo "<tr class='trc'><td>鏃犳暟鎹�</td></tr>";
+ }
+ ?>
+ </table>
+ <hr />
+ </form>
+</body>
+<script type='text/javascript' src='/language/gettext.js'></script>
+<script type='text/javascript' src="/js/calendar.js"></script>
+<script type='text/javascript' src="/js/common.js"></script>
+<script type="text/javascript">
+</script>
+
+</html>
\ No newline at end of file
diff --git a/serverrep/ltv.php b/serverrep/ltv.php
new file mode 100644
index 0000000..bf1bec5
--- /dev/null
+++ b/serverrep/ltv.php
@@ -0,0 +1,161 @@
+<?php
+include_once "/Common/Logging.php";
+include_once "/Account/User.php";
+include_once "/language/lang.php";
+include_once "/serverrep/report.php";
+
+\Logging\CreateLogging("rep.ltv.php");
+$Permission = \User\Permission::P_REP_LTV;
+
+$alertMsg = "";
+$channel = $_SESSION['spid'];
+$UserAccount = $_SESSION['UserAccount'];
+$user = new \User\User($UserAccount);
+if (!$user->HavePermission($Permission)) {
+ exit;
+}
+
+$startDate = array_key_exists("startDate", $_POST) ? $_POST["startDate"] : date("Y-m-d", strtotime("-7 days"));
+$endDate = array_key_exists("endDate", $_POST) ? $_POST["endDate"] : date("Y-m-d");
+$dayList = json_decode($_POST["dayList"], true);
+$dayTotalList = json_decode($_POST["dayTotalList"], true);
+if (!isset($dayList)) {
+ $dayList = array(1, 2, 3, 4, 5, 6, 7);
+}
+if (!isset($dayTotalList)) {
+ $dayTotalList = array(7, 14, 15, 21, 30);
+}
+if (!in_array(1, $dayList)) {
+ array_push($dayList, 1);
+}
+$maxDay = max(max($dayList), max($dayTotalList));
+
+sort($dayList);
+sort($dayTotalList);
+\Logging\LogInfo("dayList: " . print_r($dayList, true));
+\Logging\LogInfo("dayTotalList: " . print_r($dayTotalList, true));
+\Logging\LogInfo("maxDay:" . $maxDay);
+
+\Report\GetAccountFirstLoginPayReport($channel, $startDate, $endDate, $fistLoginReportArray, $fistPayReportArray);
+// \Logging\LogInfo("dayTotalList: " . print_r($fistLoginReportArray, true));
+
+?>
+
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><?php echo \Lang\gettext("鍏ㄦ湇LTV"); ?></title>
+ <link rel="stylesheet" type="text/css" href="/css/table.css">
+ <link rel="gettext" type="application/x-po" href="../language/<?php echo \Lang\getLang(); ?>/LC_MESSAGES/<?php echo \Lang\getjspodomain(); ?>.po" />
+</head>
+
+<body>
+ <center>
+ <p><b><?php echo \Lang\gettext("鍏ㄦ湇LTV"); ?></b></P>
+ </center>
+ <form method="post">
+ <?php echo \Lang\gettext("棣栫櫥鏃堕棿"); ?>:
+ <input type="text" name="startDate" id="startDate" onclick="new Calendar().show(this);" readonly value="<?php echo $startDate; ?>" size="8" />
+ ~
+ <input type="text" name="endDate" id="endDate" onclick="new Calendar().show(this);" readonly value="<?php echo $endDate; ?>" size="8" />
+ <input type="submit" value="<?php echo \Lang\gettext("鏌ヨ"); ?>" />
+ <p />
+ LTV澶╁綋鏃�: <input type="text" name="dayList" id="dayList" value="<?php echo json_encode($dayList) ?>" size="50" />
+ <p />
+ LTV澶╂眹鎬�: <input type="text" name="dayTotalList" id="dayTotalList" value="<?php echo json_encode($dayTotalList) ?>" size="50" />
+ <hr />
+ <table width="100%">
+ <?php
+ echo "<caption>銆怢TV銆�</caption>";
+ echo "<thead><tr>";
+ echo "<th align='center' width='70'>棣栫櫥鏃ユ湡</th>";
+ echo "<th align='center' width='70'>棣栫櫥浜烘暟</th>";
+ foreach ($dayList as $day) {
+ $title = "绗�" . $day . "鏃TV";
+ echo "<th align='center' width='70'>" . $title . "</th>";
+ }
+ foreach ($dayTotalList as $day) {
+ $title = $day . "鏃ユ�籐TV";
+ echo "<th align='center' width='70'>" . $title . "</th>";
+ }
+ echo "<th align='center' width='70'>鎬籐TV(澶�)</th>";
+ echo "<th align='center' width='70'>鎬诲厖鍊�</th>";
+ echo "</tr></thead>";
+ $curDate = new DateTime();
+ foreach ($fistLoginReportArray as $firstYMD => $statYMDInfo) {
+ echo "<tr class='trc'>";
+ echo "<td align='center' width='70'>" . $firstYMD . "</td>";
+ $firstYMDTime = strtotime($firstYMD);
+ $firstCount = 0;
+ // 褰撴棩ltv
+ foreach ($dayList as $day) {
+ $statYMD = date("Y-m-d", strtotime("+" . ($day - 1) . " days", $firstYMDTime));
+ $statInfo = $statYMDInfo[$statYMD] ? $statYMDInfo[$statYMD] : array();
+ if ($day == 1) {
+ $firstCount = $statInfo["keepCount"] ? $statInfo["keepCount"] : 0;
+ echo "<td align='center' width='70'>" . $firstCount . "</td>";
+ }
+
+ $payTotal = $statInfo["payTotal"] ? $statInfo["payTotal"] : 0;
+ if ($payTotal == 0 || $firstCount == 0) {
+ $text = "";
+ } else {
+ $ltv = $payTotal / $firstCount;
+ $ltv = $ltv > 0.001 ? round($ltv, 3) : round($ltv, 5);
+ // $text = $ltv . "(" . $payTotal . ")";
+ $text = $ltv;
+ }
+ echo "<td align='center' width='90'>" . $text . "</td>";
+ }
+
+ // 缁熻绱澶﹍tv
+ $paySumArray = array();
+ $interval = $curDate->diff(new DateTime($firstYMD));
+ $ltvDays = $interval->days + 1; // ltv鎬诲ぉ鏁� - 鍒涜 ~ 浠婃棩
+ $paySum = 0; // 鎬诲厖鍊�
+ for ($i = 0; $i < $ltvDays; $i++) {
+ $statYMD = date("Y-m-d", strtotime("+" . $i . " days", $firstYMDTime));
+ $statInfo = $statYMDInfo[$statYMD] ? $statYMDInfo[$statYMD] : array();
+ $payTotal = $statInfo["payTotal"] ? $statInfo["payTotal"] : 0;
+ $paySum += $payTotal;
+ $paySumArray[$i + 1] = $paySum;
+ }
+ // \Logging\LogInfo("firstYMD:" . $firstYMD . " ltvDays:" . $ltvDays);
+ // \Logging\LogInfo("paySumArray: " . print_r($paySumArray, true));
+
+ // 姹囨�籰tv
+ foreach ($dayTotalList as $days) {
+ $daysPaySum = $paySumArray[$days] ? $paySumArray[$days] : 0;
+ if ($daysPaySum == 0 || $firstCount == 0) {
+ $text = "";
+ } else {
+ $ltv = round($daysPaySum / $firstCount, 3);
+ $text = $ltv;
+ }
+ echo "<td align='center' width='90'>" . $text . "</td>";
+ }
+
+ // 鎬籐TV(澶�)
+ $ltvTotal = $firstCount == 0 ? 0 : round($paySum / $firstCount, 3);
+ echo "<td align='center' width='90'>" . $ltvTotal . "(" . $ltvDays . ")</td>";
+ // 鎬诲厖鍊�
+ echo "<td align='center' width='90'>" . $paySum . "</td>";
+ echo "</tr>";
+ }
+ if (count($fistLoginReportArray) == 0) {
+ echo "<tr class='trc'><td>鏃犳暟鎹�</td></tr>";
+ }
+ ?>
+ </table>
+ <hr />
+ </form>
+</body>
+<script type='text/javascript' src='/language/gettext.js'></script>
+<script type='text/javascript' src="/js/calendar.js"></script>
+<script type='text/javascript' src="/js/common.js"></script>
+<script type="text/javascript">
+</script>
+
+</html>
\ No newline at end of file
diff --git a/serverrep/report.php b/serverrep/report.php
new file mode 100644
index 0000000..a4c4b3b
--- /dev/null
+++ b/serverrep/report.php
@@ -0,0 +1,785 @@
+<?php
+
+namespace Report;
+
+include_once '/Common/CommFunc.php';
+include_once '/Common/Logging.php';
+include_once "/db/DBOper.php";
+
+function OnExportRep()
+{
+ $curDate = getdate();
+ // $dateStr = $curDate['year'] . "-" . $curDate['mon'] . "-" . $curDate['mday'];
+ $curHour = $curDate['hours'];
+ // 姣忓ぉx鐐瑰浐瀹氭鏌ュ鍑烘姤琛�
+ if ($curHour != 1) {
+ return;
+ }
+ $AllChannel = \CommFunc\GetAllChannel();
+ for ($i = 0; $i < count($AllChannel); $i++) {
+ $Channel = $AllChannel[$i];
+ CheckAndExportDailyReport($Channel);
+ CheckAndExportFirstKeepReport($Channel);
+ }
+}
+
+/**妫�鏌ュ苟瀵煎嚭姣忔棩鎶ヨ〃 */
+function CheckAndExportDailyReport($Channel)
+{
+ if (!\DBOper\FindOneSort("DailyReport", array("Channel" => $Channel), $retInfo, array("YMD" => 1), array("YMD" => -1))) {
+ return;
+ }
+ $StartYMDTime = 0; // 闇�瑕佸鍑虹殑璧峰鏃ユ湡鏃堕棿鎴�
+ if (isset($retInfo)) {
+ // \Logging\LogInfo("DailyReport retInfo:" . print_r($retInfo, true));
+ $lastActiveYMD = $retInfo["YMD"]; // 鏈�鍚庝竴娆″鍑虹殑鎶ヨ〃鏃ユ湡
+ $StartYMDTime = strtotime("+1 day", strtotime($lastActiveYMD)); // 浠�+1澶╁紑濮嬪鍑�
+ } else {
+ // 鍙栧嚭鏈�鏃╃殑棣栫櫥鏃ユ湡
+ if (!\DBOper\FindOneSort("AccountFirstLogin", array("Channel" => $Channel), $retInfo, array("CreateYMD" => 1), array("CreateYMD" => 1))) {
+ return;
+ }
+ if (!isset($retInfo)) {
+ // \Logging\LogInfo("AccountFirstLogin 杩樻病鏈夋暟鎹紝涓嶇敤瀵煎嚭! Channel:" . $Channel);
+ return;
+ }
+ // \Logging\LogInfo("AccountFirstLogin retInfo:" . print_r($retInfo, true));
+ $StartYMDTime = strtotime($retInfo["CreateYMD"]);
+ }
+ if (!$StartYMDTime) {
+ return;
+ }
+
+ $EndYMDTime = strtotime("-1 day", strtotime(date("Y-m-d"))); // 鍙鍑哄埌鏄ㄥぉ
+ $diffSeconds = $EndYMDTime - $StartYMDTime;
+ $diffDays = floor($diffSeconds / (3600 * 24));
+ if ($diffDays <= 0) {
+ \Logging\LogInfo("銆� " . $Channel . " 銆戜笉闇�瑕佸鍑烘瘡鏃ユ姤琛�! StartYMDTime:" . date("Y-m-d", $StartYMDTime));
+ return;
+ }
+
+ \Logging\LogInfo("===== 寮�濮嬪鍑烘瘡鏃ユ姤琛� 銆�" . $Channel . "銆� =====");
+ \Logging\LogInfo("StartYMDTime:" . $StartYMDTime . " " . date("Y-m-d", $StartYMDTime));
+
+ $batchInsDayActive = array();
+ while ($StartYMDTime <= $EndYMDTime && $diffDays >= 0) {
+ $diffDays -= 1;
+ $exportActiveYMD = date("Y-m-d", $StartYMDTime);
+ $repArray = StatDailyReport($Channel, $exportActiveYMD);
+
+ array_push($batchInsDayActive, $repArray);
+
+ $StartYMDTime = strtotime("+1 day", $StartYMDTime);
+ }
+
+ if (count($batchInsDayActive) > 0) {
+ \DBOper\BatchInsert("DailyReport", $batchInsDayActive);
+ }
+ \Logging\LogInfo("==============================================");
+}
+
+/**
+ * 缁熻鏃ユ姤琛�
+ * @param string $Channel
+ * @param string $YMD 瑕佺粺璁$殑yyyy-MM-dd
+ */
+function StatDailyReport($Channel, $YMD)
+{
+ \Logging\LogInfo("=== 缁熻: " . $YMD);
+ $DAU = \DBOper\Count("AccountDayActive", array("Channel" => $Channel, "ActiveYMD" => $YMD));
+ \Logging\LogInfo(" 鏃ユ椿璺冪敤鎴锋暟 DAU:" . $DAU);
+
+ $DNU = \DBOper\Count("AccountFirstLogin", array("Channel" => $Channel, "CreateYMD" => $YMD));
+ \Logging\LogInfo(" 鏃ユ柊澧炵敤鎴锋暟 DNU:" . $DNU);
+
+ $DNPU = \DBOper\Count("AccountFirstPay", array("Channel" => $Channel, "PayYMD" => $YMD));
+ \Logging\LogInfo(" 鏃ユ柊澧炲厖鍊肩敤鎴锋暟 DNPU:" . $DNPU);
+
+ $ret = \DBOper\Aggregate("AccountFirstPay", array(
+ array(
+ '$match' => array("Channel" => $Channel, "PayYMD" => $YMD),
+ ),
+ array(
+ '$group' => array(
+ '_id' => null,
+ 'total' => array('$sum' => '$OrderAmount'),
+ ),
+ )
+ ), $retInfo);
+ $DRNPU = 0;
+ if ($ret && isset($retInfo) && count($retInfo) > 0) {
+ $DRNPU = $retInfo[0]["total"];
+ }
+ $DRNPU = round($DRNPU, 2);
+ \Logging\LogInfo(" 鏃ユ柊澧炲厖鍊肩敤鎴峰厖鍊兼�婚 DRNPU:" . $DRNPU);
+
+ $ret = \DBOper\Aggregate("PayOrder", array(
+ array(
+ '$match' => array(
+ "Channel" => $Channel, "State" => 1,
+ "PayTime" => array('$gte' => $YMD . " 00:00:00", '$lte' => $YMD . " 23:59:59")
+ ),
+ ),
+ array(
+ '$group' => array(
+ '_id' => array('AccountID' => '$AccountID'),
+ 'total' => array('$sum' => '$OrderAmount'),
+ ),
+ )
+ ), $retInfo);
+ $DPU = 0;
+ $DRPU = 0;
+ if ($ret && isset($retInfo)) {
+ foreach ($retInfo as $info) {
+ $DPU += 1;
+ $DRPU += $info["total"];
+ }
+ }
+ $DRPU = round($DRPU, 2);
+ \Logging\LogInfo(" 鏃ュ厖鍊肩敤鎴锋暟 DPU:" . $DPU);
+ \Logging\LogInfo(" 鏃ュ厖鍊肩敤鎴锋暟鍏呭�兼�婚 DRPU:" . $DRPU);
+
+ return array(
+ "Channel" => $Channel, "YMD" => $YMD,
+ "DAU" => $DAU,
+ "DNU" => $DNU,
+ "DNPU" => $DNPU,
+ "DRNPU" => $DRNPU,
+ "DPU" => $DPU,
+ "DRPU" => $DRPU,
+ );
+}
+
+/**妫�鏌ュ苟瀵煎嚭棣栫櫥/棣栧厖鐣欏瓨姣忔棩鎶ヨ〃 */
+function CheckAndExportFirstKeepReport($Channel)
+{
+ if (!\DBOper\FindOne("ServerEvent", array("Key" => "AccountFirstKeepReportYMD"), $ret, null, false)) {
+ return;
+ }
+ $reportYMD = $ret["Value"] ? $ret["Value"] : ""; // 鏈�鍚庝竴娆℃垚鍔熷鍑烘姤琛ㄦ棩鏈�
+
+ $StartYMDTime = 0; // 闇�瑕佸鍑虹殑璧峰鏃ユ湡鏃堕棿鎴�
+ if ($reportYMD) {
+ $StartYMDTime = strtotime("+1 day", strtotime($reportYMD)); // 浠�+1澶╁紑濮嬪鍑�
+ } else {
+ // 鍙栧嚭鏈�鏃╃殑棣栫櫥鏃ユ湡
+ if (!\DBOper\FindOneSort("AccountFirstLogin", array("Channel" => $Channel), $retInfo, array("CreateYMD" => 1), array("CreateYMD" => 1))) {
+ return;
+ }
+ if (!isset($retInfo)) {
+ return;
+ }
+ $StartYMDTime = strtotime($retInfo["CreateYMD"]);
+ }
+ if (!$StartYMDTime) {
+ return;
+ }
+
+ $StartYMD = date("Y-m-d", $StartYMDTime);
+ $EndYMDTime = strtotime("-1 day", strtotime(date("Y-m-d"))); // 鍙鍑哄埌鏄ㄥぉ
+ $diffSeconds = $EndYMDTime - $StartYMDTime;
+ $diffDays = floor($diffSeconds / (3600 * 24));
+ if ($diffDays <= 0) {
+ \Logging\LogInfo("銆� " . $Channel . " 銆戜笉闇�瑕佸鍑洪鐧绘瘡鏃ユ姤琛�! StartYMD:" . $StartYMD);
+ return;
+ }
+ $EndYMD = date("Y-m-d", $EndYMDTime);
+ \Logging\LogInfo("===== 寮�濮嬪鍑洪鐧绘瘡鏃ユ姤琛� 銆�" . $Channel . "銆� =====");
+ \Logging\LogInfo("StartYMD:" . $StartYMD . " EndYMD:" . $EndYMD);
+
+ $fistLoginReportArray = array();
+ $fistPayReportArray = array();
+ while ($StartYMDTime <= $EndYMDTime && $diffDays >= 0) {
+ $diffDays -= 1;
+ $exportActiveYMD = date("Y-m-d", $StartYMDTime);
+
+ if (!StatFirstKeepReport($Channel, $exportActiveYMD, $fistLoginReportArray, $fistPayReportArray, $accountFirstLoginDateInfo, $accountFirstPayDateInfo)) {
+ return;
+ }
+ $StartYMDTime = strtotime("+1 day", $StartYMDTime);
+ }
+ \Logging\LogInfo("fistLoginReportArray:" . print_r($fistLoginReportArray, true));
+ \Logging\LogInfo("fistPayReportArray:" . print_r($fistPayReportArray, true));
+
+ // 鐢熸垚鎻掑叆鏁版嵁
+ $batchInsDatas = array();
+ foreach ($fistLoginReportArray as $CreateYMD => $ymdArray) {
+ foreach ($ymdArray as $ReportYMD => $statInfo) {
+ $keepCount = $statInfo["keepCount"] ? $statInfo["keepCount"] : 0;
+ $payTotal = $statInfo["payTotal"] ? $statInfo["payTotal"] : 0;
+ array_push($batchInsDatas, array(
+ "Channel" => $Channel,
+ "CreateYMD" => $CreateYMD,
+ "ReportYMD" => $ReportYMD,
+ "KeepCount" => $keepCount,
+ "PayTotal" => $payTotal,
+ ));
+ }
+ }
+
+ if (count($batchInsDatas) > 0) {
+ // 姣忔娓呴櫎鍚庨噸鏂版彃鍏�
+ \DBOper\Remove("AccountFirstLoginReport", array("Channel" => $Channel, "ReportYMD" => array('$gte' => $StartYMD)));
+ if (!\DBOper\BatchInsert("AccountFirstLoginReport", $batchInsDatas)) {
+ return;
+ }
+ }
+
+ // 鐢熸垚鎻掑叆鏁版嵁
+ $batchInsDatas = array();
+ foreach ($fistPayReportArray as $FirstPayYMD => $ymdArray) {
+ foreach ($ymdArray as $ReportYMD => $statInfo) {
+ $keepCount = $statInfo["keepCount"] ? $statInfo["keepCount"] : 0;
+ array_push($batchInsDatas, array(
+ "Channel" => $Channel,
+ "FirstPayYMD" => $FirstPayYMD,
+ "ReportYMD" => $ReportYMD,
+ "KeepCount" => $keepCount,
+ ));
+ }
+ }
+
+ if (count($batchInsDatas) > 0) {
+ // 姣忔娓呴櫎鍚庨噸鏂版彃鍏�
+ \DBOper\Remove("AccountFirstPayReport", array("Channel" => $Channel, "ReportYMD" => array('$gte' => $StartYMD)));
+ if (!\DBOper\BatchInsert("AccountFirstPayReport", $batchInsDatas)) {
+ return;
+ }
+ }
+
+ // 鍏ㄩ儴澶勭悊瀹屾瘯鎵嶆洿鏂�
+ \DBOper\Update("ServerEvent", array("Key" => "AccountFirstKeepReportYMD"), array("Value" => $EndYMD), false, true);
+ \Logging\LogInfo("==============================================");
+}
+
+/**
+ * 缁熻棣栫櫥鐩稿叧鐣欏瓨鏃ユ湡鎶ヨ〃锛屽寘鍚厖鍊�(鐢ㄤ簬ltv璁$畻)
+ * @param string $Channel
+ * @param string $YMD 瑕佺粺璁$殑鎶ヨ〃鏃ユ湡yyyy-MM-dd
+ * @param array $fistLoginReportArray 缁熻棣栫櫥鎶ヨ〃缁撴灉 {棣栫櫥鏃ユ湡:{缁熻鏃ユ湡:{keepCount:x, payTotal:x}} ...}}
+ * @param array $fistPayReportArray 缁熻棣栧厖鎶ヨ〃缁撴灉 {棣栧厖鏃ユ湡:{缁熻鏃ユ湡:{keepCount:x}} ...}}
+ * @param array $accountFirstLoginDateInfo 璐﹀彿棣栫櫥鏃ユ湡淇℃伅 {accountID:firstLoginYMD, ...}
+ * @param array $accountFirstPayDateInfo 璐﹀彿棣栧厖鏃ユ湡淇℃伅 {accountID:firstPayYMD, ...}
+ */
+function StatFirstKeepReport($Channel, $YMD, &$fistLoginReportArray, &$fistPayReportArray, &$accountFirstLoginDateInfo = null, &$accountFirstPayDateInfo = null)
+{
+ \Logging\LogInfo("=== 缁熻: " . $YMD);
+ if (!isset($fistLoginReportArray)) {
+ $fistLoginReportArray = array();
+ }
+ if (!isset($fistPayReportArray)) {
+ $fistPayReportArray = array();
+ }
+ if (!isset($accountFirstLoginDateInfo)) {
+ $accountFirstLoginDateInfo = array();
+ }
+ if (!isset($accountFirstPayDateInfo)) {
+ $accountFirstPayDateInfo = array();
+ }
+ if (
+ !\DBOper\Find(
+ "AccountDayActive",
+ array("Channel" => $Channel, "ActiveYMD" => $YMD),
+ $activeRetArray,
+ array("AccountID" => 1)
+ ) || !isset($activeRetArray)
+ ) {
+ return;
+ }
+
+ $dayActiveAccIDList = array(); // 缁熻鏃ユ湡娲昏穬璐﹀彿ID鍒楄〃 [accountID, ..]
+ $queryFirstLoginAccIDList = array(); // 闇�瑕佹煡璇㈤鐧绘棩鏈熺殑璐﹀彿鍒楄〃 [accountID, ..]
+ $queryFirstPayAccIDList = array(); // 闇�瑕佹煡璇㈤鍏呮棩鏈熺殑璐﹀彿鍒楄〃 [accountID, ..]
+ foreach ($activeRetArray as $activeInfo) {
+ $AccountID = $activeInfo["AccountID"];
+
+ array_push($dayActiveAccIDList, $AccountID);
+
+ if (!isset($accountFirstLoginDateInfo[$AccountID])) {
+ array_push($queryFirstLoginAccIDList, $AccountID);
+ }
+ if (!isset($accountFirstPayDateInfo[$AccountID])) {
+ array_push($queryFirstPayAccIDList, $AccountID);
+ }
+ }
+
+ if (count($queryFirstLoginAccIDList) > 0) {
+ if (
+ !\DBOper\Find(
+ "AccountFirstLogin",
+ array("Channel" => $Channel, "AccountID" => array('$in' => $queryFirstLoginAccIDList)),
+ $accountRetArray,
+ array("AccountID" => 1, "CreateYMD" => 1)
+ ) || !isset($accountRetArray)
+ ) {
+ return;
+ }
+ foreach ($accountRetArray as $accountInfo) {
+ $accountFirstLoginDateInfo[$accountInfo["AccountID"]] = $accountInfo["CreateYMD"];
+ }
+ }
+ if (count($queryFirstPayAccIDList) > 0) {
+ if (
+ !\DBOper\Find(
+ "AccountFirstPay",
+ array("Channel" => $Channel, "AccountID" => array('$in' => $queryFirstPayAccIDList)),
+ $accountPayRetArray,
+ array("AccountID" => 1, "PayYMD" => 1)
+ ) || !isset($accountPayRetArray)
+ ) {
+ return;
+ }
+
+ foreach ($accountPayRetArray as $accountInfo) {
+ $accountFirstPayDateInfo[$accountInfo["AccountID"]] = $accountInfo["PayYMD"];
+ }
+ }
+
+ if (
+ !\DBOper\Find(
+ "PayOrder",
+ array(
+ "Channel" => $Channel, "State" => 1, "PayTime" => array('$gte' => $YMD . " 00:00:00", '$lte' => $YMD . " 23:59:59"),
+ "AccountID" => array('$in' => $dayActiveAccIDList)
+ ),
+ $payRetArray,
+ array("AccountID" => 1, "PayTime" => 1, "OrderAmount" => 1)
+ ) || !isset($payRetArray)
+ ) {
+ return;
+ }
+
+ $accountPayDict = array(); // 缁熻鏃ユ湡娲昏穬璐﹀彿鍏呭�奸 {accountID:鍏呭�兼�婚, ...}
+ foreach ($payRetArray as $payInfo) {
+ $AccountID = $payInfo["AccountID"];
+ $OrderAmount = $payInfo["OrderAmount"];
+
+ $accountPayDict[$AccountID] = $accountPayDict[$AccountID] + $OrderAmount;
+ }
+
+ // 姹囨�讳俊鎭�
+ for ($i = 0; $i < count($dayActiveAccIDList); $i++) {
+ $AccountID = $dayActiveAccIDList[$i];
+ // 棣栫櫥
+ $FirstLoginYMD = $accountFirstLoginDateInfo[$AccountID];
+ if ($FirstLoginYMD) {
+ if (!isset($fistLoginReportArray[$FirstLoginYMD])) {
+ $fistLoginReportArray[$FirstLoginYMD] = array();
+ }
+ $statYMDInfo = $fistLoginReportArray[$FirstLoginYMD];
+ if (!isset($statYMDInfo[$YMD])) {
+ $statYMDInfo[$YMD] = array();
+ }
+ $statInfo = $statYMDInfo[$YMD];
+ $statInfo["keepCount"] = ($statInfo["keepCount"] ? $statInfo["keepCount"] : 0) + 1;
+
+ $payTotal = $accountPayDict[$AccountID] ? $accountPayDict[$AccountID] : 0;
+ $statInfo["payTotal"] = ($statInfo["payTotal"] ? $statInfo["payTotal"] : 0) + $payTotal;
+
+ $statYMDInfo[$YMD] = $statInfo;
+ $fistLoginReportArray[$FirstLoginYMD] = $statYMDInfo;
+ }
+
+ // 棣栧厖
+ $FirstPayYMD = $accountFirstPayDateInfo[$AccountID];
+ if ($FirstPayYMD) {
+ if (!isset($fistPayReportArray[$FirstPayYMD])) {
+ $fistPayReportArray[$FirstPayYMD] = array();
+ }
+ $statYMDInfo = $fistPayReportArray[$FirstPayYMD];
+ if (!isset($statYMDInfo[$YMD])) {
+ $statYMDInfo[$YMD] = array();
+ }
+ $statInfo = $statYMDInfo[$YMD];
+ $statInfo["keepCount"] = ($statInfo["keepCount"] ? $statInfo["keepCount"] : 0) + 1;
+
+ $statYMDInfo[$YMD] = $statInfo;
+ $fistPayReportArray[$FirstPayYMD] = $statYMDInfo;
+ }
+ }
+ \Logging\LogInfo("缁熻姣忔棩棣栫櫥OK " . $YMD);
+ return true;
+}
+
+/**
+ * 鑾峰彇姣忔棩鎶ヨ〃
+ * @param string $Channel
+ * @param string $fromYMD 璧峰鏃ユ湡yyyy-MM-dd
+ * @param string $toYMD 鍒版棩鏈焬yyy-MM-dd
+ * @param boolean $returnDateKey 鏄惁浠ユ棩鏈熶负瀛楀吀key鏍煎紡杩斿洖
+ * @return array [{k:v, ...}, ...] 鎴� {dateYMD:{k:v, ...}, ...}
+ */
+function GetDailyReport($Channel, $fromYMD, $toYMD, $returnDateKey = False)
+{
+ CheckAndExportDailyReport($Channel); // 姣忔鑾峰彇妫�鏌ュ鍑�
+ $find = array("Channel" => $Channel, "YMD" => array('$gte' => $fromYMD, '$lte' => $toYMD));
+ \DBOper\Find("DailyReport", $find, $retArray);
+ if (!isset($retArray)) {
+ $retArray = array();
+ }
+ $curYMD = date("Y-m-d");
+ if ($toYMD >= $curYMD) {
+ // 鍖呭惈褰撴棩锛屽疄鏃剁粺璁�
+ array_push($retArray, StatDailyReport($Channel, $curYMD));
+ }
+ if ($returnDateKey) {
+ $retDict = array();
+ foreach ($retArray as $repData) {
+ $retDict[$repData["YMD"]] = $repData;
+ }
+ return $retDict;
+ }
+ return $retArray;
+}
+
+/**
+ * 鏌ヨ鏃ユ湡鑼冨洿鍐呮柊鐢ㄦ埛鏁版�绘暟
+ * @param string $Channel
+ * @param string $fromYMD 璧峰鏃ユ湡yyyy-MM-dd
+ * @param string $toYMD 鍒版棩鏈焬yyy-MM-dd
+ * @return int 鎬绘暟
+ */
+function QueryNewUserCount($Channel, $fromYMD = "", $toYMD = "")
+{
+ $find = array("Channel" => $Channel);
+ $ymdCond = array();
+ if ($fromYMD) {
+ $ymdCond['$gte'] = $fromYMD;
+ }
+ if ($toYMD) {
+ $ymdCond['$lte'] = $toYMD;
+ }
+ if (count($ymdCond)) {
+ $find["CreateYMD"] = $ymdCond;
+ }
+ $count = \DBOper\Count("AccountFirstLogin", $find);
+ return $count;
+}
+
+/**
+ * 鏌ヨ鏃ユ湡鑼冨洿鍐呮瘡鏃ユ柊鐢ㄦ埛鏁�
+ * @param string $Channel
+ * @param string $fromYMD 璧峰鏃ユ湡yyyy-MM-dd
+ * @param string $toYMD 鍒版棩鏈焬yyy-MM-dd
+ * @param array $dateCountInfo {date:count, ...}
+ * @return int 鎬绘暟
+ */
+function QueryNewUserCountByDate($Channel, $fromYMD, $toYMD, &$dateCountInfo)
+{
+ $count = 0;
+ $find = array("Channel" => $Channel, "CreateYMD" => array('$gte' => $fromYMD, '$lte' => $toYMD));
+ $ret = \DBOper\Aggregate("AccountFirstLogin", array(
+ array(
+ '$match' => $find,
+ ),
+ array(
+ '$group' => array(
+ '_id' => '$CreateYMD',
+ 'count' => array('$sum' => 1),
+ ),
+ )
+ ), $retInfo);
+ if ($ret && isset($retInfo)) {
+ foreach ($retInfo as $info) {
+ $count += $info["count"];
+ $dateCountInfo[$info["_id"]] = $info["count"];
+ }
+ ksort($dateCountInfo);
+ }
+ return $count;
+}
+
+/**
+ * 鏌ヨ鏃ユ湡鑼冨洿鍐呮柊浠樿垂鐢ㄦ埛鏁版�绘暟
+ * @param string $Channel
+ * @param string $fromYMD 璧峰鏃ユ湡yyyy-MM-dd
+ * @param string $toYMD 鍒版棩鏈焬yyy-MM-dd
+ * @return int 鎬绘暟
+ */
+function QueryNewPayUserCount($Channel, $fromYMD = "", $toYMD = "")
+{
+ $find = array("Channel" => $Channel);
+ $ymdCond = array();
+ if ($fromYMD) {
+ $ymdCond['$gte'] = $fromYMD;
+ }
+ if ($toYMD) {
+ $ymdCond['$lte'] = $toYMD;
+ }
+ if (count($ymdCond)) {
+ $find["PayYMD"] = $ymdCond;
+ }
+ $count = \DBOper\Count("AccountFirstPay", $find);
+ return $count;
+}
+
+/**
+ * 鏌ヨ鏃ユ湡鑼冨洿鍐呮瘡鏃ユ柊浠樿垂鐢ㄦ埛鏁�
+ * @param string $Channel
+ * @param string $fromYMD 璧峰鏃ユ湡yyyy-MM-dd
+ * @param string $toYMD 鍒版棩鏈焬yyy-MM-dd
+ * @param array $dateCountInfo {date:count, ...}
+ * @return int 鎬绘暟
+ */
+function QueryNewPayUserCountByDate($Channel, $fromYMD, $toYMD, &$dateCountInfo)
+{
+ $count = 0;
+ $find = array("Channel" => $Channel, "PayYMD" => array('$gte' => $fromYMD, '$lte' => $toYMD));
+ $ret = \DBOper\Aggregate("AccountFirstPay", array(
+ array(
+ '$match' => $find,
+ ),
+ array(
+ '$group' => array(
+ '_id' => '$PayYMD',
+ 'count' => array('$sum' => 1),
+ ),
+ )
+ ), $retInfo);
+ if ($ret && isset($retInfo)) {
+ foreach ($retInfo as $info) {
+ $count += $info["count"];
+ $dateCountInfo[$info["_id"]] = $info["count"];
+ }
+ ksort($dateCountInfo);
+ }
+ return $count;
+}
+
+/**
+ * 鏌ヨ鏃ユ湡鑼冨洿鍐呮椿璺冪敤鎴锋暟鎬绘暟
+ * @param string $Channel
+ * @param string $fromYMD 璧峰鏃ユ湡yyyy-MM-dd
+ * @param string $toYMD 鍒版棩鏈焬yyy-MM-dd
+ * @return int 鎬绘暟
+ */
+function QueryActiveUserCount($Channel, $fromYMD, $toYMD)
+{
+ $count = 0;
+ $find = array("Channel" => $Channel, "ActiveYMD" => array('$gte' => $fromYMD, '$lte' => $toYMD));
+ $ret = \DBOper\Aggregate("AccountDayActive", array(
+ array(
+ '$match' => $find,
+ ),
+ array(
+ '$group' => array(
+ '_id' => '$AccountID', // 鎸夎处鍙峰幓閲嶅垎缁�
+ 'count' => array('$sum' => 1),
+ ),
+ )
+ ), $retInfo);
+ if ($ret && isset($retInfo)) {
+ $count = count($retInfo);
+ }
+ return $count;
+}
+
+/**
+ * 鏌ヨ鏃ユ湡鑼冨洿鍐呮瘡鏃ユ椿璺冪敤鎴锋暟
+ * @param string $Channel
+ * @param string $fromYMD 璧峰鏃ユ湡yyyy-MM-dd
+ * @param string $toYMD 鍒版棩鏈焬yyy-MM-dd
+ * @param array $dateCountInfo {date:count, ...}
+ * @return int 鎬绘暟锛堟湭鍘婚噸璐﹀彿锛�
+ */
+function QueryActiveUserCountByDate($Channel, $fromYMD, $toYMD, &$dateCountInfo)
+{
+ $count = 0;
+ $find = array("Channel" => $Channel, "ActiveYMD" => array('$gte' => $fromYMD, '$lte' => $toYMD));
+ $ret = \DBOper\Aggregate("AccountDayActive", array(
+ array(
+ '$match' => $find,
+ ),
+ array(
+ '$group' => array(
+ '_id' => '$ActiveYMD',
+ 'count' => array('$sum' => 1),
+ ),
+ )
+ ), $retInfo);
+ if ($ret && isset($retInfo)) {
+ foreach ($retInfo as $info) {
+ $count += $info["count"];
+ $dateCountInfo[$info["_id"]] = $info["count"];
+ }
+ ksort($dateCountInfo);
+ }
+ return $count;
+}
+
+
+/**
+ * 鏌ヨ鏃ユ湡鑼冨洿鍐呭厖鍊肩敤鎴峰強浠樿垂鎬婚
+ * @param string $Channel
+ * @param string $fromYMD 璧峰鏃ユ湡yyyy-MM-dd
+ * @param string $toYMD 鍒版棩鏈焬yyy-MM-dd
+ * @return array (鎬讳汉鏁�, 鎬婚搴�)
+ */
+function QueryPayUserCountAndTotal($Channel, $fromYMD, $toYMD)
+{
+ $count = 0;
+ $total = 0;
+ $find = array("Channel" => $Channel, "State" => 1);
+ $ymdCond = array();
+ if ($fromYMD) {
+ $ymdCond['$gte'] = $fromYMD . " 00:00:00";
+ }
+ if ($toYMD) {
+ $ymdCond['$lte'] = $toYMD . " 23:59:59";
+ }
+ if (count($ymdCond)) {
+ $find["PayTime"] = $ymdCond;
+ }
+ $ret = \DBOper\Aggregate("PayOrder", array(
+ array(
+ '$match' => $find,
+ ),
+ array(
+ '$group' => array(
+ '_id' => '$AccountID', // 鎸夎处鍙峰幓閲嶅垎缁�
+ 'total' => array('$sum' => '$OrderAmount'),
+ ),
+ )
+ ), $retInfo);
+ if ($ret && isset($retInfo)) {
+ foreach ($retInfo as $info) {
+ $count += 1;
+ $total += $info["total"];
+ }
+ }
+ return array($count, $total);
+}
+
+/**
+ * 鏌ヨ鏃ユ湡鑼冨洿鍐呭厖鍊肩敤鎴锋�绘暟
+ * @param string $Channel
+ * @param string $fromYMD 璧峰鏃ユ湡yyyy-MM-dd
+ * @param string $toYMD 鍒版棩鏈焬yyy-MM-dd
+ * @return int 鎬绘暟
+ */
+function QueryPayUserCount($Channel, $fromYMD, $toYMD)
+{
+ $count = 0;
+ $find = array("Channel" => $Channel, "State" => 1);
+ $ymdCond = array();
+ if ($fromYMD) {
+ $ymdCond['$gte'] = $fromYMD . " 00:00:00";
+ }
+ if ($toYMD) {
+ $ymdCond['$lte'] = $toYMD . " 23:59:59";
+ }
+ if (count($ymdCond)) {
+ $find["PayTime"] = $ymdCond;
+ }
+ $ret = \DBOper\Aggregate("PayOrder", array(
+ array(
+ '$match' => $find,
+ ),
+ array(
+ '$group' => array(
+ '_id' => '$AccountID', // 鎸夎处鍙峰幓閲嶅垎缁�
+ 'count' => array('$sum' => 1),
+ ),
+ )
+ ), $retInfo);
+ if ($ret && isset($retInfo)) {
+ $count = count($retInfo);
+ }
+ return $count;
+}
+
+/**
+ * 鏌ヨ鏃ユ湡鑼冨洿鍐呯疮璁′粯璐�
+ * @param string $Channel
+ * @param string $fromYMD 璧峰鏃ユ湡yyyy-MM-dd
+ * @param string $toYMD 鍒版棩鏈焬yyy-MM-dd
+ * @return int 鎬讳粯璐�
+ */
+function QueryPayTotal($Channel, $fromYMD = "", $toYMD = "")
+{
+ $total = 0;
+ $find = array("Channel" => $Channel, "State" => 1);
+ $ymdCond = array();
+ if ($fromYMD) {
+ $ymdCond['$gte'] = $fromYMD . " 00:00:00";
+ }
+ if ($toYMD) {
+ $ymdCond['$lte'] = $toYMD . " 23:59:59";
+ }
+ if (count($ymdCond)) {
+ $find["PayTime"] = $ymdCond;
+ }
+ $ret = \DBOper\Aggregate("PayOrder", array(
+ array(
+ '$match' => $find,
+ ),
+ array(
+ '$group' => array(
+ '_id' => null,
+ 'total' => array('$sum' => '$OrderAmount'),
+ ),
+ )
+ ), $retInfo);
+ if ($ret && isset($retInfo) && count($retInfo) > 0) {
+ $total = $retInfo[0]["total"];
+ // foreach ($retInfo as $info) {
+ // $total += $info["total"];
+ // }
+ }
+ return round($total, 2);
+}
+
+/**
+ * 鑾峰彇棣栫櫥鍙婇鍏呯敤鎴风浉鍏虫姤琛�
+ * @param string $Channel
+ * @param string $fromYMD 璧峰鏃ユ湡yyyy-MM-dd
+ * @param string $toYMD 鍒版棩鏈焬yyy-MM-dd
+ * @param array &$fistLoginReportArray {棣栫櫥鏃ユ湡:{缁熻鏃ユ湡:{keepCount:x, payTotal:x}} ...}}
+ * @param array &$fistPayReportArray {棣栧厖鏃ユ湡:{缁熻鏃ユ湡:{keepCount:x}} ...}}
+ */
+function GetAccountFirstLoginPayReport($Channel, $fromYMD, $toYMD, &$fistLoginReportArray, &$fistPayReportArray)
+{
+ CheckAndExportFirstKeepReport($Channel); // 姣忔鑾峰彇妫�鏌ュ鍑�
+ $find = array("Channel" => $Channel, "CreateYMD" => array('$gte' => $fromYMD, '$lte' => $toYMD));
+ \DBOper\Find("AccountFirstLoginReport", $find, $newUserRetArray, array("CreateYMD" => 1, "ReportYMD" => 1, "KeepCount" => 1, "PayTotal" => 1));
+ if (!isset($newUserRetArray)) {
+ $newUserRetArray = array();
+ }
+
+ $find = array("Channel" => $Channel, "FirstPayYMD" => array('$gte' => $fromYMD, '$lte' => $toYMD));
+ \DBOper\Find("AccountFirstPayReport", $find, $newPayUserRetArray, array("FirstPayYMD" => 1, "ReportYMD" => 1, "KeepCount" => 1));
+ if (!isset($newPayUserRetArray)) {
+ $newPayUserRetArray = array();
+ }
+
+ $curYMD = date("Y-m-d");
+ if ($toYMD >= $curYMD) {
+ // 鍖呭惈褰撴棩锛屽疄鏃剁粺璁�
+ StatFirstKeepReport($Channel, $curYMD, $fistLoginReportArray, $fistPayReportArray);
+ }
+
+ foreach ($newUserRetArray as $info) {
+ $FirstLoginYMD = $info["CreateYMD"];
+ $ReportYMD = $info["ReportYMD"];
+ if (!isset($fistLoginReportArray[$FirstLoginYMD])) {
+ $fistLoginReportArray[$FirstLoginYMD] = array();
+ }
+ $statYMDInfo = $fistLoginReportArray[$FirstLoginYMD];
+ $statYMDInfo[$ReportYMD] = array("keepCount" => $info["KeepCount"], "payTotal" => $info["PayTotal"]);
+ $fistLoginReportArray[$FirstLoginYMD] = $statYMDInfo;
+ }
+ ksort($fistLoginReportArray);
+
+ foreach ($newPayUserRetArray as $info) {
+ $FirstPayYMD = $info["FirstPayYMD"];
+ $ReportYMD = $info["ReportYMD"];
+ if (!isset($fistPayReportArray[$FirstPayYMD])) {
+ $fistPayReportArray[$FirstPayYMD] = array();
+ }
+ $statYMDInfo = $fistPayReportArray[$FirstPayYMD];
+ $statYMDInfo[$ReportYMD] = array("keepCount" => $info["KeepCount"]);
+ $fistPayReportArray[$FirstPayYMD] = $statYMDInfo;
+ }
+ ksort($fistPayReportArray);
+ return;
+}
diff --git a/task/minuteLoop.php b/task/minuteLoop.php
index 9eb27e3..ae0d04c 100644
--- a/task/minuteLoop.php
+++ b/task/minuteLoop.php
@@ -4,6 +4,7 @@
include_once "/db/DBOper.php";
include_once "/Common/ServerOPS.php";
include_once "/Common/Commtox7.php";
+include_once "/serverrep/report.php";
\Logging\CreateLogging("task.minuteLoop.php");
@@ -57,6 +58,7 @@
function OnHour($hourStr)
{
\Logging\LogInfo("Todo OnHour: " . $hourStr);
+ \Report\OnExportRep();
}
function OnMinute($minuteStr)
--
Gitblit v1.8.0