咸鱼鱼 发表于 2024-10-7 21:49:47

【英雄再聚】快速统计英雄再聚活动队伍选择的脚本

本帖最后由 咸鱼鱼 于 2024-10-8 09:19 编辑

10.8更新了一下,因为主楼多了个队伍名,会识别错误
昨天弄了个腾讯文档表格,写了个半成品脚本方便自己更新

今天中午睡觉一觉,发现有好心人默默更新
连忙把自己写的半成品脚本优化了一下发出来一起用
主要是一个一个用眼睛看是在太累了,试试这个把


安装完成之后点击导出excel就好了




@Name

// ==UserScript==
// @name         GM论坛英雄再聚活动统计脚本
// @namespace    http://tampermonkey.net/
// @version      0.1
// @descriptionFetch data and export to Excel
// @author       Your Name
// @match      https://www.gamemale.com/forum.php?mod=viewthread&tid=145160*
// @match      https://www.gamemale.com/thread-145160-*
// @match      https://www.gamemale.com/forum.php?mod=redirect&goto=findpost&ptid=145160*
// @grant      GM_xmlhttpRequest
// @require      https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.17.0/xlsx.full.min.js
// @grant      GM_registerMenuCommand
// ==/UserScript==

(function () {
    'use strict';
    const teams = [
      "全都队", "仗剑走天涯队", "色令智昏队", "喵喵讨伐魔王队",
      "小怪兽骑飞机队", "无畏猪猪队", "脑子很好但是我没有队", "稳如老狗队",
      "獭獭观察队", "做得很队", "烧仙草队", "金曦遗辉队",
      "猛兽出击队", "六丁六甲队", "躺着过节队", "沉默社畜队",
      "背背山队", "国庆七天乐队", "Cowboy Bebope队", "鲤鱼入后门队",
      "博闻广记分队", "只要努力就一定会成功的对不队", "同路英雄团",
      "菜鸟被掀飞队", "龙颜大悦队", "天选之子队", "关西双虎队",
      "旅行房车队", "成步堂万能事务所", "魔王勇者一家亲队",
      "祈愿者队", "狂欢之椅队", "濡湿小镰刀队"
    ];
    const day1 = ["熔岩魔犬", "毒焰小鬼", "沼气元素"];
    const equip = ["彩虹长剑", "寒冰骑枪", "飓风锁链"]
    const equip2 = ["胜利徽章", "勇气徽章"]
    const ulr1 = 'https://www.gamemale.com/thread-145160-1-1.html';
    const ulr2 = 'https://www.gamemale.com/thread-145160-2-1.html';
    const results = [];

    function fetchAndParse(url) {
      return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: "GET",
                url: url,
                onload: function (response) {
                  if (response.status === 200) {
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(response.responseText, 'text/html');

                        const contentElements = doc.querySelectorAll('.plc .t_f')
                        const urlResults = [];

                        contentElements.forEach(element => {
                            const innerHTML = element.innerText;

                            const result = {};

                            const foundKeywords = findKeywordsInString(innerHTML, teams);
                            result['队伍名'] = foundKeywords.join('')


                            if (result['队伍名']) {
                              const equipmentMatch = innerHTML.match(/当前持有装备【(.*?)】/);
                              result['持有装备'] = equipmentMatch ? equipmentMatch.trim() : '无';

                              // 每日攻击结果
                              const attackTargets = getAttackTargets(innerHTML, true)
                              Object.assign(result, attackTargets);

                              // 使用消耗物品
                              const courageBadgeDays = extractDays(innerHTML, '勇气徽章');
                              const victoryBadgeDays = extractDays(innerHTML, '胜利徽章');
                              Object.assign(result, {
                                    勇气徽章: courageBadgeDays.join(','),
                                    胜利徽章: victoryBadgeDays.join(',')
                              });
                              urlResults.push(result);
                            }
                        });

                        resolve(urlResults);
                  } else {
                        reject(new Error("Network response was not ok"));
                  }
                },
                onerror: function () {
                  reject(new Error("Network request failed"));
                }
            });
      });
    }

    // 定义一个函数,通过参数控制是否倒序
    function getAttackTargets(innerHTML, isReverse = false) {
      // 匹配攻击目标
      const attackTargetMatch = innerHTML.match(/攻击目标.*?【(.*?)】/g);
      if (!attackTargetMatch) return {}

      const targetNames = attackTargetMatch.map(item => item.match(/【(.*?)】/));

      // 创建 result 对象
      const result = {};

      // 按照 index 存入 result
      targetNames.forEach((name, index) => {
            result[`攻击目标Day${index + 1}`] = name;
      });

      // 如果需要倒序
      if (isReverse) {
            const reversedResult = {};
            const keys = Object.keys(result).reverse();

            keys.forEach(key => {
                reversedResult = result;
            });
            return reversedResult;
      }

      return result;
    }

    function exportToExcel(data, filename) {
      const worksheet = XLSX.utils.json_to_sheet(data);
      const workbook = XLSX.utils.book_new();
      XLSX.utils.book_append_sheet(workbook, worksheet, "Results");
      XLSX.writeFile(workbook, filename);
    }

    Promise.all()
      .then(allResults => {
            allResults.forEach(urlResults => {
                results.push(...urlResults);
            });
            // 导出结果为 Excel 文件
            // exportToExcel(results, 'game_results.xlsx');
            const countAttack = countAttackTargets(results, 'object')
            results.unshift(countAttack);
            // results.push(countAttack)
            console.log(results)
            console.log(countAttack);

            // 添加菜单命令
            GM_registerMenuCommand("导出到 Excel", function () {
                exportToExcel(results, 'game_results.xlsx');
            });


      })
      .catch(error => {
            console.error('There has been a problem with your fetch operation:', error);
      });



    // 查找包含在字符串中的关键词
    function findKeywordsInString(string, array) {
      // 找到 "DAY1" 的位置
      const day1Index = string.indexOf('DAY1');

      // 如果找到 "DAY1",则截取字符串,否则使用原字符串
      const searchString = day1Index !== -1 ? string.substring(0, day1Index) : string;

      // 使用 filter 过滤出存在于截取后的字符串中的关键词
      return array.filter(keyword => searchString.includes(keyword));
    }

    // 计算每天多少个攻击对象
    function countAttackTargets(results, outputFormat = 'object') {
      // 定义攻击目标
      const targets = [
            '攻击目标Day7',
            '攻击目标Day6',
            '攻击目标Day5',
            '攻击目标Day4',
            '攻击目标Day3',
            '攻击目标Day2',
            '攻击目标Day1'
      ]


      // 创建一个对象用于存储每个攻击目标的计数
      const countTargets = { '队伍名': '合计', '持有装备': null };

      // 初始化计数为 0
      targets.forEach(target => {
            countTargets = 0;
      });

      // 计算每个攻击目标的数量
      results.forEach(obj => {
            targets.forEach(target => {
                if (obj.hasOwnProperty(target)) {
                  countTargets++;
                }
            });
      });

      // 根据输出格式返回结果
      if (outputFormat === 'array') {
            return targets
                .map(target => ({
                  target: target,
                  count: countTargets
                }))
                .filter(item => item.count > 0); // 过滤掉计数为 0 的项
      } else {
            // 在对象格式中,删除计数为 0 的项
            for (const target of targets) {
                if (countTargets === 0) {
                  delete countTargets;
                }
            }
            return countTargets;
      }
    }


    // 函数用于提取特定徽章的日期
    function extractDays(innerHTML, badgeName) {
      // 按照 "DAY" 切分成多个部分
      const days = innerHTML.split(/DAY/).slice(1); // 第0项是空字符串,忽略

      const badgeDays = [];

      days.forEach(day => {
            if (day.includes(badgeName)) {
                // 如果当前天数包含徽章名称,提取对应的天数
                const dayNumber = day.trim().split('\n'); // 获取第一行,即 DAYX
                badgeDays.push(`DAY${dayNumber}`);
            }
      });

      return badgeDays;
    }


    const innerHTML = `
DAY1
今日使用【黄色结晶】×3,【青色结晶】×3,兑换【奥法之书】
当前持有装备【奥法之书】
攻击目标【沼气元素】风,防御1,HP50
基础伤害-防御减伤+装备加成=结算伤害
5-0+0=5


DAY2
今日使用【红色结晶】×1,兑换【勇气徽章】
当前持有装备【奥法之书】【勇气徽章】
攻击目标【污水元素】,水,防御0,HP40
基础伤害-防御减伤+装备加成=结算伤害
5-0+2=7

DAY3
今日使用【红色结晶】×1,兑换【胜利徽章】
当前持有装备【奥法之书】【胜利徽章】
攻击目标【污水元素】,水,防御0,HP40
基础伤害-防御减伤+装备加成=结算伤害
5-0+2=7

DAY4
今日使用【红色结晶】×1,兑换【勇气徽章】
当前持有装备【奥法之书】【勇气徽章】
攻击目标【污水元素】,水,防御0,HP40
基础伤害-防御减伤+装备加成=结算伤害
5-0+2=7
`


})();




凯诺斯 发表于 2024-10-7 21:59:56

好强大的脚本,可以很轻松的收集数据进行决策{:6_169:}

zzy159 发表于 2024-10-7 22:03:28

哇哦,这样统计起来又方便了捏;P嘿嘿

sanweny 发表于 2024-10-7 22:06:13

楼主好上心,可惜今天真的没办法把boss敲死了{:4_114:}

Morphyus 发表于 2024-10-7 22:11:41

{:6_188:}楼主才是这次战场的最强辅助啊

娱乐法师火布偶 发表于 2024-10-7 22:21:32

为了这个活动楼主真是开发了很多小工具了

user_login 发表于 2024-10-7 22:30:34

昨天用java写了个自动监控的
队伍名匹配就麻烦,亚洛斯队长把名字放在【】外,还有后面有不以”队“结束的。
还因为某个队伍的攻击目标修改正则

折木 发表于 2024-10-7 22:37:51

奇奇怪怪的脚本又增加了{:6_169:}

silencedonkey 发表于 2024-10-7 22:49:08

着实很方便,这样就可以实时看到各个队都在干什么了;P

毛茸茸兽兽 发表于 2024-10-7 23:02:27

吼吼~看u老师的话,以后还是建议都按xxx队格式好咯

黑达克 发表于 2024-10-7 23:40:25

结果今天都还是没有几队人去打BOSS呀{:6_175:}

桀桀桀 发表于 2024-10-7 23:42:56

果然泥潭是一个卧虎藏龙之地,我负责潜水就完事了_(:з」∠)_

仿生人2778号 发表于 2024-10-7 23:51:00

天惹,好努力的楼主{:3_59:}{:3_59:}

tuxonstar 发表于 2024-10-8 00:08:31

非常方便的小工具了,感谢楼主一直在做!

娱乐伙伴琴键猴 发表于 2024-10-8 00:28:43

如优老师所说,最好可以加入一些冗余

Freeze123 发表于 2024-10-8 01:52:47

到时候查找起来很方便惹

油漆王 发表于 2024-10-8 02:11:53

哇,这也有人做脚本!坛友真是既强大又勤劳!

zhuovboyan 发表于 2024-10-8 04:47:31

0-0 这就是大佬嘛 相当于活动的军师了jpg

2302594 发表于 2024-10-8 06:47:27

这都有插件?牛逼啊

you9632587 发表于 2024-10-8 08:38:40

今天开始上班大家都没那么多时间了,有脚本还是更方便大家更新数据啊
页: [1] 2
查看完整版本: 【英雄再聚】快速统计英雄再聚活动队伍选择的脚本