Last active
April 12, 2025 19:01
-
-
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; } | |
const actorMatch = line.match(/(\p{L}+), \[\d\d\.\d\d\.\d{4} \d\d:\d\d\]/u); | |
if (actorMatch) { | |
actor = actorMatch[1]; | |
continue; | |
} | |
const match = line.match(/^-?(\d+)\s+(.+)/u); | |
if (match) { | |
const trata = { actor: actor, cost: parseInt(match[1]), good: match[2].trim() }; | |
trataList.push(trata); | |
} | |
else { | |
const creditMatch = line.match(/^\+\s?(\d+)\s+(.+)/u); | |
if (creditMatch) { | |
creditList.push({ actor: actor, data: line.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