Last active
May 2, 2026 11:53
-
-
Save WhiteBearSpirit/94045ead951a27c06a0fe69d9c1980fb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <html> | |
| <head> | |
| <title>Money cat</title> | |
| </head> | |
| <body> | |
| <div style="display: inline-block;"> | |
| <textarea id="in" name="in" rows="40" cols="100"></textarea> | |
| <textarea id="out" name="out" rows="40" cols="100"></textarea> | |
| </div> | |
| <div> | |
| <button onclick="process();">Categorize</button> | |
| </div> | |
| </body> | |
| </html> | |
| <script type="text/javascript"> | |
| function process() { | |
| const values = document.getElementById('in').value.split('\n'); | |
| var actor = null; | |
| var trataList = Array(); | |
| var creditList = Array(); | |
| for (let i = 0; i < values.length; i++) { | |
| const line = values[i]; | |
| if (!line) { continue; } | |
| let dataLine = line; | |
| const actorWithSomethingMatch = line.match(/\[\d\d\.\d\d\.\d{4} \d\d:\d\d\] (\p{L}+): (\+?\d+\s+.+)/u); | |
| if (actorWithSomethingMatch) { | |
| actor = actorWithSomethingMatch[1]; | |
| dataLine = actorWithSomethingMatch[2]; | |
| } | |
| match = dataLine.match(/^(\d+)\s+(.+)/u); | |
| if (match) { | |
| const trata = { actor: actor, cost: parseInt(match[1]), good: match[2].trim() }; | |
| trataList.push(trata); | |
| } | |
| else { | |
| const creditMatch = dataLine.match(/^\+\s?(\d+)\s+(.+)/u); | |
| if (creditMatch) { | |
| creditList.push({ actor: actor, data: dataLine.trim() }); | |
| } | |
| } | |
| } | |
| const groupedDebit = groupBy(trataList, "actor"); | |
| document.getElementById("out").value = ""; | |
| for (let [key, value] of groupedDebit) { | |
| const outLines = value.map(t => t.cost + "\t" + categorizeSingle(t.good) + "\t" + t.good); | |
| document.getElementById("out").value = document.getElementById("out").value + key + "\n" + outLines.join("\n") + "\n\n"; | |
| } | |
| const groupedCredit = groupBy(creditList, "actor"); | |
| for (let [key, value] of groupedCredit) { | |
| const outLines = value.map(t => t.data.replace(/\+\s*/, "").replace(/\s+/, "\t")); | |
| document.getElementById("out").value = document.getElementById("out").value + "Приход " + key + ":\n" + outLines.join("\n") + "\n\n"; | |
| } | |
| } | |
| function categorizeSingle(good) { | |
| if (!good) { return "ХЗ"; } | |
| const keys = Object.keys(catalog); | |
| const match = keys.find(s => good.toLowerCase().startsWith(s.toLowerCase())); | |
| const catalogued = catalog[match]; | |
| if (!catalogued) { return "ХЗ: " + good; } | |
| return catalogued; | |
| } | |
| // Категории: | |
| // Еда | |
| // Личное | |
| // Здоровье | |
| // Животные | |
| // Хозбыт | |
| // Строй | |
| // Жильё | |
| // Телеком | |
| // Транспорт | |
| // Запас/Кредит | |
| const catalog = { | |
| "зсд": "Транспорт", | |
| "самокат": "Транспорт", | |
| "сомокат": "Транспорт", | |
| "кш": "Транспорт", | |
| "еда": "Еда", | |
| "продукты": "Еда", | |
| "человекоеда": "Еда", | |
| "морожен": "Еда", | |
| "кафе": "Еда", | |
| "тоже еда": "Еда", | |
| "бензин": "Транспорт", | |
| "мойка": "Транспорт", | |
| "электричка": "Транспорт", | |
| "электричество": "Жильё", | |
| "Жильё": "Жильё", | |
| "квартплата": "Жильё", | |
| "коммуналка": "Жильё", | |
| "квартира": "Жильё", | |
| "домик": "Жильё", | |
| "гостиница": "Жильё", | |
| "хата": "Жильё", | |
| "кусок кварт": "Жильё", | |
| "спотифай": "Личное", | |
| "хоз": "Хозбыт", | |
| "стакан": "Хозбыт", | |
| "кружка": "Хозбыт", | |
| "строй": "Строй", | |
| "умнодом": "Строй", | |
| "др": "Личное", | |
| "открытки": "Личное", | |
| "кино": "Личное", | |
| "сувенир": "Личное", | |
| "звероеда": "Животные", | |
| "животные": "Животные", | |
| "еда котам": "Животные", | |
| "птицам": "Животные", | |
| "наполнитель котам": "Животные", | |
| "кото": "Животные", | |
| "подарки": "Личное", | |
| "подарок": "Личное", | |
| "музеум": "Личное", | |
| "авто": "Транспорт", | |
| "омывайка": "Транспорт", | |
| "одлп": "Личное", | |
| "фольга": "Хозбыт", | |
| "цветочег": "Личное", | |
| "личное": "Личное", | |
| "штаны": "Личное", | |
| "ресторан": "Личное", | |
| "лента еда": "Еда", | |
| "манго": "Еда", | |
| "миндаль": "Еда", | |
| "чай": "Еда", | |
| "вода": "Еда", | |
| "шаверма": "Еда", | |
| "арбу": "Еда", | |
| "овощи": "Еда", | |
| "фрукт": "Еда", | |
| "плов": "Еда", | |
| "чаё": "Еда", | |
| "вино": "Еда", | |
| "бухло": "Еда", | |
| "шоколад": "Еда", | |
| "билет на эл": "Транспорт", | |
| "билет на по": "Транспорт", | |
| "транспондер": "Транспорт", | |
| "парковка": "Транспорт", | |
| "порковка": "Транспорт", | |
| "токси": "Транспорт", | |
| "кофе": "Еда", | |
| "букет": "Личное", | |
| "ветеринар": "Животные", | |
| "такси": "Транспорт", | |
| "таксо": "Транспорт", | |
| "транспорт": "Транспорт", | |
| "платные дороги": "Транспорт", | |
| "сомокот": "Транспорт", | |
| "интенсив": "Личное", | |
| "йота": "Телеком", | |
| "моб ": "Телеком", | |
| "телеком": "Телеком", | |
| "мобильный": "Телеком", | |
| "мтс": "Телеком", | |
| "тмобайл": "Телеком", | |
| "интернет": "Телеком", | |
| "платеж по кредит": "Запас/Кредит", | |
| "кредит": "Запас/Кредит", | |
| "запас": "Запас/Кредит", | |
| "торт": "Еда", | |
| "орешки": "Еда", | |
| "какава": "Еда", | |
| "одежда": "Личное", | |
| "аптека": "Здоровье", | |
| "здоровье": "Здоровье", | |
| "мелатонин": "Здоровье", | |
| "лекарств": "Здоровье", | |
| "психо": "Здоровье", | |
| "гло": "Личное", | |
| "стики": "Личное", | |
| "вейп": "Личное", | |
| "птен": "Животные", | |
| "билайн": "Телеком", | |
| "инет": "Телеком", | |
| "кот": "Животные", | |
| "котам": "Животные", | |
| "птиц": "Животные", | |
| "ку": "Жильё", | |
| "квартир": "Жильё", | |
| "Сказк": "личное", | |
| "благо": "личное", | |
| "лично": "личное", | |
| "лич ": "личное", | |
| "даг ": "личное", | |
| "донат": "личное", | |
| "концерт": "личное", | |
| "бензак": "транспорт", | |
| "порковка": "транспорт", | |
| "лисапед": "транспорт", | |
| "велосипед": "транспорт", | |
| "проезд": "транспорт" | |
| }; | |
| function groupBy(items, key) { | |
| const map = new Map(); | |
| items.forEach((item) => { | |
| const keyValue = item[key]; | |
| const currArr = map.has(keyValue) ? map.get(keyValue) : []; | |
| currArr.push(item); | |
| map.set(keyValue, currArr); | |
| }); | |
| return map; | |
| } | |
| </script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment