Advertisement
ooshbin

fixDuplicates

Mar 25th, 2022 (edited)
894
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.     /* globals getObj findObjs */
  2.  
  3.     const fixDuplicates = (() => { //eslint-disable-line
  4.  
  5.         let env = 'api';
  6.  
  7.         if (!this.on) env = 'console';
  8.  
  9.         const myOn = this.on ? this.on : () =>{}
  10.  
  11.         const hlog = (msg) => {
  12.             if (env === 'console') console.log(msg);
  13.             else (this.log||console.log)(msg);
  14.         }
  15.  
  16.         const rx = { id: /(-[A-Za-z0-9_-]{19})(\b|$)/, rowId: /_(-[A-Za-z0-9-]{19})_/ }
  17.  
  18.         const sheetData = {
  19.             repSecs: {
  20.                 traits: { keyAttrs: ['name', 'description'] },
  21.                 proficiencies: { keyAttrs: ['name', 'prof_type'] },
  22.                 tool: { keyAttrs: ['toolname', 'toolattr_base'] },
  23.                 inventory: { keyAttrs: ['itemname', 'itemcount'] },
  24.                 attack:  { keyAttrs: ['atkname', 'atkrange'] },
  25.                 'spell-cantrip': { keyAttrs: ['spellname', 'spellschool'] },
  26.                 'spell-1': { keyAttrs: ['spellname', 'spellschool'] },
  27.                 'spell-2': { keyAttrs: ['spellname', 'spellschool'] },
  28.                 'spell-3': { keyAttrs: ['spellname', 'spellschool'] },
  29.                 'spell-4': { keyAttrs: ['spellname', 'spellschool'] },
  30.                 'spell-5': { keyAttrs: ['spellname', 'spellschool'] },
  31.                 'spell-6': { keyAttrs: ['spellname', 'spellschool'] },
  32.                 'spell-7': { keyAttrs: ['spellname', 'spellschool'] },
  33.                 'spell-8': { keyAttrs: ['spellname', 'spellschool'] },
  34.                 'spell-9': { keyAttrs: ['spellname', 'spellschool'] },
  35.             }
  36.         }
  37.  
  38.         const helpers = {
  39.             api: {
  40.                 getAllAttrs: (charId, section) => {
  41.                     const rxSection = new RegExp(`repeating_${section}`, 'i'),
  42.                         allAttrs = findObjs({ type: 'attribute', characterid: charId });
  43.                     return allAttrs.length ? allAttrs.filter(a => rxSection.test(a.get('name'))) : [];
  44.                 },
  45.                 getChar: (charId) => {
  46.                     return getObj('character', charId);
  47.                 },
  48.                 getAllChars: () => {
  49.                     return findObjs({ type: 'character' });
  50.                 },
  51.                 findCharFromName: (charName) => {
  52.                     const chars = helpers.api.getAllChars(),
  53.                         rxName = new RegExp(`^\\s*${charName}\\s*$`, 'i');
  54.                     return chars.filter(c => rxName.test(c.get('name')));
  55.                 },
  56.                 filterNpcs: (c) => {
  57.                     let flag = findObjs({ type: 'attribute', characterid: c.id, name: 'npc' })[0];
  58.                     if (!flag || flag.get('current') != 1) return 1;
  59.                 },
  60.                 deleteAttr: (attribute) => attribute.remove(),
  61.                 toChat: (msg) => this.sendChat('fixDupeBot', `/w gm ${msg}`)
  62.             },
  63.             console: {
  64.                 getAllAttrs: (charId, section) => {
  65.                     const rxSection = new RegExp(`repeating_${section}`, 'i'),
  66.                         allAttrs = window.Campaign.characters.get(charId).attribs.models;
  67.                     return allAttrs.length ? allAttrs.filter(a => rxSection.test(a.get('name'))) : [];
  68.                 },
  69.                 getChar: (charId) => {
  70.                     return window.Campaign.characters.get(charId);
  71.                 },
  72.                 getAllChars: () => {
  73.                     return window.Campaign.characters.models;
  74.                 },
  75.                 findCharFromName: (charName) => {
  76.                     const chars = helpers.console.getAllChars(),
  77.                         rxName = new RegExp(`^\\s*${charName}\\s*$`, 'i');
  78.                     return chars.filter(c => rxName.test(c.get('name')));
  79.                 },
  80.                 filterNpcs: (c) => {
  81.                     let flag = c.attribs.models.find(a => a.get('name') === 'npc');
  82.                     if (flag && flag.get('current') == 1) return null;
  83.                     else return 1;
  84.                 },
  85.                 deleteAttr: (attribute) => attribute.destroy(),
  86.                 toChat: () => {},
  87.             }
  88.         }
  89.  
  90.         const deleteDuplicates = (delQueue, charId) => {
  91.             let deletedAttrs = 0;
  92.             for (let section in delQueue) {
  93.                 const allAttrs = helpers[env].getAllAttrs(charId, section);
  94.                 delQueue[section].forEach(row => {
  95.                     // hlog(`Checking ${row}...`)
  96.                     const rowAttrs = allAttrs.filter(a => a.get('name').indexOf(row) > -1);
  97.                     if (rowAttrs.length) {
  98.                         // hlog(`Found ${rowAttrs.length} attributes in row to delete`);
  99.                         rowAttrs.forEach(a => {
  100.                             helpers[env].deleteAttr(a);
  101.                             deletedAttrs ++;
  102.                         });
  103.                     }
  104.                 });
  105.             }
  106.             return deletedAttrs;
  107.         }
  108.  
  109.         const findDuplicates = (charId) => {
  110.             // hlog(`Fixing sheet ${charId}`);
  111.             const deleteQueue = {},
  112.                 dupeNamesLog = [];
  113.             const sections = Object.keys(sheetData.repSecs),
  114.                 char = helpers[env].getChar(charId)
  115.             if (!char) return new Error(`Couldn't find character`);
  116.             sections.forEach(section => {
  117.                 const sectionQueue = [];
  118.                 const rxKeyAttr1 = new RegExp(`repeating_${section}.*_${sheetData.repSecs[section].keyAttrs[0]}$`, 'i'),
  119.                     rxKeyAttr2 = new RegExp(`repeating_${section}.*_${sheetData.repSecs[section].keyAttrs[1]}$`, 'i'),
  120.                     processedNames = [],
  121.                     attrs = helpers[env].getAllAttrs(charId, section);
  122.                 const attrs1 = attrs.filter(a => rxKeyAttr1.test(a.get('name'))),
  123.                     attrs2 = attrs.filter(a => rxKeyAttr2.test(a.get('name')));
  124.                 attrs1.forEach(attr => {
  125.                     if (!processedNames.includes(attr.get('current'))) {
  126.                         const masterRow = (attr.get('name').match(rx.rowId)||[])[1];
  127.                         if (!masterRow) return hlog(`Bad rowid`);
  128.                         // hlog(`Comparing ${masterRow}...`);
  129.                         const duplicates = attrs1.filter(a => a.get('current') === attr.get('current'));
  130.                         if (duplicates.length > 1) {
  131.                             // hlog(`Duplicates found: ${duplicates.length-1}`);
  132.                             duplicates.forEach(dupe => {
  133.                                 const dupeRow = (dupe.get('name').match(rx.rowId)||[])[1];
  134.                                 if (!dupeRow) return hlog(`Bad rowId`);
  135.                                 const master2 = attrs2.find(a => a.get('name').indexOf(masterRow) > -1),
  136.                                     compare2 = attrs2.find(a => a.get('name').indexOf(dupeRow) > -1);
  137.                                 if (!flags.secondCheck || ((master2 && compare2) && (master2.get('current') === compare2.get('current')) && (dupeRow !== masterRow))) {
  138.                                     // hlog(`Duplicate verified at row: ${dupeRow}`);
  139.                                     sectionQueue.push(`${dupeRow}`);
  140.                                     dupeNamesLog.push(dupe.get('current'));
  141.                                 }
  142.                             });
  143.                         }
  144.                     } //else hlog(`Skipping ${attr.get('current')}, already processed`);
  145.                     processedNames.push(attr.get('current'));
  146.                 });
  147.                 // hlog(`Duplicates found in ${section}: ${sectionQueue.length}`);
  148.                 deleteQueue[section] = sectionQueue;
  149.             });
  150.             const total = Object.entries(deleteQueue).reduce((a,v) => a += v[1].length, 0);
  151.             // hlog(`Finished all sections, deleteQueue has ${total} entries`);
  152.             if (flags.deleteDupes) {
  153.                 let deleted = total > 0 ? deleteDuplicates(deleteQueue, charId) : 0;
  154.                 return deleted ? (`{{**${helpers[env].getChar(charId).get('name')}**: ${total} duplicate(s) deleted}}`) : null;
  155.             } else {
  156.                 return dupeNamesLog.length ? `{{** ${helpers[env].getChar(charId).get('name')} ** - ${dupeNamesLog.join(', ')}}}` : null;
  157.             }
  158.         }
  159.  
  160.         const getCharIds = (includeNpc, charId, charName) => {
  161.             let idArray = []
  162.             if (charName) {
  163.                 let char = helpers[env].findCharFromName(charName);
  164.                 if (!char || !char.length) return helpers[env].toChat(`Error: couldn't look up character from "${charName}"`);
  165.                 if (char.length > 1) return helpers[env].thChat(`Error: found multiple character from supplied name: ${char.map(c=>c.get('name')).join(', ')}`);
  166.                 else if (!char[0] || !char[0].id) return helpers[env].thChat(`Error: something went wrong, bad character data`);
  167.                 else idArray.push(char[0].id);
  168.             }
  169.             else if (charId) {
  170.                 let char = helpers[env].getChar(charId);
  171.                 if (char) idArray.push(char.id);
  172.                 else return helpers[env].toChat(`Error: couldn't look up character from "${charId}"`);
  173.             }
  174.             else {
  175.                 let allChars = helpers[env].getAllChars();
  176.                 allChars = includeNpc ? allChars : allChars.filter(helpers[env].filterNpcs);
  177.                 idArray = allChars.map(c=>c.id);
  178.                 // hlog(idArray.length);
  179.             }
  180.             // hlog(idArray);
  181.             return idArray;
  182.         }
  183.  
  184.         const flags = { deleteDupes: false, chatReport: false, secondCheck: true }
  185.  
  186.         const handleCli = async (msgContent) => {
  187.             let charIdArray = [];
  188.             flags.deleteDupes = /--del/i.test(msgContent) ? true : false;
  189.             flags.chatReport = /--rep/i.test(msgContent) ? true : false;
  190.             flags.secondCheck = /--single/.test(msgContent) ? false : true;
  191.             if (/--all/.test(msgContent)) charIdArray = getCharIds(true);
  192.             else if (/--pc/.test(msgContent)) charIdArray = getCharIds();
  193.             else if (/--char/.test(msgContent)) {
  194.                 let charId = (msgContent.match(rx.id)||[])[1];
  195.                 if (!charId) {
  196.                     let charNameMatch = msgContent.match(/--char[\w]*\s+((.+?)\s*--|(.+)$)/);
  197.                     let charName = charNameMatch ? charNameMatch[2] || charNameMatch[3] : null;
  198.                     if (!charName) {
  199.                         helpers[env].toChat(`Error: invalid charId or charName`);
  200.                         return;
  201.                     } else charIdArray = getCharIds(null, null, charName);
  202.                 } else {
  203.                     if (helpers[env].getChar(charId)) charIdArray.push(charId);
  204.                 }
  205.             } else {
  206.                 helpers[env].toChat(`Error: invalid command line. Use --char --all or --pcs`);
  207.             }
  208.             if (charIdArray.length) {
  209.                 hlog(`cycling through ${charIdArray.join(', ')}...`);
  210.                 let reportLog = [];
  211.                 await Promise.all(charIdArray.map(async (id) => {
  212.                     const result = findDuplicates(id, flags.deleteDupes);
  213.                     if (result) reportLog.push(result);
  214.                 }));
  215.                 if (flags.chatReport) {
  216.                     let chatTemplate = `&{template:default}{{name=fixDupes Report}}`;
  217.                     chatTemplate += reportLog.length ? reportLog.join(' ') : `{{No duplicates found. These aren't the droids you're looking for. Move along.}}`;
  218.                     helpers[env].toChat(chatTemplate);
  219.                 }
  220.             }
  221.         }
  222.  
  223.         const consoleHandleChatMsg = (msg) => {
  224.             console.log(msg);
  225.             if (/^!fixdup(e|licate)/i.test(msg)) handleCli(msg)
  226.         }
  227.  
  228.         myOn('ready', () => {
  229.             setTimeout(() => hlog(`<< fixDuplicates finished loading - running in environment: ${env.toUpperCase()} >>`), 500);
  230.             myOn('chat:message', (msg) => {
  231.                 if (msg.type === 'api' && /^!fixdup(e|licate)/i.test(msg.content)) handleCli(msg.content);
  232.             });
  233.         });
  234.  
  235.         const watchChat = (() => { //eslint-disable-line
  236.             if (env === 'api') return;
  237.             const chat = document.querySelector('#textchat-input textarea'),
  238.                 sendbutton = $('#textchat-input button.btn'),
  239.                 send = () => sendbutton.trigger('click');
  240.             helpers.console.toChat = (msg) => {
  241.                 chat.value = `${msg}`;
  242.                 send();
  243.             };
  244.             if (chat) {
  245.                 chat.addEventListener('change', (ev) => consoleHandleChatMsg(ev.target.value));
  246.                 chat.addEventListener('input', (ev) => window.chatCache = ev.target.value );
  247.                 chat.addEventListener('keyup', (ev) => { if (ev.key === 'Enter') consoleHandleChatMsg(window.chatCache||'') });
  248.             }
  249.         })();
  250.  
  251.         setTimeout(() => console.log(`<< fixDuplicates finished loading - running in environment: ${env.toUpperCase()} >>`), 1500);
  252.  
  253.     })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement